Verifying the safety of user pointer dereferences
Download
1 / 77

- PowerPoint PPT Presentation


  • 210 Views
  • Updated On :

Verifying the Safety of User Pointer Dereferences. Suhabe Bugrara [email protected] Stanford University Joint work with Alex Aiken. Unchecked User Pointer Dereferences. Security property of operating systems Two types of pointers in operating systems

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about '' - andrew


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
Verifying the safety of user pointer dereferences l.jpg

Verifying the Safety of User Pointer Dereferences

Suhabe Bugrara

[email protected]

Stanford University

Joint work with Alex Aiken


Unchecked user pointer dereferences l.jpg
Unchecked User Pointer Dereferences

  • Security property of operating systems

  • Two types of pointers in operating systems

    • kernel pointer: pointer created by the operating system

    • user pointer: pointer created by a user application and passed to the operating system via an entry point such as a system call

  • Must check that a user pointer points into userspace before dereferencing it


Unchecked user pointer dereferences3 l.jpg
Unchecked User PointerDereferences

1: static ssize_t read_port(…, char * __user buf, …) {

2: unsigned long i = *ppos;

3: char * __user tmp = buf;

4:


Unchecked user pointer dereferences4 l.jpg
Unchecked User PointerDereferences

1: static ssize_t read_port(…, char * __user buf, …) {

2: unsigned long i = *ppos;

3: char * __user tmp = buf;

4:

7:

8: while (count-- > 0 && i < 65536) {

9: if (__put_user(inb(i),tmp) < 0) //deref

10: return -EFAULT;

11: i++;

12: tmp++;

13: }

14:

15: *ppos = i;

16: return tmp-buf;

17: }


Unchecked user pointer dereferences5 l.jpg
Unchecked User PointerDereferences

1: static ssize_t read_port(…, char * __user buf, …) {

2: unsigned long i = *ppos;

3: char * __user tmp = buf;

4:

5: if (!access_ok(..,buf,...)) //check

6: return -EFAULT;

7:

8: while (count-- > 0 && i < 65536) {

9: if (__put_user(inb(i),tmp) < 0) //deref

10: return -EFAULT;

11: i++;

12: tmp++;

13: }

14:

15: *ppos = i;

16: return tmp-buf;

17: }


Security vulnerability l.jpg
Security Vulnerability

  • Malicious user could

    • Take control of the operating system

    • Overwrite kernel data structures

    • Read sensitive data out of kernel memory

    • Crash machine by corrupting data


Slide7 l.jpg
Goal

  • Design a program analysis to prove statically that no unchecked user pointer dereferences exist in the entire operating system


Challenges l.jpg
Challenges

  • Verification

    • provide guarantee of correctness

  • Precision

    • report low number of false alarms

  • Scalability

    • analyze more than 6 MLOC



Verification10 l.jpg
Verification

  • Soundness

    • If the program analysis reports that no vulnerabilities exist, then the program contains none


Verification11 l.jpg
Verification

  • Soundness

    • If the program analysis reports that no vulnerabilities exist, then the program contains none

  • Completeness

    • If the program analysis reports that a vulnerability exists, then program contains one


Verification12 l.jpg
Verification

  • Soundness

    • If the program analysis reports that no vulnerabilities exist, then the program contains none

  • Completeness

    • If the program analysis reports that a vulnerability exists, then program contains one

  • Impossible for a program analysis to be both sound and complete


Sound and incomplete verifier l.jpg
Sound and Incomplete Verifier

  • Proves the absence of vulnerabilities

  • May report false alarms


Soundness caveats l.jpg
Soundness Caveats

  • Unsafe memory operations

  • Concurrency

  • Inline assembly

  • Analysis fails to analyze some procedures


Precision l.jpg
Precision

  • Minimize the number of false alarms

  • Reasoning more deeply about program

  • Computationally expensive

  • High precision inhibits scalability


Example l.jpg
Example

1: void sys_call (int *u, const int cmd) { //u is user pointer

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) { //check u

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u; //dereference u

12: }


One possible approach l.jpg
One Possible Approach

1: void sys_call (int *u, const int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: }

(*u,user)


One possible approach18 l.jpg
One Possible Approach

1: void sys_call (int *u, const int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: }

(*u,user)

(*u,user)


One possible approach19 l.jpg
One Possible Approach

1: void sys_call (int *u, const int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: }

(*u,user)

(*u,user)

(*u,user)


One possible approach20 l.jpg
One Possible Approach

1: void sys_call (int *u, const int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: }

(*u,user)

(*u,user)

(*u,user)

(*u,user)

(*u,checked)


One possible approach21 l.jpg
One Possible Approach

1: void sys_call (int *u, const int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: }

(*u,user)

(*u,user)

(*u,user)

(*u,user)

(*u,checked)

(*u,user) lost precision!


One possible approach22 l.jpg
One Possible Approach

1: void sys_call (int *u, const int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: }

(*u,user)

(*u,user)

(*u,user)

(*u,user)

(*u,checked)

(*u,user) lost precision!

(*u,user)

(*u,error) emit warning!

…, but, procedure does not contain any vulnerabilities!


Path sensitivity l.jpg
Path Sensitivity

  • Ability to reason about branch correlations

  • Programs use substantial amount of branch correlation in practice

  • Important for reducing the number of false alarms


Example24 l.jpg
Example

1: void sys_call (int *u, int cmd) { //u is user pointer

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) { //check u

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u; //dereference u

12: }


Path sensitivity25 l.jpg
Path Sensitivity

1: void sys_call (int *u, int cmd) { //u is user pointer

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) { //check u

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u; //dereference u

12: }

Valid Path


Path sensitivity26 l.jpg
Path Sensitivity

1: void sys_call (int *u, const int cmd) { //u is user pointer

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) { //check u

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u; //dereference u

12: }

Valid Path


Path sensitivity27 l.jpg
Path Sensitivity

1: void sys_call (int *u, const int cmd) { //u is user pointer

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) { //check u

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u; //dereference u

12: }

Valid Path


Path sensitivity28 l.jpg
Path Sensitivity

1: void sys_call (int *u, const int cmd) { //u is user pointer

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) { //check u

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u; //dereference u

12: }

Invalid Path!


Path sensitive analysis l.jpg
Path Sensitive Analysis

1: void sys_call (int *u, const int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: }


Path sensitive analysis30 l.jpg
Path Sensitive Analysis

1: void sys_call (int *u, const int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: }

(*u,user)  true


Path sensitive analysis31 l.jpg
Path Sensitive Analysis

“guard”

1: void sys_call (int *u, const int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: }

(*u,user)  true


Path sensitive analysis32 l.jpg
Path Sensitive Analysis

1: void sys_call (int *u, const int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: }

(*u,user)  true

(*u,user)  true


Path sensitive analysis33 l.jpg
Path Sensitive Analysis

1: void sys_call (int *u, const int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: }

(*u,user)  true

(*u,user)  true

(*u,user)  true


Path sensitive analysis34 l.jpg
Path Sensitive Analysis

1: void sys_call (int *u, const int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: }

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,checked)  cmd == 1


