Presentation is loading. Please wait.

Presentation is loading. Please wait.

Verifying the Safety of User Pointer Dereferences

Similar presentations


Presentation on theme: "Verifying the Safety of User Pointer Dereferences"— Presentation transcript:

1 Verifying the Safety of User Pointer Dereferences
Suhabe Bugrara Stanford University Joint work with Alex Aiken

2 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

3 Unchecked User Pointer Dereferences
1: static ssize_t read_port(…, char * __user buf, …) { 2: unsigned long i = *ppos; 3: char * __user tmp = buf; 4:

4 Unchecked User Pointer Dereferences
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: }

5 Unchecked User Pointer Dereferences
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: }

6 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

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

8 Challenges Verification Precision Scalability
provide guarantee of correctness Precision report low number of false alarms Scalability analyze more than 6 MLOC

9 Verification

10 Verification Soundness
If the program analysis reports that no vulnerabilities exist, then the program contains none

11 Verification Soundness Completeness
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

12 Verification Soundness Completeness
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

13 Sound and Incomplete Verifier
Proves the absence of vulnerabilities May report false alarms

14 Soundness Caveats Unsafe memory operations Concurrency Inline assembly
Analysis fails to analyze some procedures

15 Precision Minimize the number of false alarms
Reasoning more deeply about program Computationally expensive High precision inhibits scalability

16 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: }

17 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)

18 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)

19 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)

20 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)

21 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!

22 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!

23 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

24 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: }

25 Path Sensitivity Valid Path
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

26 Path Sensitivity Valid Path
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

27 Path Sensitivity Valid Path
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

28 Path Sensitivity Invalid Path!
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!

29 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: }

30 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

31 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

32 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

33 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

34 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

35 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

36 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)  . . .

37 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 &&

38 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) && . . .

39 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 . . .

40 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

41 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

42 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

43 Scalability Abstraction Compositionality
Throw away guards at procedure boundaries Compositionality Analyze each procedure in isolation

44 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

45 Abstraction initial summary (*u,user)  true (*u,checked)  cmd == 1
(*u,error)  false initial summary

46 α = Abstraction abstraction function initial summary (*u,user)  true
(*u,checked)  cmd == 1 (*u,error)  false abstraction function initial summary

47 α = Abstraction abstraction function initial summary final summary
(*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

48 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

49 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

50 Compositionality 1: int get (int *v) { 2: int x; 3: 4: x = *v; 5:
6: return x; 7: }

51 Compositionality 1: int get (int *v) { 2: int x; (*v,user)  c1 3:
5: 6: return x; 7: } (*v,user)  c1

52 Compositionality “context variable” 1: int get (int *v) { 2: int x;
3: 4: x = *v; 5: 6: return x; 7: } (*v,user)  c1

53 Compositionality 1: int get (int *v) { 2: int x; (*v,user)  c1 3:
5: 6: return x; 7: } (*v,user)  c1 (*v,user)  c1

54 Compositionality 1: int get (int *v) { 2: int x; (*v,user)  c1 3:
5: 6: return x; 7: } (*v,user)  c1 (*v,user)  c1 (*v,user)  c1 (*v,error)  c1

55 Compositionality 1: int get (int *v) { 2: int x; (*v,user)  c1 3:
5: 6: return x; 7: } (*v,user)  c1 (*v,user)  c1 (*v,user)  c1 (*v,error)  c1

56 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

57 Analysis Passes Alias analysis
computes memory model for each procedure

58 Analysis Passes Alias analysis User state propagation
computes memory model for each procedure User state propagation propagates user states throughout OS

59 Analysis Passes Alias analysis User state propagation
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

60 Linux 2.6.17.1 built for x86 lines of code 6.2 million procedures
91,543 global variables 40,760 composite types 14,794 initializers 35,317 loops 33,886 system call parameters 627 dereference sites 867,544

61 Experiment Setup time bound per procedure 3 minutes
alias analysis time outs ~9 K procedures (10%) user ptr analysis time outs 154 procedures (0.17%) compute nodes 25 cpus per node 4 memory per node 6 GB total run time 3.5 hours

62 Results Verified automatically Warnings
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

63 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: }

64 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: }

65 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: }

66 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)

67 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: }

68 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

69 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

70 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

71 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

72 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: }

73 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: }

74 Related Work MECA, by Yang, Kremenek, Xie, Engler Sparse, by Torvalds
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

75 Future Work Eliminate the time outs on procedures
Handle inline assembly statements Reduce number of false alarms

76 Conclusions Nearly verifying important security property
Scaling to largest open source program Reporting low number of false alarms

77 Questions


Download ppt "Verifying the Safety of User Pointer Dereferences"

Similar presentations


Ads by Google