Finding Race Conditions in Kernels from fuzzing to symbolic - - PowerPoint PPT Presentation

finding race conditions in kernels
SMART_READER_LITE
LIVE PREVIEW

Finding Race Conditions in Kernels from fuzzing to symbolic - - PowerPoint PPT Presentation

Finding Race Conditions in Kernels from fuzzing to symbolic execution Meng Xu July 16, 2020 Meng Xu (Georgia Tech) Finding Race Conditions in Kernels 1 July 16, 2020 The game of attack and defense Bug fi nding Exploitation Pro fi t Meng Xu


slide-1
SLIDE 1

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

July 16, 2020

Finding Race Conditions in Kernels

from fuzzing to symbolic execution

1

Meng Xu

slide-2
SLIDE 2

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

The game of attack and defense

2

Bug finding Exploitation Profit

slide-3
SLIDE 3

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

The game of attack and defense

3

Bug finding Exploitation Profit

Privacy violations in browsers [CCS’15] Kernel double-fetch bugs [SP’18] Concolic execution [Security’18] Kernel file system bugs [SOSP’19] File system data races [SP’20] C to SMT Transpilation [WIP]

slide-4
SLIDE 4

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

The game of attack and defense

4

Bug finding Profit

Privacy violations in browsers [CCS’15] Concolic execution [Security’18] Kernel file system bugs [SOSP’19]

Protection through diversity

Comprehensive memory prot. [ATC’17] Malicious document prot. [Security’17] Information leak prot. [TDSC’18] Kernel double-fetch bugs [SP’18] File system data races [SP’20] C to SMT Transpilation [WIP]

slide-5
SLIDE 5

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

The game of attack and defense

5

Bug finding

Privacy violations in browsers [CCS’15] Concolic execution [Security’18] Kernel file system bugs [SOSP’19]

Protection through diversity

Comprehensive memory prot. [ATC’17] Malicious document prot. [Security’17] Information leak prot. [TDSC’18]

Recovery

Android security survey [CSUR’16] 1-day vuln. in OSS [CCS’17] Android update attack [ComSIS’18] IoT device resiliency [SP’19] Secure router for smart homes [in sub.] Kernel double-fetch bugs [SP’18] File system data races [SP’20] C to SMT Transpilation [WIP]

slide-6
SLIDE 6

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

In this dissertation

6

Bug finding

Privacy violations in browsers [CCS’15] Concolic execution [Security’18] Kernel file system bugs [SOSP’19]

Protection through diversity

Comprehensive memory prot. [ATC’17] Malicious document prot. [Security’17] Information leak prot. [TDSC’18]

Recovery

Android security survey [CSUR’16] 1-day vuln. in OSS [CCS’17] Android update attack [ComSIS’18] IoT device resiliency [SP’19] Secure router for smart homes [in sub.] Kernel double-fetch bugs [SP’18] File system data races [SP’20] C to SMT Transpilation [WIP]

slide-7
SLIDE 7

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

In this dissertation

7

Bug finding

Privacy violations in browsers [CCS’15] Concolic execution [Security’18] Kernel file system bugs [SOSP’19]

Protection through diversity

Comprehensive memory prot. [ATC’17] Malicious document prot. [Security’17] Information leak prot. [TDSC’18]

Recovery

Android security survey [CSUR’16] 1-day vuln. in OSS [CCS’17] Android update attack [ComSIS’18] IoT device resiliency [SP’19] Secure router for smart homes [in sub.] Kernel double-fetch bugs [SP’18] File system data races [SP’20]

Race conditions

C to SMT Transpilation [WIP]

slide-8
SLIDE 8

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Race conditions

8

Definition: Two memory accesses from different threads such that

  • 1. They access the same memory location
  • 2. At least one of them is a write operation
  • 3. They may interleave without restrictions (i.e., locks, orderings, etc)
slide-9
SLIDE 9

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

The classic race condition example

9

for(i=0; i<5; i++) { count++; } count = 0 Thread 1 Thread 2

*Assume sequential consistency.

for(i=0; i<5; i++) { count++; } What is the value of count when both threads terminate?

slide-10
SLIDE 10

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

The classic race condition example

10

for(i=0; i<5; i++) { count++; } count = 0 Thread 1 Thread 2

*Assume sequential consistency.

for(i=0; i<5; i++) { count++; } What is the value of count when both threads terminate? Any value between 5 to 10

slide-11
SLIDE 11

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

The classic race condition example

11

for(i=0; i<5; i++) { lock(mutex); count++; unlock(mutex); } count = 0 Thread 1 Thread 2

*Assume sequential consistency.

for(i=0; i<5; i++) { lock(mutex); count++; unlock(mutex); } What is the value of count when both threads terminate? 10

slide-12
SLIDE 12

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

The rise of race conditions

12

Percentage of race conditions used by 0-days in the wild

0% 25% 50% 75% 100% 2015 2016 2017 2018 2019

33% 29% 26% 23% 17% Race conditions Other bugs

slide-13
SLIDE 13

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Agenda

13

  • 1. What are race conditions?
  • 2. Finding their presence with fuzzing?

[SP’20] Data races in file systems

  • 3. Towards a more systematic methodology?

[SP’18] Symbolic race checking

  • 4. Up to the extreme of completeness and soundness?

[WIP (CAV’21)] C to SMT transpilation

Increasing level

  • f guarantee

Increasing level

  • f practicality
slide-14
SLIDE 14

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Agenda

14

  • 1. What are race conditions?
  • 2. Finding their presence with fuzzing?

[SP’20] Data races in file systems

  • 3. Towards a more systematic methodology?

[SP’18] Symbolic race checking

  • 4. Up to the extreme of completeness and soundness?

[WIP (CAV’21)] C to SMT transpilation

c c

slide-15
SLIDE 15

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

High level of concurrency in the Linux kernel

15

22 threads run in the background!

slide-16
SLIDE 16

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

A data race in the kernel

16

Information lost! if (!p) p = kmalloc(...); p is a global pointer initialized to null Thread 1 Thread 2 if (!p) p = kmalloc(...);

slide-17
SLIDE 17

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

A data race in the kernel

17

Information lost! if (!p) p = kmalloc(...); p is a global pointer initialized to null Thread 1 Thread 2 if (!p) p = kmalloc(...);

This data race can be easily detected…

if we drive the execution into these code paths at runtime

slide-18
SLIDE 18

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Fuzzing as a way to explore the program

18

1 2 3 4 5 6 7 8 9 Start End

slide-19
SLIDE 19

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Code coverage as an approximation

19

1 2 3 4 5 6 7 8 9 Start End

  • pen(“some-file”, O_READ, ...)
slide-20
SLIDE 20

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Code coverage as an approximation

20

1 2 3 4 5 6 7 8 9 Start End

  • pen(“some-file”, O_READ, ...)
  • pen(“some-file”, O_WRITE, ...)
slide-21
SLIDE 21

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Code coverage as an approximation

21

1 2 3 4 5 6 7 8 9 Start End

  • pen(“some-file”, O_READ, ...)
  • pen(“some-file”, O_WRITE, ...)
  • pen(“new-file”, O_READ, ...)
slide-22
SLIDE 22

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Code coverage as an approximation

22

1 2 3 4 5 6 7 8 9 Start End

  • pen(“some-file”, O_READ, ...)
  • pen(“some-file”, O_WRITE, ...)
  • pen(“new-file”, O_READ, ...)

......

  • pen(“some-file”, O_RDWR, ...)

20 trials

Coverage growth stalled!

slide-23
SLIDE 23

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Code coverage as an approximation

23

1 2 3 4 5 6 7 8 9 Start End

  • pen(“some-file”, O_READ, ...)
  • pen(“some-file”, O_WRITE, ...)
  • pen(“new-file”, O_READ, ...)

......

  • pen(“some-file”, O_RDWR, ...)

20 trials rename(“new-file”, “old-file”)

10 11 12 13 14

slide-24
SLIDE 24

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

The conventional fuzzing process

24

Syscall generator Test case Program executor Feedback

code coverage

Memory error

Crashed?

slide-25
SLIDE 25

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

The conventional fuzzing process

25

Syscall generator Test case Program executor Feedback

code coverage

Memory error

Crashed?

The code coverage metric backs all modern kernel fuzzers

including Syzkaller, kAFL, and their follow-ups, and is one of the key reason why over 200 memory errors were found and reported during the past few years!

slide-26
SLIDE 26

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Back to our data race example

26

if (!p) p = kmalloc(...); p is a global pointer initialized to null Thread 1 Thread 2 if (!p) p = kmalloc(...);

*Assume sequential consistency.

slide-27
SLIDE 27

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Back to our data race example

27

if (!p) p = kmalloc(...); p is a global pointer initialized to null Thread 1 Thread 2 if (!p) p = kmalloc(...);