Path sensitive analysis35 l.jpg
Path Sensitive Analysis

1: void sys_call (int *u, const int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: }

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,checked)  cmd == 1

(*u,user)  true

(*u,checked)  cmd == 1


Path sensitive analysis36 l.jpg
Path Sensitive Analysis

1: void sys_call (int *u, const int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: }

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,checked)  cmd == 1

(*u,user)  true

(*u,checked)  cmd == 1

(*u,user)  true

(*u,checked)  cmd == 1

(*u,error)  . . .


Path sensitive analysis37 l.jpg
Path Sensitive Analysis

1: void sys_call (int *u, const int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: }

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,checked)  cmd == 1

(*u,user)  true

(*u,checked)  cmd == 1

(*u,user)  true

(*u,checked)  cmd == 1

(*u,error)  cmd == 1 && . . .


Path sensitive analysis38 l.jpg
Path Sensitive Analysis

1: void sys_call (int *u, const int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: }

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,checked)  cmd == 1

(*u,user)  true

(*u,checked)  cmd == 1

(*u,user)  true

(*u,checked)  cmd == 1

(*u,error)  cmd == 1 && !(cmd == 1) && . . .


Path sensitive analysis39 l.jpg
Path Sensitive Analysis

1: void sys_call (int *u, const int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: }

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,checked)  cmd == 1

(*u,user)  true

(*u,checked)  cmd == 1

(*u,user)  true

(*u,checked)  cmd == 1

(*u,error)  cmd == 1 && !(cmd == 1) && true

. . .


Path sensitive analysis40 l.jpg
Path Sensitive Analysis

1: void sys_call (int *u, const int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: }

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,checked)  cmd == 1

(*u,user)  true

(*u,checked)  cmd == 1

(*u,user)  true

(*u,checked)  cmd == 1

(*u,error)  cmd == 1 && !(cmd == 1) && true

 false


Path sensitive analysis41 l.jpg
Path Sensitive Analysis

1: void sys_call (int *u, const int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: }

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,checked)  cmd == 1

(*u,user)  true

