/
Static Detection of Event-based Races in Android App Static Detection of Event-based Races in Android App

Static Detection of Event-based Races in Android App - PowerPoint Presentation

SmoochieBoochie
SmoochieBoochie . @SmoochieBoochie
Follow
343 views
Uploaded On 2022-08-01

Static Detection of Event-based Races in Android App - PPT Presentation

Yongjian Hu Univ of California Riverside Iulian Neamtiu NJIT Motivation Rise of EventDriven Systems Concurrency is a Serious Issue 66 of highseverity Android bugs are due to concurrency Zhou et al EASE15 ID: 931441

action msg int handler msg action handler int message void race sensitivity misrunning context false static event source case

Share:

Link:

Embed:

Download Presentation from below link

Download Presentation The PPT/PDF document "Static Detection of Event-based Races in..." is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.


Presentation Transcript

Slide1

Static Detection of Event-based Races in Android App

Yongjian HuUniv. of California, Riverside

Iulian Neamtiu

NJIT

Slide2

Motivation

Rise of Event-Driven Systems

Concurrency is a Serious Issue

66% of high-severity Android bugs are due to concurrency [Zhou et al., EASE’15]

84% of Android race bugs are event-driven races [Bielik et al., OOPSLA’15; Hsial et al. PLDI’14; Maiya et al., PLDI’14]

Mobile apps

Web apps

Data centers

Slide3

Concurrency Error Example

class MainActivity {

DataBase

mDB;

BroadcastReceiver recv

=

new BroadcastReceiver() { void

onReceive(Context ctx

, Intent i) {

Bundle b =

i.getExtras

(); mDB.update(b); } } void onCreate(...) { mDB = new DataBase(); registerReceiver(recv, ...); } void onStart() { mDB.open(); } void onStop() { mDB.close(); } void onDestroy() { unregisterReceiver(recv); mDB = null; }}

Main Thread

Broadcast Receiver

onCreate

()

register

unregister

update

onStart

()

onReceive

()

onStop

()

onDestroy

()

update()

before

close()OK

not ordered

Slide4

Concurrency Error Example

class MainActivity {

DataBase

mDB;

BroadcastReceiver recv

=

new BroadcastReceiver() { void

onReceive(Context ctx

, Intent i) {

Bundle b =

i.getExtras

(); mDB.update(b); } } void onCreate(...) { mDB = new DataBase(); registerReceiver(recv, ...); } void onStart() { mDB.open(); } void onStop() { mDB.close(); } void onDestroy() { unregisterReceiver(recv); mDB = null; }}

Main Thread

Broadcast Receiver

onCreate

()

register

unregister

update

onStart

()

onReceive

()

onStop

()

onDestroy

()

update()

after

close()Exception!

not ordered

Slide5

State-of-the-art in (Android) Race Detection

Prior Android race detectors: all are dynamic

DroidRacer

[

Maiya et al., PLDI’14]; CAFA [Hsiao et al., PLDI’14]; EventRacer [Bielik et al., OOPSLA’15]LimitationsCoverage issues

→ False negatives; “no run - no see”False positives (imprecise Android modeling)

Static race detection is hard [Hong and Kim, STVR’15]Only 7 out of 43 detectors are static“the accuracy of [static] models is often low because of the imprecision inherent to static analysis methods”

Slide6

Our Approach

SIERRA

: the first

static, sound

event-driven race detector for Android appsHighly effectiveFinds 29 true races per app vs. 4 (best dynamic detector)EfficientAnalyzes an app in 31 minutes on average

Slide7

SIERRA: StatI

c Event-based Race detectoR for Android

App

Analysis booster

Hybrid

Context

Selector

Call Graph Builder

PA Refiner

Pointer

Analysis

Static HB Graph

Race ReportsRace <rw1,rw1’>Race <rw2,rw2’>. . .

Path/Context Sensitivity Refutation

Race Prioritization

WALA

THRESHER

Building HB Graph

Race Refinement

Race Reporting

Slide8

Event Race Definition

Action = context-sensitive event handlingNovel abstraction, reifies

Callbacks (lifecycle, GUI callbacks, etc.)

Thread,

AsyncTask, ExecutorHandler’s SendMessage and PostRunnableHappens-before (HB): A1 ≺ A2A1 is completed before A2

Event race = “racy” pair of memory accessesAccess same location: α(x) = α(y)At least one access is write: α(x):Write ꓦ α(y):Write

Access from two actions: θ(x) = A1 ꓥ θ(y) = A2 ꓥ A1 ≠ A2

No HB between two actions: A1 ⊀ A2 ꓥ A2 ⊀ A1

Slide9

“Boosting” Static Analysis with