*Assume sequential consistency.

No CRASH when the data race is triggered!

slide-28
SLIDE 28

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Traditional fuzzers rely on crash as a bug signal

28

Syscall generator Test case Program executor Feedback

code coverage

Memory error

Crashed?

slide-29
SLIDE 29

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Checking data races - locking

29

Workqueue Syscall

W

lock

R

unlock lock unlock

slide-30
SLIDE 30

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Checking data races - ordering (causality)

30

Timer Workqueue Syscall

W

delayed_work <timer start> <timer end> queue_work

R

<work start>

slide-31
SLIDE 31

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Bring out data races explicitly with a checker

31

Syscall generator Test case Program executor Feedback

code coverage

Data race checker Memory error

Crashed?

Data race

Signaled?

slide-32
SLIDE 32

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

A slightly complicated data race

32

sys_readlink(path, ...): global A = 1; local x; if (IS_DIR(path)) { x = A + 1; if (!G[x]) G[x] = kmalloc(...); } sys_truncate(size, ...): global A = 0; local y; if (size > 4096) { y = A * 2; if (!G[y]) G[y] = kmalloc(...); } G[…] is all null at initialization Thread 1 Thread 2

*Assume sequential consistency.

slide-33
SLIDE 33

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

A slightly complicated data race

33

sys_readlink(path, ...): global A = 1; local x; if (IS_DIR(path)) { x = A + 1; if (!G[x]) G[x] = kmalloc(...); } sys_truncate(size, ...): global A = 0; local y; if (size > 4096) { y = A * 2; if (!G[y]) G[y] = kmalloc(...); } G[…] is all null at initialization Thread 1 Thread 2

*Assume sequential consistency.

slide-34
SLIDE 34

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Case simplified

34

A = 1; x = A + 1; Thread 1 A = 0; y = A * 2; Thread 2 Can we reach x == y?

slide-35
SLIDE 35

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Case simplified

35

A = 1; x = A + 1; Thread 1 A = 0; y = A * 2; Thread 2 Can we reach x == y? A = 0; A = 1; x = A + 1; y = A * 2; A = 0; A = 1; x = A + 1; y = A * 2; A = 0; A = 1; x = A + 1; y = A * 2; x = 2, y = 0 x = 1, y = 0 x = 1, y = 0 A = 0; A = 1; x = A + 1; y = A * 2; A = 0; A = 1; x = A + 1; y = A * 2; A = 0; A = 1; x = A + 1; y = A * 2; x = 2, y = 0 x = 2, y = 2 x = 2, y = 2

slide-36
SLIDE 36

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

All interleavings yield to the same code coverage!

36

A = 0; A = 1; x = A + 1; y = A * 2; A = 0; A = 1; x = A + 1; y = A * 2; A = 0; A = 1; x = A + 1; y = A * 2; x = 2, y = 0 x = 1, y = 0 x = 1, y = 0 A = 0; A = 1; x = A + 1; y = A * 2; A = 0; A = 1; x = A + 1; y = A * 2; A = 0; A = 1; x = A + 1; y = A * 2; x = 2, y = 0 x = 2, y = 2 x = 2, y = 2

global A = 1; local x; if (IS_DIR(path)) x = A + 1; if (!G[x]) G[x] = kmalloc(...); ... global A = 0; local y; if (size > 4096) y = A * 2; if (!G[y]) G[y] = kmalloc(...); ...

slide-37
SLIDE 37

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Incompleteness of CFG edge coverage

37

slide-38
SLIDE 38

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

A multi-dimensional view of coverage in fuzzing

38

Edge-coverage only Krace

slide-39
SLIDE 39

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Visualizing the concurrency dimension

39

slide-40
SLIDE 40

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Visualizing the concurrency dimension

40

Edge-coverage only Krace

slide-41
SLIDE 41

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Bring fuzzing to the concurrency dimension

41

Syscall generator Test case Program executor Feedback

code coverage

Data race checker Memory error

Crashed?

Data race

Signaled?

slide-42
SLIDE 42

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Bring fuzzing to the concurrency dimension

42

Syscall generator Test case Program executor Feedback

code coverage

Data race checker

concurrency coverage

Memory error

Crashed?

Data race

Signaled?

slide-43
SLIDE 43

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Bring fuzzing to the concurrency dimension

43

Syscall generator Test case Program executor Feedback

code coverage

Data race checker Interleaving generator

concurrency coverage

Memory error

Crashed?

Data race

Signaled?

slide-44
SLIDE 44

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Concurrency coverage tracking

44

Syscall generator Test case Program executor Feedback

code coverage

Data race checker Interleaving generator

concurrency coverage

Memory error

Crashed?

Data race

Signaled?

slide-45
SLIDE 45

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

A straw-man solution

sys_readlink(path, ...): global A = 1; local x; if (IS_DIR(path)) { x = A + 1; if (G[x]) kmalloc(...); } sys_truncate(size, ...): global A = 0; local y; if (size > 4096) { y = A * 2; if (G[y]) kmalloc(...); } Thread 1 Thread 2

45

i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12

slide-46
SLIDE 46

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

A straw-man solution

sys_readlink(path, ...): global A = 1; local x; if (IS_DIR(path)) { x = A + 1; if (G[x]) kmalloc(...); } sys_truncate(size, ...): global A = 0; local y; if (size > 4096) { y = A * 2; if (G[y]) kmalloc(...); } Thread 1 Thread 2 global A = 1; global A = 0; local y; local x; if (IS_DIR(path)) { if (size > 4096) { x = A + 1; y = A * 2; if(G[x]) if (G[y]) kmalloc(...); } kmalloc(...); } A possible interleaving

46

i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i1 i7 i8 i9 i2 i3 i4 i10 i5 i6 i11 i12

slide-47
SLIDE 47

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

A straw-man solution

sys_readlink(path, ...): global A = 1; local x; if (IS_DIR(path)) { x = A + 1; if (G[x]) kmalloc(...); } sys_truncate(size, ...): global A = 0; local y; if (size > 4096) { y = A * 2; if (G[y]) kmalloc(...); } Thread 1 Thread 2 global A = 1; global A = 0; local y; local x; if (IS_DIR(path)) { if (size > 4096) { x = A + 1; y = A * 2; if(G[x]) if (G[y]) kmalloc(...); } kmalloc(...); }

47

i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i1 i7 i8 i9 i2 i3 i4 i10 i5 i6 i11 i12