(*u,checked)  cmd == 1

(*u,user)  true

(*u,checked)  cmd == 1

(*u,error)  false


Path sensitive analysis42 l.jpg
Path Sensitive Analysis

1: void sys_call (int *u, const int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: }

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,checked)  cmd == 1

(*u,user)  true

(*u,checked)  cmd == 1

(*u,user)  true

(*u,checked)  cmd == 1

(*u,error)  false


Scalability l.jpg
Scalability

  • Abstraction

    • Throw away guards at procedure boundaries

  • Compositionality

    • Analyze each procedure in isolation


Path sensitive analysis44 l.jpg
Path Sensitive Analysis

1: void sys_call (int *u, const int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: }

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,checked)  cmd == 1

(*u,user)  true

(*u,checked)  cmd == 1

(*u,user)  true

(*u,checked)  cmd == 1

(*u,error)  false


Abstraction l.jpg
Abstraction

(*u,user)  true

(*u,checked)  cmd == 1

(*u,error)  false

initial summary


Abstraction46 l.jpg
Abstraction

α

=

(*u,user)  true

(*u,checked)  cmd == 1

(*u,error)  false

abstraction function

initial summary


Abstraction47 l.jpg
Abstraction

α

=

(*u,user)  true

(*u,checked)  cmd == 1

(*u,error)  false

(*u,user)  true

(*u,checked)  false

(*u,error)  false

abstraction function

initial summary

final

summary


Abstraction48 l.jpg
Abstraction

1: void sys_call (int *u, const int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: }

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,checked)  cmd == 1

(*u,user)  true

(*u,checked)  cmd == 1

(*u,user)  true

(*u,checked)  cmd == 1

(*u,error)  false


Abstraction49 l.jpg
Abstraction

1: void sys_call (int *u, const int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: }

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,checked)  cmd == 1

(*u,user)  true

(*u,checked)  cmd == 1

(*u,user)  true

(*u,checked)  false

(*u,error)  false


Compositionality l.jpg
Compositionality

1: int get (int *v) {

2: int x;

3:

4: x = *v;

5:

6: return x;

7: }


Compositionality51 l.jpg
Compositionality

1: int get (int *v) {

2: int x;

3:

4: x = *v;

5:

6: return x;

7: }

(*v,user)  c1


Compositionality52 l.jpg
Compositionality

“context variable”

1: int get (int *v) {

2: int x;

3:

4: x = *v;

5:

6: return x;

7: }

(*v,user)  c1


Compositionality53 l.jpg
Compositionality

1: int get (int *v) {

2: int x;

3:

4: x = *v;

5:

6: return x;

7: }

(*v,user)  c1

(*v,user)  c1


Compositionality54 l.jpg
Compositionality

1: int get (int *v) {

2: int x;

3:

4: x = *v;

5:

6: return x;

7: }

(*v,user)  c1

(*v,user)  c1

(*v,user)  c1

(*v,error)  c1


Compositionality55 l.jpg
Compositionality

1: int get (int *v) {

2: int x;

3:

4: x = *v;

5:

6: return x;

7: }

(*v,user)  c1

(*v,user)  c1

(*v,user)  c1

(*v,error)  c1


Fixed point computation l.jpg
Fixed Point Computation

  • Generate summary of behavior for each procedure with respect to calling context

  • Apply summary of callee at call site in caller

  • Repeatedly generate and apply summaries until a fixed point is reached


Analysis passes l.jpg
Analysis Passes

  • Alias analysis

    • computes memory model for each procedure


Analysis passes58 l.jpg
Analysis Passes

  • Alias analysis

    • computes memory model for each procedure

  • User state propagation

    • propagates user states throughout OS


Analysis passes59 l.jpg
Analysis Passes

  • Alias analysis

    • computes memory model for each procedure

  • User state propagation

    • propagates user states throughout OS

  • Unchecked and safety state propagation

    • determines safety of each dereference site




Results l.jpg
Results

  • Verified automatically

    • 616 out of 627 system call parameters (98.2 %)

    • 851,686 out of 852,092 dereferences (99.95%)

  • Warnings

    • 11 warnings on system call parameters

    • 406 warnings on dereferences

    • 22 annotations required to verify


False alarm interprocedural must modify l.jpg
False Alarm: Interprocedural Must-Modify

1: int verify_iovec (struct msghdr *m, ..., char *address, int mode)

2: {

3: int err;

4:

5: if (m->msg_namelen) {

6: if (mode == VERIFY_READ) {

7: err = move_addr_to_kernel (m->msg_name,

8: m->msg_namelen,

9: address);

10: if (err < 0) return err;

11: }

12:

13: m->msg_name = address;

14: } else {

15: m->msg_name = NULL;

16: }

17: ...

18: }