Fixpoint-based Callgraph Construction

Manifest.xml

lists all the activities

For each activity:Find lifecycle callbacks, e.g., onCreate

, onStartFind XML registered callbacks, e.g.,

onClickFind system callbacks, e.g.,

onLowMemoryBuild call graph for found actionsFind and add to work list registered UI callbacks, e.g.,

onItemClick, onLongPressAdded to work list if new actions found

Go back to step 4. Iterate until fixpoint

onCreate

onStart

onResumeonClick

onCreateOptionsMenu

onLow

Memory

thread

AsyncTask

onPost

Execution

msg1.

handleMessage

Runnable1

onItemClick

onLongPress

Runnable2

……

……

Slide10

Action Sensitivity: When Context Sensitivity is Insufficient

Hybrid context sensitivity [Kastrinis et al., PLDI’13]K object sensitivity for dispatch invocations

K call-site sensitivity for static invocations

a

Base64.encodeBytes(byte[] source)

Base64.encodeBytes(byte[] source,

int

offset,

int

length,

int

options)

Base64.encodeBytesToBytes(byte[] source, int offset, int length, int options) { …… os = new OutputStream(…); os.write(…);}Action1c1:

c2:

c3:

Points-to(<[c2::c3],

os>) = {<[c2::c3], new OutputStream

>}Event1:WRITE: <[c2::c3], os>READ: <[c2::c3],

os>

Points-to(<[c2::c3], os>) = {<[c2::c3], new OutputStream>}Event2:

WRITE: <[c2::c3], os>READ: <[c2::c3], os>

Base64.encodeBytes(byte[] source)

Base64.encodeBytes(byte[] source,

int

offset,

int

length,

int

options)

Base64.encodeBytesToBytes(byte[] source,

int

offset,

int

length, int options) { …… os

= new

OutputStream

(…);

os.write

(…);

}

Action2

c1’:

c2:

c3:

Conflated → Imprecise → False positive

K=2

Slide11

Action Sensitivity: When Context Sensitivity is Insufficient

Hybrid context sensitivity [Kastrinis et al., PLDI’13]K object sensitivity for dispatch invocations

K call-site sensitivity for static invocations

We add

Action sensitivity

Base64.encodeBytes(byte[] source)

Base64.encodeBytes(byte[] source,

int

offset,

int

length,

int

options)Base64.encodeBytesToBytes(byte[] source, int offset, int length, int options) { …… os = new OutputStream(…); os.write(…);}Action1c1:

c2:

c3:

Points-to (<[c2::c3

@a1],

os>) = {<[c2::c3@a1], new OutputStream>}

Event1:WRITE: <[c2::c3@a1], os>READ: <[c2::c3@a1], os>

Points-to(<[c2::c3

@a2], os>) = {<[c2::c3

@a2], new OutputStream>}Event2:WRITE: <[c2::c3

@a2], os>READ: <[c2::c3

@a2], os>

Base64.encodeBytes(byte[] source)

Base64.encodeBytes(byte[] source,

int

offset,

int

length,

int options)

Base64.encodeBytesToBytes(byte[] source, int offset, int

length, int options) { …… os = new OutputStream(…);

os.write(…);}

Action2

c1’:

c2:

c3:

No race

Slide12

Happens-before Rules

e

1

e

2

Method M

A

1

A

2

<

dom

Δe1Δe2A1≺A2

Action invocation rule (sender ≺ receiver) Component lifecycle rule

GUI layout/object orderIntra-procedural dominationIntra-action, inter-procedural dominationInter-action transitivity

Transitivity

onResume()

onPause()

*

onClick1()

onClick2()

onClick3()

onResume

onClick1

onResume

onClick2

onClick2

onClick3

Slide13

Symbolic Execution-based Refutation

So far, the analysis is…Context sensitiveField sensitive

Path insensitive

and discovers 22% of all possible actions orders Which is not bad!Next, we use symbolic execution-based refutation to further order accessesBonus: on-demand path sensitivity!

Slide14

Example

Path

Constraints

Backward symbolic execution

mIsRunning

= true

if (

mIsRunning

)

Method entry

if (*)

Method exit

PostDelayedmIsRunning = falsemAccumTime = …

mIsRunning

= false

mIsRunning

= false

true

if (

mIsRunning

)

mIsRunning

= false

mAccumTime

= …

OpenSudoku

app

Can 𝜶A occur before 𝜶B?

Timer.Runnable runner = {void run() {//action

A if (mIsRunning) { mAccumTime=... // 𝜶

A if (*) { ... postDelayed

(runner,...); } else mIsRunning

=false; }}}void stop(){// action

B if (mIsRunning) {

mIsRunning

= false;

mAccumTime

=... // 𝜶

B

}

}