if (IS_DIR(path)) { if (size > 4096) { Hash(i1, i7, i8, i2, i3, i9, i4, i10, i5, i11, i12, i6) = 7825 Hash(i1, i7, i8, i2, i9, i3, i4, i10, i5, i11, i12, i6) = 1356

slide-48
SLIDE 48

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

A straw-man solution

sys_readlink(path, ...): global A = 1; local x; if (IS_DIR(path)) { x = A + 1; if (G[x]) kmalloc(...); } sys_truncate(size, ...): global A = 0; local y; if (size > 4096) { y = A * 2; if (G[y]) kmalloc(...); } Thread 1 Thread 2 global A = 1; global A = 0; local y; local x; if (IS_DIR(path)) { if (size > 4096) { x = A + 1; y = A * 2; if(G[x]) if (G[y]) kmalloc(...); } kmalloc(...); } A possible interleaving

48

i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i1 i7 i8 i9 i2 i3 i4 i10 i5 i6 i11 i12

Number of possible interleavings of two threads

If two threads have and instructions respectively, then the number interleavings between them is given by:

m n

(m + n)! m! × n!

m = n = 2

6

m = n = 4

70

m = n = 8

13K

m = n = 16

601M

slide-49
SLIDE 49

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Observations on practical interleaving tracking

49

slide-50
SLIDE 50

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Observations on practical interleaving tracking

50

Only interleaved accesses to shared memory matters

  • In an extreme case where two threads do not shared

memory, they interleaving does not matter at all.

Only interleaved read-write accesses to shared memory locations matters

  • In an extreme case where two threads only read from

shared memory, they interleaving does not matter at all.

Thread interleaving alters the def-use relation of memory locations!

Thread 1 Thread 2

slide-51
SLIDE 51

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Observations on practical interleaving tracking

51

Only interleaved accesses to shared memory matters

  • In an extreme case where two threads do not shared

memory, they interleaving does not matter at all.

Only interleaved read-write accesses to shared memory locations matters

  • In an extreme case where two threads only read from

shared memory, they interleaving does not matter at all.

Thread interleaving alters the def-use relation of memory locations!

Thread 1 Thread 2

R R

x = A + 1 y = A * 2

slide-52
SLIDE 52

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Observations on practical interleaving tracking

52

Only interleaved accesses to shared memory matters

  • In an extreme case where two threads do not shared

memory, they interleaving does not matter at all.

Only interleaved read-write accesses to shared memory locations matters

  • In an extreme case where two threads only read from

shared memory, they interleaving does not matter at all.

Thread interleaving alters the def-use relation of memory locations!

Thread 1 Thread 2

R

x = A + 1

W

A = 1

W

A = 0

slide-53
SLIDE 53

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Observations on practical interleaving tracking

53

Only interleaved accesses to shared memory matters

  • In an extreme case where two threads do not shared

memory, they interleaving does not matter at all.

Only interleaved read-write accesses to shared memory matters

  • In an extreme case where two threads only read from

shared memory, they interleaving does not matter at all.

Thread interleaving alters the def-use relation of memory locations!

Thread 1 Thread 2

R

x = A + 1

W

A = 1

W

A = 0

Interleaving approximation

Track cross-thread write-to-read (def-to-use) edges!

slide-54
SLIDE 54

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Observations on practical interleaving tracking

54

Interleaving approximation

Track cross-thread write-to-read (def-to-use) edges!

slide-55
SLIDE 55

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Aliased-instruction coverage

55

Thread 1 Thread 2

R

x = A + 1

W

A = 1

W

A = 0

i1 i2 i3

i2 i3

slide-56
SLIDE 56

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Aliased-instruction coverage

56

Thread 1 Thread 2

R

x = A + 1

W

A = 1

W

A = 0

W

B = 2

R

y = B * 4

i1 i2 i3 i4 i5

i2 i5, i4 i3

→ →

slide-57
SLIDE 57

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Aliased-instruction coverage

57

Thread 1 Thread 2

R

x = A + 1

W

A = 1

W

A = 0

W

B = 2

R

y = B * 4

i1 i2 i3 i4 i5

i2 i5, i4 i3

→ →

Concurrency coverage bitmap size

During our experiment, we observed 63,590 unique cross-thread, write-to-read edges. a bitmap size of 128KB will be sufficient.

slide-58
SLIDE 58

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Concurrency coverage tracking

58

Syscall generator Test case Program executor Feedback

code coverage

Data race checker Interleaving generator

concurrency coverage

Memory error

Crashed?

Data race

Signaled?

slide-59
SLIDE 59

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Interleaving exploration

59

Syscall generator Test case Program executor Feedback

code coverage

Data race checker Interleaving generator

concurrency coverage

Memory error

Crashed?

Data race

Signaled?

slide-60
SLIDE 60

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Active interleaving exploration - ideal case

60

A = 1; x = A + 1; Thread 1 A = 0; y = A * 2; Thread 2 A = 0; A = 1; x = A + 1; y = A * 2; A = 0; A = 1; x = A + 1; y = A * 2; A = 0; A = 1; x = A + 1; y = A * 2; x = 2, y = 0 x = 1, y = 0 x = 1, y = 0 A = 0; A = 1; x = A + 1; y = A * 2; A = 0; A = 1; x = A + 1; y = A * 2; A = 0; A = 1; x = A + 1; y = A * 2; x = 2, y = 0 x = 2, y = 2 x = 2, y = 2

i3 i4 i1 i2

<nil> i3 i2

i3 i2

<nil> i1 i4

i1 i4

slide-61
SLIDE 61

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Active interleaving exploration - ideal case

61

A = 1; x = A + 1; Thread 1 A = 0; y = A * 2; Thread 2 A = 0; A = 1; x = A + 1; y = A * 2; A = 0; A = 1; x = A + 1; y = A * 2; A = 0; A = 1; x = A + 1; y = A * 2; x = 2, y = 0 x = 1, y = 0 x = 1, y = 0 A = 0; A = 1; x = A + 1; y = A * 2; A = 0; A = 1; x = A + 1; y = A * 2; A = 0; A = 1; x = A + 1; y = A * 2; x = 2, y = 0 x = 2, y = 2 x = 2, y = 2

i3 i4 i1 i2

<nil> i3 i2

i3 i2

<nil> i1 i4

i1 i4

Enumerating all interleaving among all kernel threads is impossible

During our experiment, we observed at maximum 60 threads running concurrently. Assume each thread have only 10 shared memory accesses possibilities.

⟶ 1060

slide-62
SLIDE 62

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Active interleaving exploration through delay injection

62

T1 T2 T3 T4

R W W R i1 i2 i3 i4

Concurrency coverage

slide-63
SLIDE 63

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Active interleaving exploration through delay injection

63

T1 T2 T3 T4

R R W W i1 i2 i3 i4

d(669) d(300) d(273) d(20)

R W W R

Concurrency coverage

slide-64
SLIDE 64

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Active interleaving exploration through delay injection

64

T1 T2 T3 T4

R R W W i1 i2 i3 i4

d(669) d(300) d(273) d(20) Concurrency coverage

slide-65
SLIDE 65

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Interleaving exploration

65

Syscall generator Test case Program executor Feedback

code coverage

Data race checker Interleaving generator

concurrency coverage

Memory error

Crashed?

Data race

Signaled?

slide-66
SLIDE 66

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Bring them all together

66

Syscall generator Test case Program executor Feedback

code coverage

Data race checker Interleaving generator

concurrency coverage

Memory error

Crashed?

Data race

Signaled?

slide-67
SLIDE 67

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

QEMU-based implementation

67

slide-68
SLIDE 68

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Alias coverage growth will be saturating

68

Btrfs Ext4 But file systems that are higher in concurrency level saturates much slower!

slide-69
SLIDE 69

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Edge and alias coverage goes generally in synchronization

69

Btrfs Ext4 But there will be time when the edge coverage saturates but alias coverage keeps finding new thread interleaving

slide-70
SLIDE 70

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Slightly more branch coverage than Syzkaller

70

Btrfs Ext4 This maybe due to the fact that we give each seed more chances (if they make progresses in alias coverage)

slide-71
SLIDE 71

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Bugs found by Krace

71 Evaluation Bugs

File system # data races # harmful confirmed

Btrfs 11 8 Ext4 4 1 VFS 8 2

Total 23 11

slide-72
SLIDE 72

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Comparison with related works

72

Structured input Seed selection Application Coverage metric

[SP’19] Janus [ICSE’19] DifFuzz [VLDB’20] Apollo [CCS’17] SlowFuzz …… [ICSE’19] SLF …… [Google] Syzkaller [FSE’19] Fudge …… [ASE’18] FairFuzz [CCS’16] AFLFast [SP’18] Angora [SP’20] Krace [RAID’19] Benchmark

slide-73
SLIDE 73

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Conclusion and contribution

73

Structured input Seed selection Application Coverage metric

[SP’19] Janus [ICSE’19] DifFuzz [VLDB’20] Apollo [CCS’17] SlowFuzz …… [ICSE’19] SLF …… [Google] Syzkaller [FSE’19] Fudge …… [ASE’18] FairFuzz [CCS’16] AFLFast [SP’18] Angora [SP’20] Krace [RAID’19] Benchmark

slide-74
SLIDE 74

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Common criticism about the fuzzing approach

74

  • 1. How strong is the security guarantee?

e.g., 1 hour of fuzzing without any bugs, what does that mean?

  • 2. Can you deterministically replay the bugs found?

Most likely not, because we do not directly control the scheduler.

  • 3. How easy can these data races be triggered in reality?

Hard to argue, because fuzzing is essentially a probabilistic search.

  • 4. What are the consequences out of these data races?

e.g., can you really alter the control flow or change some sensitive data?

slide-75
SLIDE 75

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Agenda

75

  • 1. What are race conditions?
  • 2. Finding their presence with fuzzing?

[SP’20] Data races in file systems

  • 3. Towards a more systematic methodology?

[SP’18] Symbolic race checking

  • 4. Up to the extreme of completeness and soundness?

[WIP (CAV’21)] C to SMT transpilation

c c

slide-76
SLIDE 76

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Agenda

76

  • 1. What are race conditions?
  • 2. Finding their presence with fuzzing?

[SP’20] Data races in file systems

  • 3. Towards a more systematic methodology?

[SP’18] Symbolic race checking

  • 4. Up to the extreme of completeness and soundness?

[WIP (CAV’21)] C to SMT transpilation

c

slide-77
SLIDE 77

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

SMT and symbolic execution

77

  • SMT stands for satisfiability modulo theories
  • Given some basic math theories about Booleans, Integers, etc, decide

whether some constraints are satisfiable or not ==> constraint solvers.

  • Example: what are the values of and that satisfy both constraints:
  • Manual solving:

x y x + y = 10 x + 2y = 20 x = 0, y = 10

slide-78
SLIDE 78

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

An SMT script is a problem description

78

  • To describe the problem to an automated solver,
  • we need some standardized format ==> an SMT script
  • Continued from the example:
  • x + y = 10

x + 2y = 20

(declare-const x Int) (declare-const y Int) (assert (= (+ x y) 10)) (assert (= (+ x (* 2 y)) 20)) (check-sat) (get-model) sat (model (define-fun y () Int 10) (define-fun x () Int 0) )

The problem we have in mind The SMT script we formulated The answer given by Z3 SMT solver

slide-79
SLIDE 79

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

sat (model (define-fun y () Int 10) (define-fun x () Int 0) )

Analogy with bug finding

79

The problem we have in mind The SMT script we formulated The answer given by Z3 SMT solver

int loop(int x) { int s = 1; for (int i=1; i<=x; i++) { s *= i; } return s; }

Will variable “s” overflow in the program?

??? ???

  • x + y = 10

x + 2y = 20

(declare-const x Int) (declare-const y Int) (assert (= (+ x y) 10)) (assert (= (+ x (* 2 y)) 20)) (check-sat) (get-model)

slide-80
SLIDE 80

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Analogy with bug finding

80

The problem we have in mind The SMT script we formulated The answer given by Z3 SMT solver

int loop(int x) { int s = 1; for (int i=1; i<=x; i++) { s *= i; } return s; }

Will variable “s” overflow in the program?

??? ???

Symbolizing program — focus of the ongoing CAV’21 paper Translating bug description — focus of the SP’18 paper

slide-81
SLIDE 81

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

What is a double-fetch bug?

81

User program address space Kernel address space

static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(attr, &uattr->size, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_from_user(uattr, attr, attr->size))

slide-82
SLIDE 82

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

What is a double-fetch bug?

82

User program address space Kernel address space

static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(attr, &uattr->size, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_from_user(uattr, attr, attr->size))

slide-83
SLIDE 83

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

What is a double-fetch bug?

83

User program address space Kernel address space

static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(attr, &uattr->size, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_from_user(uattr, attr, attr->size))

?? bytes

slide-84
SLIDE 84

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

What is a double-fetch bug?

84

User program address space Kernel address space

static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(attr, &uattr->size, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_from_user(uattr, attr, attr->size))

?? bytes 4 bytes 30

slide-85
SLIDE 85

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

What is a double-fetch bug?

85

User program address space Kernel address space

static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(attr, &uattr->size, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_from_user(uattr, attr, attr->size))

?? bytes 4 bytes 30 30

slide-86
SLIDE 86

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

What is a double-fetch bug?

86

User program address space Kernel address space

static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(attr, &uattr->size, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_from_user(uattr, attr, attr->size))

?? bytes 4 bytes 30 30

slide-87
SLIDE 87

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

What is a double-fetch bug?

87

User program address space Kernel address space

static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(attr, &uattr->size, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_from_user(uattr, attr, attr->size))

30 bytes 4 bytes 30 30

slide-88
SLIDE 88

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(kattr, uattr, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_from_user(uattr, attr, attr->size))

What is a double-fetch bug?

88

User program address space Kernel address space 30 bytes 4 bytes 30 30 30

slide-89
SLIDE 89

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(kattr, uattr, size)) return -EFAULT; ...... } copy_to_user(uattr, attr, attr->size))