False alarm interprocedural must modify64 l.jpg
False Alarm: Interprocedural Must-Modify

1: int verify_iovec (struct msghdr *m, ..., char *address, int mode)

2: {

3: int err;

4:

5: if (m->msg_namelen) {

6: if (mode == VERIFY_READ) {

7: err = move_addr_to_kernel (m->msg_name,

8: m->msg_namelen,

9: address);

10: if (err < 0) return err;

11: }

12:

13: m->msg_name = address;

14: } else {

15: m->msg_name = NULL;

16: }

17: ...

18: }


False alarm interprocedural must modify65 l.jpg
False Alarm: Interprocedural Must-Modify

1: int verify_iovec (struct msghdr *m, ..., char *address, int mode)

2: {

3: int err;

4:

5: if (m->msg_namelen) {

6: if (mode == VERIFY_READ) {

7: err = move_addr_to_kernel (m->msg_name,

8: m->msg_namelen,

9: address);

10: if (err < 0) return err;

11: }

12:

13: m->msg_name = address;

14: } else {

15: m->msg_name = NULL;

16: }

17: ...

18: }


False alarm interprocedural must modify66 l.jpg
False Alarm: Interprocedural Must-Modify

1: int verify_iovec (struct msghdr *m, ..., char *address, int mode)

2: {

3: int err;

4:

5: if (m->msg_namelen) {

6: if (mode == VERIFY_READ) {

7: err = move_addr_to_kernel (m->msg_name,

8: m->msg_namelen,

9: address);

10: if (err < 0) return err;

11: }

12:

13: m->msg_name = address;

14: } else {

15: m->msg_name = NULL;

16: }

17: ...

18: }

m->msg_name

must-modified under

!(m->msg_namelen &&

mode == VERIFY_READ &&

err < 0)


False alarm interprocedural branch correlation l.jpg
False Alarm:Interprocedural Branch Correlation

1: int sound_ioctl(uint cmd, ulong arg) {

2:

3: if (_SIOC_DIR(cmd) != _SIOC_NONE &&

4: _SIOC_DIR(cmd) != 0)

5:

6: if(_SIOC_DIR(cmd)&_SIOC_WRITE)

7: if (!access_ok(arg))

8: return -EFAULT;

9:

10: ...

11: return sound_mixer_ioctl(cmd, arg);

12: }

13: int sound_mixer_ioctl(uint cmd, void *arg)

14: {

15: ...

16: return aci_mixer_ioctl(cmd, arg);

17: }

18:

19:

20: int aci_mixer_ioctl(uint cmd, void *arg)

21: {

22: switch(cmd)

23: case SOUND_MIXER_WRITE_IGAIN:

24: ...*arg...;

25: ...

26: }


False alarm interprocedural branch correlation68 l.jpg
False Alarm:Interprocedural Branch Correlation

1: int sound_ioctl(uint cmd, ulong arg) {

2:

3: if (_SIOC_DIR(cmd) != _SIOC_NONE &&

4: _SIOC_DIR(cmd) != 0)

5:

6: if(_SIOC_DIR(cmd)&_SIOC_WRITE)

7: if (!access_ok(arg))

8: return -EFAULT;

9:

10: ...

11: return sound_mixer_ioctl(cmd, arg);

12: }

13: int sound_mixer_ioctl(uint cmd, void *arg)

14: {

15: ...

16: return aci_mixer_ioctl(cmd, arg);

17: }

18:

19:

20: int aci_mixer_ioctl(uint cmd, void *arg)

21: {

22: switch(cmd)

23: case SOUND_MIXER_WRITE_IGAIN:

24: ...*arg...;

25: ...

26: }

1


False alarm interprocedural branch correlation69 l.jpg
False Alarm:Interprocedural Branch Correlation

1: int sound_ioctl(uint cmd, ulong arg) {

2:

3: if (_SIOC_DIR(cmd) != _SIOC_NONE &&

4: _SIOC_DIR(cmd) != 0)

5:

6: if(_SIOC_DIR(cmd)&_SIOC_WRITE)

7: if (!access_ok(arg))

8: return -EFAULT;

9:

10: ...

11: return sound_mixer_ioctl(cmd, arg);

12: }

13: int sound_mixer_ioctl(uint cmd, void *arg)

14: {

15: ...

16: return aci_mixer_ioctl(cmd, arg);

17: }

18:

19:

20: int aci_mixer_ioctl(uint cmd, void *arg)