Yes!

Slide15

Example

Path

Constraints

Backward symbolic execution

mIsRunning

= true

if (

mIsRunning

)

mAccumTime

= …

mIsRunning

= false

mIsRunning = false

if (

mIsRunning

)Method entry

Method exit

true

mIsRunning = falsemAccumTime

= …

Race Refuted!

Can

𝜶B occur before 𝜶

A? Timer.Runnable

runner = {void run() {//action

A if (mIsRunning) { mAccumTime=... //

𝜶A if (*) { ... postDelayed

(runner,...); } else mIsRunning=false; }}}

void stop(){// action B if (mIsRunning) {

mIsRunning = false; mAccumTime=... // 𝜶

B }}

No!

Slide16

Evaluation

Best priorwork (dynamic)

Basic static analysis (CG,PA)

HB construction

Symbolic Execution

Total

1,310

29

560

1,899

Efficiency (median time, in seconds)

App

Installs(millions)ActionsHB edgesRacy pairsAfter action sensitivityAfter refu- tationTrue racesFalse posi-tivesEvent RacerBarcode Scanner> 1001362,756 (30%)642415114

7VLC

> 1001512,349 (20%)202

7835323

0FB Reader> 10

2594,710 (14%)836

28510693135

K-9> 53125,725 (12%)

1,3473708972

171NPR> 1

490

10,673 (9%)607

13221210

3Across 20

apps1602,755 (22%)43180

332944

≫Effectiveness: races found

Dataset: 194 open-source apps; 20 analyzed manuallyLimitation: bound #paths to 5,000 while still sound (report race, might be false positives)

Slide17

Conclusions

Event-based races: most prevalent concurrency errors in AndroidPrior approaches: all dynamicLow coverage, false negatives, false positives

Our approach

First fully static event-based race detector

Novel action sensitive context abstractionStatic happens-before relationStatic backward symbolic execution to refute false racesHighly effective; efficient

Slide18

Backup

Slide19

Race Prioritization

PriorityHigh priorityRaces in app codeNormal priorityRaces in framework but invoked from app code

Low priority

Purely framework race

Report race ifWitness feasible paths from alternative schedulesCannot refute (to preserve soundness)E.g., Out Of Memory, max paths limit, max time limit (1,500 sec.)Potential false positive

Slide20

Context Sensitivity(cont’d)

Object insensitive = imprecision

void

onTouchEvent

(

MotionEvent e1,

MotionEvent e2) { ……

if (e1.getX() – e2.getX() > 120.0f …) { Message msg

= new Message(); msg.what = FLING;

……

this.handler.sendMessage

(

msg); } else { Message msg = new Message(); msg.what = LONG_PRESS; …… this.handler.sendMessage(msg); }}Handler handler = new Handler() { public void handleMessage(Message msg) { …… switch (msg.what) { case FLING: …… case LONG_PRESS: …… } }}

MERGED

O1:

Slide21

Context Sensitivity(cont’d)

Object sensitivity in SIERRA = precision

void

onTouchEvent

(MotionEvent

e1, MotionEvent e2) {

…… if (e1.getX() – e2.getX() > 120.0f …) {

Message msg = new Message();

msg.what = FLING; ……

this.handler.sendMessage(

msg

);

} else { Message msg = new Message(); msg.what = LONG_PRESS; …… this.handler.sendMessage(msg); }}Handler handler = new Handler() { public void handleMessage(Message msg) { …… switch (msg.what) { case FLING: …… case LONG_PRESS: …… } }}

Handler handler = new Handler() {

public void handleMessage(Message msg) {

…… switch (msg.what) {

case FLING: …… case LONG_PRESS: ……

} }}

C1:

C2:O

h:K-obj

+ 1-call-site for event posting and message passing

ctx

:<o

h,c1>

ctx

:<oh

,c2>

Slide22

Happens-before Rules

Rule 1: Action invocation ruleThe sender action happens-before the recipientRule 2: Component lifecycle rule

Activity.onCreate

<

Activity.onStartActivity.onStart < Activity.onStop……Rule 3: GUI layout/object orderActivity.onResume <

View.onClick < Activity.onPause

Slide23

Happens-before Rules (cont’d)

e

1

e

2

Method M

A

1

A

2

<

dom

Δe1Δe2<HBRule 4: Intra-procedural dominationMethod M in action A has two action posts: e1

and e2e1 dominates e2: e

1 <dom e2Δe1 ≤ Δ

e2, Δ is post delayed timeRule 5: Intra-action, inter-procedural dominationMethod M1 Action A, M2 Action A