What is a double-fetch bug?

89

User program address space Kernel address space 30 bytes 4 bytes 30 30 30 Copy 30 bytes back to user

slide-90
SLIDE 90

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

The assumption failure

static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(kattr, attr, size)) return -EFAULT; ...... } copy_to_user(uattr, attr, attr->size))

90

User program address space Kernel address space 30 bytes 4 bytes Copy 30 bytes back to user 30 30 30

What can go wrong in this process?

Data atomicity during syscall execution is not guaranteed!

slide-91
SLIDE 91

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Up until the first fetch…

91

User program address space Kernel address space

static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(attr, &uattr->size, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_from_user(uattr, attr, attr->size))

?? bytes 4 bytes 30 30

slide-92
SLIDE 92

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Wrong assumption: atomicity in syscall

92

User program address space Kernel address space

static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(attr, &uattr->size, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_from_user(uattr, attr, attr->size))

?? bytes 4 bytes 60000 30

slide-93
SLIDE 93

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(kattr, uattr, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_from_user(uattr, attr, attr->size))

Wrong assumption: atomicity in syscall

93

User program address space Kernel address space 30 bytes 4 bytes 60000 60000 30

slide-94
SLIDE 94

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(kattr, uattr, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_to_user(uattr, kattr, kattr->size))

When the exploit happens

94

User program address space Kernel address space 30 bytes 4 bytes 60000 60000 Kernel information leak! 30

slide-95
SLIDE 95

Meng Xu (Georgia Tech) Finding Semantic Bugs in Kernels March 18, 2020

Modeling a double-fetch bug

95

Fetch: a pair , where

  • the starting address of the fetch
  • the size of memory copied into kernel

(A, S) A S

slide-96
SLIDE 96

Meng Xu (Georgia Tech) Finding Semantic Bugs in Kernels March 18, 2020

Modeling a double-fetch bug

96

Fetch: a pair , where

  • the starting address of the fetch
  • the size of memory copied into kernel

Overlap: two fetches, and , that satisfy

(A, S) A S (A1, S1) (A2, S2) A1 ≤ A2 < (A1 + S1) || A2 ≤ A1 < (A2 + S2)

slide-97
SLIDE 97

Meng Xu (Georgia Tech) Finding Semantic Bugs in Kernels March 18, 2020

Modeling a double-fetch bug

97

Fetch: a pair , where

  • the starting address of the fetch
  • the size of memory copied into kernel

Overlap: two fetches, and , that satisfy Dependency: such that controls whether and how the second fetch might take place.

(A, S) A S (A1, S1) (A2, S2) A1 ≤ A2 < (A1 + S1) || A2 ≤ A1 < (A2 + S2) ∃V ∈ 𝙿𝚠𝚏𝚜𝚖𝚋𝚚 V

slide-98
SLIDE 98

Meng Xu (Georgia Tech) Finding Semantic Bugs in Kernels March 18, 2020

Modeling a double-fetch bug

98

Fetch: a pair , where

  • the starting address of the fetch
  • the size of memory copied into kernel

Overlap: two fetches, and , that satisfy Dependency: such that controls whether and how the second fetch might take place. Precaution: check that from the second fetch equals from the first fetch.

(A, S) A S (A1, S1) (A2, S2) A1 ≤ A2 < (A1 + S1) || A2 ≤ A1 < (A2 + S2) ∃V ∈ 𝙿𝚠𝚏𝚜𝚖𝚋𝚚 V V′ V

slide-99
SLIDE 99

Meng Xu (Georgia Tech) Finding Semantic Bugs in Kernels March 18, 2020

Model illustration

99

static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(kattr, uattr, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_to_user(uattr, kattr, kattr->size))

slide-100
SLIDE 100

Meng Xu (Georgia Tech) Finding Semantic Bugs in Kernels March 18, 2020

Model illustration

100

size static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(kattr, uattr, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_to_user(uattr, kattr, kattr->size))

slide-101
SLIDE 101

Meng Xu (Georgia Tech) Finding Semantic Bugs in Kernels March 18, 2020

Model illustration

101

size static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(kattr, uattr, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_to_user(uattr, kattr, kattr->size)) kattr

  • >size
slide-102
SLIDE 102

Meng Xu (Georgia Tech) Finding Semantic Bugs in Kernels March 18, 2020

Model illustration

102

size static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(kattr, uattr, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_to_user(uattr, kattr, kattr->size))

Control dependency

  • n variable size

kattr

  • >size
slide-103
SLIDE 103

Meng Xu (Georgia Tech) Finding Semantic Bugs in Kernels March 18, 2020

Model illustration

103

size static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(kattr, uattr, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_to_user(uattr, kattr, kattr->size))

Control dependency

  • n variable size

Data dependency

  • n variable size

kattr

  • >size
slide-104
SLIDE 104

Meng Xu (Georgia Tech) Finding Semantic Bugs in Kernels March 18, 2020

Model illustration

104

size kattr

  • >size

static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(kattr, uattr, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_to_user(uattr, kattr, kattr->size))

Control dependency

  • n variable size

Data dependency

  • n variable size

Missing check: 𝚕𝚋𝚞𝚞𝚜 → 𝚝𝚓𝚤𝚏 = 𝚝𝚓𝚤𝚏

slide-105
SLIDE 105

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Symbolic checking

105

static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(kattr, uattr, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_to_user(uattr, kattr, kattr->size))

slide-106
SLIDE 106

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Symbolic checking

106