21: {

22: switch(cmd)

23: case SOUND_MIXER_WRITE_IGAIN:

24: ...*arg...;

25: ...

26: }

1

1. *arg

checked under condition

_SIOC_DIR(cmd) != _SIOC_NONE && _SIOC_DIR(cmd) != 0 && _SIOC_DIR(cmd)&_SIOC_WRITE


False alarm interprocedural branch correlation70 l.jpg
False Alarm:Interprocedural Branch Correlation

1: int sound_ioctl(uint cmd, ulong arg) {

2:

3: if (_SIOC_DIR(cmd) != _SIOC_NONE &&

4: _SIOC_DIR(cmd) != 0)

5:

6: if(_SIOC_DIR(cmd)&_SIOC_WRITE)

7: if (!access_ok(arg))

8: return -EFAULT;

9:

10: ...

11: return sound_mixer_ioctl(cmd, arg);

12: }

13: int sound_mixer_ioctl(uint cmd, void *arg)

14: {

15: ...

16: return aci_mixer_ioctl(cmd, arg);

17: }

18:

19:

20: int aci_mixer_ioctl(uint cmd, void *arg)

21: {

22: switch(cmd)

23: case SOUND_MIXER_WRITE_IGAIN:

24: ...*arg...;

25: ...

26: }

1

2

1. *arg

checked under condition

_SIOC_DIR(cmd) != _SIOC_NONE && _SIOC_DIR(cmd) != 0 && _SIOC_DIR(cmd)&_SIOC_WRITE


False alarm interprocedural branch correlation71 l.jpg
False Alarm:Interprocedural Branch Correlation

1: int sound_ioctl(uint cmd, ulong arg) {

2:

3: if (_SIOC_DIR(cmd) != _SIOC_NONE &&

4: _SIOC_DIR(cmd) != 0)

5:

6: if(_SIOC_DIR(cmd)&_SIOC_WRITE)

7: if (!access_ok(arg))

8: return -EFAULT;

9:

10: ...

11: return sound_mixer_ioctl(cmd, arg);

12: }

13: int sound_mixer_ioctl(uint cmd, void *arg)

14: {

15: ...

16: return aci_mixer_ioctl(cmd, arg);

17: }

18:

19:

20: int aci_mixer_ioctl(uint cmd, void *arg)

21: {

22: switch(cmd)

23: case SOUND_MIXER_WRITE_IGAIN:

24: ...*arg...;

25: ...

26: }

1

2

1. *arg

checked under condition

_SIOC_DIR(cmd) != _SIOC_NONE && _SIOC_DIR(cmd) != 0 && _SIOC_DIR(cmd)&_SIOC_WRITE

2. cmd == SOUND_MIXER_WRITE_IGAIN

implies

_SIOC_DIR(cmd) != _SIOC_NONE && _SIOC_DIR(cmd) != 0 && _SIOC_DIR(cmd)&_SIOC_WRITE


False alarm function pointers l.jpg
False Alarm:Function Pointers

1: struct { char *name; ...} map[] = ...,

2: {[NFSCTL_GETFD] = {.name = ".getfd", ...},

3: [NFSCTL_GETFS] = {.name = ".getfs", ...},};

4:

5: long sys_nfsservctl (int cmd, ..., void *res) {

6: ...

7: struct file *file = do_open(map[cmd].name);

8: ...

9: int err = file->f_op->read(file, res, ...);

10: ...

11: }


False alarm function pointers73 l.jpg
False Alarm:Function Pointers

1: int notifier_call_chain(struct notifier_block **nl, ulong val, void *v)

2: {

3: int ret = NOTIFY_DONE;

4: struct notifier_block *nb;

5:

6: nb = *nl;

7:

8: while (nb) {

9: ret = nb->notifier_call(nb, val, v);

10: ...

11: nb = nb->next;

12: }

13:

14: return ret;

15: }


Related work l.jpg
Related Work

  • MECA, by Yang, Kremenek, Xie, Engler

    • bug finder, path-insensitive, Linux, automatic

  • Sparse, by Torvalds

    • bug finder, path-insensitive, Linux, 10,000 annotations

  • CQual, by Johnson, Wagner

    • verifier, path-insensitive, Linux, automatic, 300 KLOC

  • ESP, by Dor, Adams, Das, Yang

    • verifier, path-sensitive, Windows, automatic, 1 MLOC


Future work l.jpg
Future Work

  • Eliminate the time outs on procedures

  • Handle inline assembly statements

  • Reduce number of false alarms


Conclusions l.jpg
Conclusions

  • Nearly verifying important security property

  • Scaling to largest open source program

  • Reporting low number of false alarms



ad