Action posts: e1 , e2 e1

dominates e2Δe1 ≤ Δe

2, Δ is post delayed timeRule 6: Inter-action transitivityAction A1 < A2A1→post A3, A

2→post A4Rule 7: TransitivityA1

< A2 ꓥ A2 < A3 A1 < A3

A1→post A3, A2→post A

4

 

Slide24

Context Sensitivity(cont’d)

Object insensitive = imprecision

void

onTouchEvent

(

MotionEvent e1,

MotionEvent e2) { ……

if (e1.getX() – e2.getX() > 120.0f …) { Message msg

= new Message(); msg.what = FLING;

……

this.handler.sendMessage

(

msg); } else { Message msg = new Message(); msg.what = LONG_PRESS; …… this.handler.sendMessage(msg); }}Handler handler = new Handler() { public void handleMessage(Message msg) { …… switch (msg.what) { case FLING: …… case LONG_PRESS: …… } }}

MERGED

O1:

Slide25

Context Sensitivity(cont’d)

Object sensitivity in SIERRA = precision

void

onTouchEvent

(MotionEvent

e1, MotionEvent e2) {

…… if (e1.getX() – e2.getX() > 120.0f …) {

Message msg = new Message();

msg.what = FLING; ……

this.handler.sendMessage(

msg

);

} else { Message msg = new Message(); msg.what = LONG_PRESS; …… this.handler.sendMessage(msg); }}Handler handler = new Handler() { public void handleMessage(Message msg) { …… switch (msg.what) { case FLING: …… case LONG_PRESS: …… } }}

Handler handler = new Handler() {

public void handleMessage(Message msg) {

…… switch (msg.what) {

case FLING: …… case LONG_PRESS: ……

} }}

C1:

C2:O

h:K-obj

+ 1-call-site for event posting and message passing

ctx

:<o

h,c1>

ctx

:<oh

,c2>

Slide26

Context Sensitivity (cont’d)

SIERRA’s hybrid context sensitivity<k-obj + action> for normal dispatch methods<k-cfa

+ action> for static methods

<k-

obj + 1-call-site + action> for event posting and message passingSingletonContextFor singleton design patternUse global context instead of adding action sensitivityInflatedViewContextInvoked via

View.findViewById(int viewId

)Use viewId as context item

Slide27

Happens-before Rules

Rule 1: Action invocation ruleThe sender action happens-before the recipientRule 2: Component lifecycle rule

Activity.onCreate

<

Activity.onStartActivity.onStart < Activity.onStop……Rule 3: GUI layout/object orderActivity.onResume <

View.onClick < Activity.onPause

Slide28

Happens-before Rules (cont’d)

e

1

e

2

Method M

A

1

A

2

<

dom

Δe1Δe2<HBRule 4: Intra-procedural dominationMethod M in action A has two action posts: e1

and e2e1 dominates e2: e

1 <dom e2Δe1 ≤ Δ

e2, Δ is post delayed timeRule 5: Intra-action, inter-procedural dominationMethod M1 Action A, M2 Action A

Action posts: e1 , e2 e1

dominates e2Δe1 ≤ Δe

2, Δ is post delayed timeRule 6: Inter-action transitivityAction A1 < A2A1→post A3, A

2→post A4Rule 7: TransitivityA1

< A2 ꓥ A2 < A3 A1 < A3

A1→post A3, A2→post A

4

 

Slide29

Concurrency Error, Example 1

Intra-component Race

Image overridden!

Slide30

Concurrency Error, Example 2

Inter-component Race

update()

before

close()

:

OK

Slide31

Concurrency Error, Example 2

Inter-component Race

update()

after

close()

:

Exception!

Slide32

“Boosting” Static Analysis with Fixpoint

-based Callgraph Construction

Manifest.xml lists all the activities

For each activity:

Find lifecycle callbacks, e.g., onCreate, onStartFind XML registered callbacks, e.g.,

onClickFind system callbacks, e.g.,

onLowMemoryBuild call graph for found actions

Find and add to work list registered UI callbacks, e.g., onItemClick, onLongPress

Added to work list if new actions foundGo back to step 4. Iterate until fixpoint

onCreate

onStart

onResume

onClickonCreateOptionsMenuonLowMemory

thread

AsyncTask

onPost

Execution

msg1.

handleMessage

Runnable1

onItemClick

onLongPress

Runnable2

……

……

onCreate

onStart

onResume

onClick

onCreate

OptionsMenu

onLow

Memory

thread

AsyncTask

onPost

Execution

msg1.

handleMessage

Runnable1

onItemClick

onLongPress

Runnable2

*

*

Prior Android static analyses: imprecise