static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(kattr, uattr, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_to_user(uattr, kattr, kattr->size)) $1 = PARAM(uattr), @1 = USER_MEM(uattr) // uattr $2 = PARAM(kattr), @2 = KERN_MEM(kattr) // kattr /* first fetch */ fetch(F1): {A = $1 + 4, S = 4} $3 @1(4, 8, U1), @3 = nil // size /* sanity checks */ assert: $3 PAGE_SIZE AND $3 PERF_ATTR_SIZE_VER0 /* second fetch */ fetch(F2): {A = $1, S = $3} @2(0, $2, K) @1(0, S2, U2) /* check overlap */ assert: F2.A F1.A (F2.A + F2.S) OR F1.A F2.A (F1.A + F1.S) [solve] SAT with solution @1(4, 8, U) /* check double-fetch bug */ [prove] @1(4, 8, U1) == @1(4, 8, U2) FAIL ← ≤ ≥ ← ≤ < ≤ < → →

slide-107
SLIDE 107

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Symbolic checking

107

static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(kattr, uattr, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_to_user(uattr, kattr, kattr->size)) $1 = PARAM(uattr), @1 = USER_MEM(uattr) // uattr $2 = PARAM(kattr), @2 = KERN_MEM(kattr) // kattr /* first fetch */ fetch(F1): {A = $1, S = 4} $3 @1(0, 4, U1), @3 = nil // size /* sanity checks */ assert: $3 PAGE_SIZE AND $3 PERF_ATTR_SIZE_VER0 /* second fetch */ fetch(F2): {A = $1, S = $3} @2(0, $2, K) @1(0, S2, U2) /* check overlap */ assert: F2.A F1.A (F2.A + F2.S) OR F1.A F2.A (F1.A + F1.S) [solve] SAT with solution @1(4, 8, U) /* check double-fetch bug */ [prove] @1(4, 8, U1) == @1(4, 8, U2) FAIL ← ≤ ≥ ← ≤ < ≤ < → →

slide-108
SLIDE 108

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Symbolic checking

108

static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(kattr, uattr, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_to_user(uattr, kattr, kattr->size)) $1 = PARAM(uattr), @1 = USER_MEM(uattr) // uattr $2 = PARAM(kattr), @2 = KERN_MEM(kattr) // kattr /* first fetch */ fetch(F1): {A = $1, S = 4} $3 @1(0, 4, U1), @3 = nil // size /* sanity checks */ assert: $3 PAGE_SIZE AND $3 PERF_ATTR_SIZE_VER0 /* second fetch */ fetch(F2): {A = $1, S = $3} @2(0, $2, K) @1(0, S2, U2) /* check overlap */ assert: F2.A F1.A (F2.A + F2.S) OR F1.A F2.A (F1.A + F1.S) [solve] SAT with solution @1(4, 8, U) /* check double-fetch bug */ [prove] @1(4, 8, U1) == @1(4, 8, U2) FAIL ← ≤ ≥ ← ≤ < ≤ < → →

slide-109
SLIDE 109

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Symbolic checking

109

static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(kattr, uattr, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_to_user(uattr, kattr, kattr->size)) $1 = PARAM(uattr), @1 = USER_MEM(uattr) // uattr $2 = PARAM(kattr), @2 = KERN_MEM(kattr) // kattr /* first fetch */ fetch(F1): {A = $1, S = 4} $3 @1(0, 4, U1), @3 = nil // size /* sanity checks */ assert: $3 PAGE_SIZE AND $3 PERF_ATTR_SIZE_VER0 /* second fetch */ fetch(F2): {A = $1, S = $3} @2(0, $2, K) @1(0, S2, U2) /* check overlap */ assert: F2.A F1.A (F2.A + F2.S) OR F1.A F2.A (F1.A + F1.S) [solve] SAT with solution @1(4, 8, U) /* check double-fetch bug */ [prove] @1(4, 8, U1) == @1(4, 8, U2) FAIL ← ≤ ≥ ← ≤ < ≤ < → →

slide-110
SLIDE 110

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Symbolic checking

110

static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(kattr, uattr, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_to_user(uattr, kattr, kattr->size)) $1 = PARAM(uattr), @1 = USER_MEM(uattr) // uattr $2 = PARAM(kattr), @2 = KERN_MEM(kattr) // kattr /* first fetch */ fetch(F1): {A = $1, S = 4} $3 @1(0, 4, U1), @3 = nil // size /* sanity checks */ assert: $3 PAGE_SIZE AND $3 PERF_ATTR_SIZE_VER0 /* second fetch */ fetch(F2): {A = $1, S = $3} @2(0, $2, K) @1(0, S2, U2) /* check overlap */ check: F2.A F1.A (F2.A + F2.S) OR F1.A F2.A (F1.A + F1.S) [solve] SAT with solution @1(0, 4, U) /* check double-fetch bug */ [prove] @1(4, 8, U1) == @1(4, 8, U2) FAIL ← ≤ ≥ ← ≤ < ≤ < → →

slide-111
SLIDE 111

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Symbolic checking

111

static int perf_copy_attr( struct perf_event_attr __user *uattr, struct perf_event_attr *kattr) { u32 size; /* first fetch */ if (copy_from_user(&size, &uattr->size, 4)) return -EFAULT; /* sanity checks */ if (size > PAGE_SIZE || size < PERF_ATTR_SIZE_VER0) return -EFAULT; /* second fetch */ if (copy_from_user(kattr, uattr, size)) return -EFAULT; ...... } /* BUG: when attr->size is used later */ copy_to_user(uattr, kattr, kattr->size)) $1 = PARAM(uattr), @1 = USER_MEM(uattr) // uattr $2 = PARAM(kattr), @2 = KERN_MEM(kattr) // kattr /* first fetch */ fetch(F1): {A = $1, S = 4} $3 @1(0, 4, U1), @3 = nil // size /* sanity checks */ assert: $3 PAGE_SIZE AND $3 PERF_ATTR_SIZE_VER0 /* second fetch */ fetch(F2): {A = $1, S = $3} @2(0, $2, K) @1(0, S2, U2) /* check overlap */ check: F2.A F1.A (F2.A + F2.S) OR F1.A F2.A (F1.A + F1.S) [solve] SAT with solution @1(0, 4, U) /* check double-fetch bug */ [prove] @1(0, 4, U1) == @1(0, 4, U2) FAIL ← ≤ ≥ ← ≤ < ≤ < → →

slide-112
SLIDE 112

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

(Partial) symbolic model for concurrent memory access

112

(load mem i) => 30 (declare mem (Array[Int->Int])) (declare i Int) (load mem i) => 30 Sequential representation (store mem i 30) 1st load 2nd load Initialize store

slide-113
SLIDE 113

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

(Partial) symbolic model for concurrent memory access

113

(load mem i) => 30 (declare mem (Array[Int->Int])) (declare i Int) (load mem i) => 30 (declare mem (Array[(Int Int)->Int])) (declare i Int) (declare v Int) (load mem (i 0)) => 30 (load mem (i 1)) => <unknown> Sequential representation Concurrent representation (store mem i 30) (store mem (i 0) 30) 1st load 2nd load Initialize store

slide-114
SLIDE 114

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Back to our toy program

114

count++; count = 0 Thread 1 Thread 2

*Assume sequential consistency.

count++; count == ??

slide-115
SLIDE 115

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Back to our toy program

115

temp = load(&count); store(&count, temp + 1); count = 0 Thread 1 Thread 2

*Assume sequential consistency.

temp = load(&count); store(&count, temp + 1); load(&count) == ??

slide-116
SLIDE 116

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Modeling memory accesses with concurrency versioning

116

load (M, (&count, v1)) store(M, (&count, 1), …+1) store(M, (&count, 0), 0) Thread 1 Thread 2

*Assume sequential consistency.

load (M, (&count, v2)) store(M, (&count, 2), …+1) load (M, (&count, v3))

T1(L): T1(S): :T2(L) :T2(S)

slide-117
SLIDE 117

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Modeling memory accesses with concurrency versioning

117

load (M, (&count, v1)) store(M, (&count, 1), …+1) store(M, (&count, 0), 0) Thread 1 Thread 2

*Assume sequential consistency.

load (M, (&count, v2)) store(M, (&count, 2), …+1) load (M, (&count, v3))

v1 cond.

0 ¬ T2(S)→T1(L) 2 T2(S)→T1(L)

v2 cond.

0 ¬ T1(S)→T2(L) 1 T1(S)→T2(L)

v3 cond.

1 T2(S)→T1(S) 2 T1(S)→T2(S)

slide-118
SLIDE 118

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Modeling memory accesses with concurrency versioning

118

load (M, (&count, v1)) store(M, (&count, 1), …+1) store(M, (&count, 0), 0) Thread 1 Thread 2

*Assume sequential consistency.

load (M, (&count, v2)) store(M, (&count, 2), …+1) load (M, (&count, v3))

Ask an SMT solver to get a valid combination of variables

i.e., can we have ? load (M, (&count, v3)) == 1 ?

v1 cond.

0 ¬ T2(S)→T1(L) 2 T2(S)→T1(L)

v2 cond.

0 ¬ T1(S)→T2(L) 1 T1(S)→T2(L)

v3 cond.

1 T2(S)→T1(S) 2 T1(S)→T2(S)

slide-119
SLIDE 119

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Modeling memory accesses with concurrency versioning

119

load (M, (&count, v1)) store(M, (&count, 1), …+1) store(M, (&count, 0), 0) Thread 1 Thread 2

*Assume sequential consistency.

load (M, (&count, v2)) store(M, (&count, 2), …+1) load (M, (&count, v3))

v1 cond.

0 ¬ T2(S)→T1(L) 2 T2(S)→T1(L)

v2 cond.

0 ¬ T1(S)→T2(L) 1 T1(S)→T2(L)

v3 cond.

1 T2(S)→T1(S) 2 T1(S)→T2(S)

Ask an SMT solver to get a valid combination of variables

i.e., can we have ? load (M, (&count, v3)) == 1 ? ==> T1(L) → T2(L) → T2(S) → T1(S) ==> v1 = 0, v2 = 0, v3 = 1

slide-120
SLIDE 120

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Modeling locks as additional constraints

120

lock(mutex); load (M, (&count, v1)) store(M, (&count, 1), …+1) unlock(mutex) store(M, (&count, 0), 0) Thread 1 Thread 2

*Assume sequential consistency.

lock(mutex); load (M, (&count, v2)) store(M, (&count, 2), …+1) unlock(mutex) load (M, (&count, v3))

v1 cond.

T1(M)→T2(M) 2 T2(M)→T1(M)

v2 cond.

T2(M)→T1(M) 1 T1(M)→T2(M)

v2 cond.

1 T2(M)→T1(M) 2 T1(M)→T2(M)

slide-121
SLIDE 121

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Modeling locks as additional constraints

121

lock(mutex); load (M, (&count, v1)) store(M, (&count, 1), …+1) unlock(mutex) store(M, (&count, 0), 0) Thread 1 Thread 2

*Assume sequential consistency.

lock(mutex); load (M, (&count, v2)) store(M, (&count, 2), …+1) unlock(mutex) load (M, (&count, v3))

v1 cond.

T1(M)→T2(M) 2 T2(M)→T1(M)

v2 cond.

T2(M)→T1(M) 1 T1(M)→T2(M)

v2 cond.

1 T2(M)→T1(M) 2 T1(M)→T2(M)

Ask an SMT solver to get a valid combination of variables

i.e., can we have ? load (M, (&count, v3)) == 1 ? ==> unsat

slide-122
SLIDE 122

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

The challenges faced in extending our SP’18 work

122

  • 1. Path explosion due to the number of branches

e.g., a typical filesystem-related syscall sees 60+ branches ⇒ states

  • 2. Handling of unbounded loops

e.g., 79% of loops in the Btrfs filesystem (4052 / 5124) are unbounded

  • 3. Memory operations and pointer arithmetics

e.g., malloc(<symbolic-size>), memset(…, <symbolic-size>), …

  • 4. A large and diverse vocabulary of kernel synchronization primitives

e.g., sequence locks, RCUs, barriers, etc.

260

slide-123
SLIDE 123

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

The gap between kernel code and the toy program…

123

  • 1. Path explosion due to the number of branches

e.g., a typical filesystem-related syscall sees 60+ branches ⇒ states

  • 2. Handling of unbounded loops

e.g., 79% of loops in the Btrfs filesystem (4052 / 5124) are unbounded

  • 3. Memory operations and pointer arithmetics

e.g., malloc(<symbolic-size>), memset(…, <symbolic-size>), …

  • 4. A large and diverse vocabulary of kernel synchronization primitives

e.g., sequence locks, RCUs, barriers, etc.

260

And yet we have to solve all these challenges, …

If we were to run a symbolic checking on a whole kernel module (e.g., a filesystem)

slide-124
SLIDE 124

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Whole-program lossless symbolic representation

124

The problem we have in mind The SMT script we formulated The answer given by Z3 SMT solver

int loop(int x) { int s = 1; for (int i=1; i<=x; i++) { s *= i; } return s; }

Will variable “s” overflow in the program?

??? ???

Symbolizing program — focus of the ongoing CAV’21 paper Translating bug description — focus of the SP’18 paper

slide-125
SLIDE 125

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Problem 1: Path explosion due to branching

125

slide-126
SLIDE 126

126

slide-127
SLIDE 127

127

But, if complex CFG is a problem, why compilers are not afraid of it?

slide-128
SLIDE 128

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Problem 1: Path explosion due to branching

128

<? x == 0 ?> e=phi(e1, e2, e3) <? e >= 10 ?> <? x >= 2 ?> e1 = 5 e2 = 10 e3 = 15 f1 = x + 1 f2 = x + 2 f = phi(f1, f2) unsigned func(unsigned x) { unsigned e; if (x == 0) { e = 5; } else { if (x >= 2) { e = 10; } else { e = 15; } } unsigned f; if (e >= 10) { f = x + 1; } else { f = x + 2; } return f; }

slide-129
SLIDE 129

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Problem 1: Path explosion due to branching

129

<? x == 0 ?> e=phi(e1, e2, e3) <? e >= 10 ?> <? x >= 2 ?> e1 = 5 e2 = 10 e3 = 15 f1 = x + 1 f2 = x + 2 f = phi(f1, f2) <? x == 0 ?> e1 = 5 e=phi(e1, e2, e3) <? e >= 10 ?> f2 = x + 2 f = phi(f1, f2)

slide-130
SLIDE 130

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Problem 1: Path explosion due to branching

130

<? x == 0 ?> e=phi(e1, e2, e3) <? e >= 10 ?> <? x >= 2 ?> e1 = 5 e2 = 10 e3 = 15 f1 = x + 1 f2 = x + 2 f = phi(f1, f2) <? x == 0 ?> e=phi(e1, e2, e3) <? e >= 10 ?> <? x >= 2 ?> e1 = 5 e2 = 10 f1 = x + 1 f = phi(f1, f2) e=phi(e1, e2, e3) <? e >= 10 ?> f2 = x + 2 f = phi(f1, f2)

slide-131
SLIDE 131

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Problem 1: Path explosion due to branching

131

<? x == 0 ?> e=phi(e1, e2, e3) <? e >= 10 ?> <? x >= 2 ?> e1 = 5 e2 = 10 e3 = 15 f1 = x + 1 f2 = x + 2 f = phi(f1, f2) <? x == 0 ?> e=phi(e1, e2, e3) <? e >= 10 ?> <? x >= 2 ?> e1 = 5 e2 = 10 e3 = 15 f1 = x + 1 f = phi(f1, f2) e=phi(e1, e2, e3) <? e >= 10 ?> f2 = x + 2 f = phi(f1, f2) e=phi(e1, e2, e3) <? e >= 10 ?> f1 = x + 1 f = phi(f1, f2)

slide-132
SLIDE 132

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Problem 1: Path explosion due to branching

132

<? x == 0 ?> e=phi(e1, e2, e3) <? e >= 10 ?> <? x >= 2 ?> e1 = 5 e2 = 10 e3 = 15 f1 = x + 1 f2 = x + 2 f = phi(f1, f2)

This part gets repeatedly executed by conventional symbolic executors such as KLEE, SAGE, etc.

e=phi(e1, e2, e3) <? e >= 10 ?> f1 = x + 1 f = phi(f1, f2) e=phi(e1, e2, e3) <? e >= 10 ?> f2 = x + 2 f = phi(f1, f2) e=phi(e1, e2, e3) <? e >= 10 ?> f1 = x + 1 f = phi(f1, f2)

slide-133
SLIDE 133

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Problem 1: Path explosion due to branching

133

<? x == 0 ?> e=phi(e1, e2, e3) <? e >= 10 ?> <? x >= 2 ?> e1 = 5 e2 = 10 e3 = 15 f1 = x + 1 f2 = x + 2 f = phi(f1, f2) <? x == 0 ?> e=phi(e1, e2, e3) <? e >= 10 ?> <? x >= 2 ?> e1 = 5 e2 = 10 e3 = 15 f1 = x + 1 f = phi(f1, f2) e=phi(e1, e2, e3) <? e >= 10 ?> f2 = x + 2 f = phi(f1, f2) e=phi(e1, e2, e3) <? e >= 10 ?> f1 = x + 1 f = phi(f1, f2) … … . … . … . … . … . … . … .

This is path explosion although there is only a small change at the bottom of the CFG

slide-134
SLIDE 134

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Problem 1: Path explosion due to branching

134

  • Is there a way to avoid state forking?
  • Yes, as long as we do not try to enumerate all paths!
  • Can we faithfully summarize a program without enumerating all paths?
  • Yes!
  • Besides depth-first exploration, there is breadth-first search for graphs.
slide-135
SLIDE 135

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Solution 1: Guarded symbolic representation

135

{{ pre-condition }} [ … … <basic-block> … ] {{ post-condition }}

<? x == 0 ?>

true . . . ↩ x = 0 . . . ↩ x ≠ 0

e1 = 5

x = 0 e1 = 5 ↩ x = 0

slide-136
SLIDE 136

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Solution 1: Guarded symbolic representation

136

{{ pre-condition }} [ … … <basic-block> … ] {{ post-condition }}

e=phi(e1, e2, e3)

e1 = 5 ↩ x = 0 e2 = 10 ↩ (x ≠ 0 ∧ x ≥ 2) e3 = 15 ↩ (x ≠ 0 ∧ x < 2) e = 5 ↩ x = 0 e = 10 ↩ (x ≠ 0 ∧ x ≥ 2) e = 15 ↩ (x ≠ 0 ∧ x < 2) e = ite(x = 0, 5, ite(x ≥ 2, 10, 15) ↩ true

Path is joined here!

slide-137
SLIDE 137

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Solution 1: Guarded symbolic representation

137

unsigned func(unsigned x) { unsigned e; if (x == 0) { e = 5; } else { if (x >= 2) { e = 10; } else { e = 15; } } unsigned f; if (e >= 10) { f = x + 1; } else { f = x + 2; } return f; } <? x == 0 ?> e=phi(e1, e2, e3) <? e >= 10 ?> <? x >= 2 ?> e1 = 5 e2 = 10 e3 = 15 f1 = x + 1 f2 = x + 2 f = phi(f1, f2)

1 2 3 4 5 6 7 8 9

f = ite(x = 0, x + 1 x + 2) ↩ true f = { x + 1 ↩ x = 0 x + 2 ↩ x ≠ 0

slide-138
SLIDE 138

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Problem 2: Loops

138

e=phi(e1, e2, e3) <? e >= 10 ?> e1 = 5 e2 = 10 e3 = 15

e1 = 5 ↩ x = 0 e2 = 10 ↩ (x ≠ 0 ∧ x ≥ 2) e3 = 15 ↩ (x ≠ 0 ∧ x < 2)

What is the condition for this back-edge?

slide-139
SLIDE 139

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Problem 2: Unbounded loops

139

int bar_simple(void) { int s = 0; for (int i = 0; i < 100; i++) { s += i; } return s; }

Bounded loops: know the number of iteration statically

slide-140
SLIDE 140

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Problem 2: Unbounded loops

140

int bar(int x) { int s = 1; for (int i = 1; i <= x; i++) { s *= i; if (s > 1000) { break; } } return s; } int bar_simple(void) { int s = 0; for (int i = 0; i < 100; i++) { s += i; } return s; }

Unbounded loops: the number of loop iteration is unknown Bounded loops: know the number of iteration statically

slide-141
SLIDE 141

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Solution 2: Loop modeling with recursive functions

141

Every loop can be converted to a recursion in a lossless way,

And SMT solvers like Z3 are capable of handling recursions!

slide-142
SLIDE 142

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Solution 2: Loop modeling with recursive functions

142

int bar(int x) { int s = 1; for (int i=1; i<=x; i++) { s *= i; if (s > 1000) { break; } } return s; }

slide-143
SLIDE 143

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Solution 2: Loop modeling with recursive functions

143

int bar(int x) { int s = 1; for (int i=1; i<=x; i++) { s *= i; if (s > 1000) { break; } } return s; }

slide-144
SLIDE 144

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Solution 2: Loop modeling

144

int bar(int x) { int s = 1; for (int i=1; i<=x; i++) { s *= i; if (s > 1000) { break; } } return s; }

s0 = 1 ↩ x > 0 sphi = { 5040 ↩ x ≥ 8 x! ↩ 0 < x < 8

How do we get this?

slide-145
SLIDE 145

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Solution 2: Loop modeling

145

int bar(int x) { int s = 1; for (int i=1; i<=x; i++) { s *= i; if (s > 1000) { break; } } return s; }

These are the variables we should recurse on

slide-146
SLIDE 146

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Solution 2: Loop modeling with recursive functions

146

int bar(int x) { int s = 1; for (int i=1; i<=x; i++) { s *= i; if (s > 1000) { break; } } return s; }

fi(k) = { 1 if k = 0 fi(k − 1) + 1 if k > 0 Suppose we are in -th iteration

k

slide-147
SLIDE 147

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Solution 2: Loop modeling with recursive functions

147

int bar(int x) { int s = 1; for (int i=1; i<=x; i++) { s *= i; if (s > 1000) { break; } } return s; }

fi(k) = { 1 if k = 0 fi(k − 1) + 1 if k > 0 fs(k) = { 1 if k = 0 fs(k − 1) × fi(k − 1) if k > 0 Suppose we are in -th iteration

k

slide-148
SLIDE 148

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Solution 2: Loop modeling with recursive functions

148

int bar(int x) { int s = 1; for (int i=1; i<=x; i++) { s *= i; if (s > 1000) { break; } } return s; }

fi(k) = { 1 if k = 0 fi(k − 1) + 1 if k > 0 fs(k) = { 1 if k = 0 fs(k − 1) × fi(k − 1) if k > 0 floop(k) = { True if k = 0 floop(k − 1) ∧ (fi(k − 1) ≤ x) ∧ (fs(k − 1) ≤ 1000) if k > 0 Suppose we are in -th iteration

k

slide-149
SLIDE 149

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Solution 2: Loop modeling with recursive functions

149

int bar(int x) { int s = 1; for (int i=1; i<=x; i++) { s *= i; if (s > 1000) { break; } } return s; }

fi(k) = { 1 if k = 0 fi(k − 1) + 1 if k > 0 fs(k) = { 1 if k = 0 fs(k − 1) × fi(k − 1) if k > 0 floop(k) = { True if k = 0 floop(k − 1) ∧ (fi(k − 1) ≤ x) ∧ (fs(k − 1) ≤ 1000) if k > 0 Suppose we are in -th iteration

k

Suppose we exited after -th iteration

m

sphi = fs(m) ↩ (fi(m) > x ∧ floop(m)) sphi = fs(m) ↩ (fs(m) > 1000 ∧ floop(m))

Exited through i > x Exited through s > 1000

slide-150
SLIDE 150

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Solution 2: Loop modeling with recursive functions

150

int bar(int x) { int s = 1; for (int i=1; i<=x; i++) { s *= i; if (s > 1000) { break; } } return s; }

fi(k) = { 1 if k = 0 fi(k − 1) + 1 if k > 0 fs(k) = { 1 if k = 0 fs(k − 1) × fi(k − 1) if k > 0 floop(k) = { True if k = 0 floop(k − 1) ∧ (fi(k − 1) ≤ x) ∧ (fs(k − 1) ≤ 1000) if k > 0 Suppose we are in -th iteration

k

Suppose we exited after -th iteration

m

sphi = fs(m) ↩ (fi(m) > x ∧ floop(m)) sphi = fs(m) ↩ (fs(m) > 1000 ∧ floop(m))

Exited through i > x Exited through s > 1000

sphi = { 5040 ↩ x ≥ 8 x! ↩ 0 < x < 8

slide-151
SLIDE 151

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Problem 3: Symbolic memory

151

int val = *ptr;

  • 1. Which object is ptr pointer to?
  • 2. What is the value stored in that memory region?
slide-152
SLIDE 152

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Problem 3: Symbolic memory

152

Malloc with symbolic size

void *p = malloc(e); if (x == 0) { e = 5; } else { if (x >= 2) { e = 10; } else { e = 15; } }

slide-153
SLIDE 153

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Problem 3: Symbolic memory

153

Malloc with symbolic size

char *h = malloc(8); h[0:7] = 1; if (x > 100) { h[0:5] = 2; } else if (x < 100) { h[2:7] = 3; } else { h[3:4] = 4; } if (x >= 100) { h[1:6] = 5; }

Partial override with conditions

void *p = malloc(e); if (x == 0) { e = 5; } else { if (x >= 2) { e = 10; } else { e = 15; } }

slide-154
SLIDE 154

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Problem 3: Symbolic memory

154

void *p = malloc(e); if (x == 0) { e = 5; } else { if (x >= 2) { e = 10; } else { e = 15; } }

Malloc with symbolic size

char *h = malloc(8); h[0:7] = 1; if (x > 100) { h[0:5] = 2; } else if (x < 100) { h[2:7] = 3; } else { h[3:4] = 4; } if (x >= 100) { h[1:6] = 5; }

Partial override with conditions

char *g = malloc(128); memset(g, 42, 20); memset(g, 66, x);

Memset with symbolic length

slide-155
SLIDE 155

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Solution 3: Object-chunk memory model

155

char *p = malloc(e);

Obj. Pointer Size Condition 1 0x0001_0000 5 x == 0 2 0x0002_0000 10 x >= 2 3 0x0003_0000 15 x == 1

slide-156
SLIDE 156

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Solution 3: Object-chunk memory model

156

char *p = malloc(e);

Obj. Pointer Size Condition 1 0x0001_0000 5 x == 0 2 0x0002_0000 10 x >= 2 3 0x0003_0000 15 x == 1

Chunk Offset Length Value Cond. Blob Live Chunk Offset Length Value Cond. Blob Live Chunk Offset Length Value Cond. Blob Live

slide-157
SLIDE 157

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Solution 3: Object-chunk memory model

157

char *p = malloc(e);

Obj. Pointer Size Condition 1 0x0001_0000 5 x == 0 2 0x0002_0000 10 x >= 2 3 0x0003_0000 15 x == 1

Chunk Offset Length Value Cond. Blob Live 1 2 1 42 TRUE store (2, 42) TRUE Chunk Offset Length Value Cond. Blob Live 1 2 1 42 TRUE store (2, 42) TRUE Chunk Offset Length Value Cond. Blob Live 1 2 1 42 TRUE store (2, 42) TRUE

p[2] = 42;

slide-158
SLIDE 158

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Solution 3: Object-chunk memory model

158

char *p = malloc(e);

Obj. Pointer Size Condition 1 0x0001_0000 5 x == 0 2 0x0002_0000 10 x >= 2 3 0x0003_0000 15 x == 1

Chunk Offset Length Value Cond. Blob Live 1 2 1 42 TRUE store (2, 42) FALSE 2 2 1 42 TRUE store (2, 0) TRUE Chunk Offset Length Value Cond. Blob Live 1 2 1 42 TRUE store (2, 42) FALSE 2 2 1 42 TRUE store (2, 0) TRUE Chunk Offset Length Value Cond. Blob Live 1 2 1 42 TRUE store (2, 42) FALSE 2 2 1 42 TRUE store (2, 0) TRUE

p[2] = 42; p[2] = 0;

slide-159
SLIDE 159

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Solution 3: Object-chunk memory model

159

Chunk Offset Length Value Cond. Blob Live

char *h = malloc(8); h[0:7] = 1; if (x > 100) { h[0:5] = 2; } else if (x < 100) { h[2:7] = 3; } else { h[3:4] = 4; } if (x >= 100) { h[1:6] = 5; }

slide-160
SLIDE 160

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Solution 3: Object-chunk memory model

160

Chunk Offset Length Value Cond. Blob Live 1 8 1 TRUE 11111111 TRUE

char *h = malloc(8); h[0:7] = 1; if (x > 100) { h[0:5] = 2; } else if (x < 100) { h[2:7] = 3; } else { h[3:4] = 4; } if (x >= 100) { h[1:6] = 5; }

slide-161
SLIDE 161

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Solution 3: Object-chunk memory model

161

Chunk Offset Length Value Cond. Blob Live 1 8 1 TRUE 11111111 x <= 100 2 6 2 x > 100 22222211 x > 100

char *h = malloc(8); h[0:7] = 1; if (x > 100) { h[0:5] = 2; } else if (x < 100) { h[2:7] = 3; } else { h[3:4] = 4; } if (x >= 100) { h[1:6] = 5; }

slide-162
SLIDE 162

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Solution 3: Object-chunk memory model

162

Chunk Offset Length Value Cond. Blob Live 1 8 1 TRUE 11111111 x == 100 2 6 2 x > 100 22222211 x > 100 3 2 6 3 x < 100 11333333 x < 100

char *h = malloc(8); h[0:7] = 1; if (x > 100) { h[0:5] = 2; } else if (x < 100) { h[2:7] = 3; } else { h[3:4] = 4; } if (x >= 100) { h[1:6] = 5; }

slide-163
SLIDE 163

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Solution 3: Object-chunk memory model

163

Chunk Offset Length Value Cond. Blob Live 1 8 1 TRUE 11111111 FALSE 2 6 2 x > 100 22222211 x > 100 3 2 6 3 x < 100 11333333 x < 100 4 3 2 4 x == 100 11144111 x == 100

char *h = malloc(8); h[0:7] = 1; if (x > 100) { h[0:5] = 2; } else if (x < 100) { h[2:7] = 3; } else { h[3:4] = 4; } if (x >= 100) { h[1:6] = 5; }

slide-164
SLIDE 164

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Solution 3: Object-chunk memory model

164

Chunk Offset Length Value Cond. Blob Live 1 8 1 TRUE 11111111 FALSE 2 6 2 x > 100 22222211 FALSE 3 2 6 3 x < 100 11333333 x < 100 4 3 2 4 x == 100 11144111 FALSE 5 1 6 5 x > 100 25555551 x > 100 6 1 6 5 x == 100 15555551 x == 100

char *h = malloc(8); h[0:7] = 1; if (x > 100) { h[0:5] = 2; } else if (x < 100) { h[2:7] = 3; } else { h[3:4] = 4; } if (x >= 100) { h[1:6] = 5; }

slide-165
SLIDE 165

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

KSA Symbolic Executor

A new design for kernel symbolic execution

165

Gated representation Loop modeling with recursion Object-chunk memory model Concurrency versioning

slide-166
SLIDE 166

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

KSA Symbolic Executor

A new design for kernel symbolic execution

166

Gated representation Loop modeling with recursion Object-chunk memory model Concurrency versioning

Kernel source code LLVM bitcode module

1

slide-167
SLIDE 167

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

KSA Symbolic Executor

A new design for kernel symbolic execution

167

Gated representation Loop modeling with recursion Object-chunk memory model Concurrency versioning

Kernel source code LLVM bitcode module

1

module_init annotation Baseline symbolic representation (e.g., initialize global variables, memory layouts, etc)

2

slide-168
SLIDE 168

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

KSA Symbolic Executor

A new design for kernel symbolic execution

168

Gated representation Loop modeling with recursion Object-chunk memory model Concurrency versioning

Kernel source code LLVM bitcode module

1

module_init annotation Baseline symbolic representation (e.g., initialize global variables, memory layouts, etc)

2 3

Symbolic representation of the multi-threaded program

syscall_1 syscall_2 … syscall_m syscall_3 syscall_4 … syscall_n

A multi-threaded program

slide-169
SLIDE 169

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

KSA Symbolic Executor

A new design for kernel symbolic execution

169

Gated representation Loop modeling with recursion Object-chunk memory model Concurrency versioning

Kernel source code LLVM bitcode module

1

module_init annotation Baseline symbolic representation (e.g., initialize global variables, memory layouts, etc)

2 3

Symbolic representation of the multi-threaded program

syscall_1 syscall_2 … syscall_m syscall_3 syscall_4 … syscall_n

A multi-threaded program Mathematic models for checkers

4

Counter examples Proof of no errors

slide-170
SLIDE 170

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Ongoing research on the KSA framework

170

  • Integration with bug definitions
  • Memory errors
  • Data races
  • Incorrect locking
  • Integration with SMT backends
  • Expression simplifier
  • ML-based constraint solver
  • Conditional abstraction
slide-171
SLIDE 171

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Agenda

171

  • 1. What are race conditions?
  • 2. Finding their presence with fuzzing?

[SP’20] Data races in file systems

  • 3. Towards a more systematic methodology?

[SP’18] Symbolic race checking

  • 4. Up to the extreme of completeness and soundness?

[WIP (CAV’21)] C to SMT transpilation

slide-172
SLIDE 172

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Acknowledgement

172

Taesoo Kim Wenke Lee Alessandro Orso Brendan Saltaformaggio Marcus Peinado Michael Backes Xinyu Xing Byoungyoung Lee Chengyu Song Kangjie Lu Yeongjin Jang Sangho Lee Yang Ji Changwoo Min Hanqing Zhao Jungyeon Yoon Steffen Maass Mohan Kumar Chenxiong Qian Ruian Duan Seulbae Kim Fan Sang Ren Ding Wen Xu Ming-Wei Shih Insu Yun Sanidhya Kashap Daehee Jang Hong Hu Paul England Manuel Huber Zhichuang Sun

slide-173
SLIDE 173

Meng Xu (Georgia Tech) Finding Race Conditions in Kernels July 16, 2020

Summary

173

Concept

  • Alias coverage
  • Formal bug definitions
  • Lossless C to SMT transpilation

Future work

  • Working with the SMT community to solve the constraints generated by KSA.
  • Extending the techniques for checking properties on neural networks.
  • Symbolic representation of re-entrant programs (e.g., protocol-ed programs).

Impact

  • 50+ bugs found and reported
  • All tools open-sourced