precise and scalable detection of double fetch bugs in os
play

Precise and Scalable Detection of Double-Fetch Bugs in OS Kernels - PowerPoint PPT Presentation

Precise and Scalable Detection of Double-Fetch Bugs in OS Kernels Meng Xu , Chenxiong Qian, Kangjie Lu + , Michael Backes*, Taesoo Kim Georgia Tech | University of Minnesota + | CISPA, Germany* 1 What is Double-Fetch? Address Space


  1. Precise and Scalable Detection of Double-Fetch Bugs in OS Kernels Meng Xu , Chenxiong Qian, Kangjie Lu + , Michael Backes*, Taesoo Kim Georgia Tech | University of Minnesota + | CISPA, Germany* � 1

  2. What is Double-Fetch?

  3. Address Space Separation 0x00000000 User / Program 3 GB Address Space 0xC0000000 Kernel 1 GB Address Space 0xFFFFFFFF A Typical Address Space Separation Scheme with a 32-bit Virtual Address Space � 3

  4. No Dereference on Userspace Pointers 0x00000000 User / Program 3 GB Address Space 0xDEADBEEF 0xC0000000 void kfunc (int __user *uptr, int *kptr) { Kernel 1 GB …… Address Space Uninitialized } 0xFFFFFFFF A Typical Address Space Separation Scheme with a 32-bit Virtual Address Space � 4

  5. No Dereference on Userspace Pointers 0x00000000 User / Program 3 GB Address Space 0xDEADBEEF 0xDEADBEEF 0xC0000000 void kfunc (int __user *uptr, int *kptr) { Kernel 1 GB …… Address Space 0xDEADBEEF Uninitialized } 0xFFFFFFFF A Typical Address Space Separation Scheme with a 32-bit Virtual Address Space � 5

  6. No Dereference on Userspace Pointers 0x00000000 User / Program 3 GB Address Space 0xDEADBEEF 0xC0000000 void kfunc (int __user *uptr, int *kptr) { Kernel 1 GB *kptr = *uptr; …… Address Space 0xDEADBEEF Uninitialized } 0xFFFFFFFF A Typical Address Space Separation Scheme with a 32-bit Virtual Address Space � 6

  7. No Dereference on Userspace Pointers 0x00000000 User / Program 3 GB Address Space 0xDEADBEEF 0xC0000000 void kfunc (int __user *uptr, int *kptr) { Kernel 1 GB copy_from_user(kptr, uptr, 4); …… Address Space 0xDEADBEEF Uninitialized } 0xFFFFFFFF A Typical Address Space Separation Scheme with a 32-bit Virtual Address Space � 7

  8. Shared Userspace Pointer Across Threads 0x00000000 …… User / Program 3 GB Address Space 0xDEADBEEF 0xDEADBEEF 0xC0000000 void kfunc (int __user *uptr, int *kptr) { Kernel 1 GB copy_from_user(kptr, uptr, 4); …… Address Space 0xDEADBEEF Uninitialized } 0xFFFFFFFF A Typical Address Space Separation Scheme with a 32-bit Virtual Address Space � 8

  9. Shared Userspace Pointer Across Threads 0x00000000 …… User / Program 3 GB Address Space 0xDEADBEEF 0xDEADBEEF 0xC0000000 void kfunc (int __user *uptr, int *kptr) { Kernel 1 GB copy_from_user(kptr, uptr, 4); …… Address Space 0xDEADBEEF Uninitialized } 0xFFFFFFFF A Typical Address Space Separation Scheme with a 32-bit Virtual Address Space � 9

  10. Why Double-Fetch? 1 static int perf_copy_attr_simplified ?? bytes 2 (struct perf_event_attr __user *uattr, 3 struct perf_event_attr *attr) { 4 5 u32 size; 6 7 // first fetch 8 if (get_user(size, &uattr->size)) 9 return -EFAULT; 10 11 // sanity checks 12 if (size > PAGE_SIZE || 13 size < PERF_ATTR_SIZE_VER0) 14 return -EINVAL; 15 16 // second fetch 17 if (copy_from_user(attr, uattr, size)) 18 return -EFAULT; 19 20 ...... 21 } 22 23 // BUG: when attr->size is used later 24 memcpy(buf, attr, attr->size); Adapted from perf_copy_attr in file kernel/events/core.c � 10

  11. Why Double-Fetch? 1 static int perf_copy_attr_simplified ?? bytes 2 (struct perf_event_attr __user *uattr, 3 struct perf_event_attr *attr) { 30 4 5 u32 size; 4 bytes 6 7 // first fetch 8 if (get_user(size, &uattr->size)) 9 return -EFAULT; 10 11 // sanity checks 12 if (size > PAGE_SIZE || 13 size < PERF_ATTR_SIZE_VER0) 14 return -EINVAL; 15 16 // second fetch 17 if (copy_from_user(attr, uattr, size)) 18 return -EFAULT; 19 20 ...... 21 } 22 23 // BUG: when attr->size is used later 24 memcpy(buf, attr, attr->size); Adapted from perf_copy_attr in file kernel/events/core.c � 11

  12. Why Double-Fetch? 1 static int perf_copy_attr_simplified ?? bytes 2 (struct perf_event_attr __user *uattr, 3 struct perf_event_attr *attr) { 30 30 4 5 u32 size; 4 bytes 6 7 // first fetch 8 if (get_user(size, &uattr->size)) 30 9 return -EFAULT; 10 11 // sanity checks 12 if (size > PAGE_SIZE || 13 size < PERF_ATTR_SIZE_VER0) 14 return -EINVAL; 15 16 // second fetch 17 if (copy_from_user(attr, uattr, size)) 18 return -EFAULT; 19 20 ...... 21 } 22 23 // BUG: when attr->size is used later 24 memcpy(buf, attr, attr->size); Adapted from perf_copy_attr in file kernel/events/core.c � 12

  13. Why Double-Fetch? 1 static int perf_copy_attr_simplified ?? bytes 2 (struct perf_event_attr __user *uattr, 3 struct perf_event_attr *attr) { 30 30 4 5 u32 size; 4 bytes 6 7 // first fetch 8 if (get_user(size, &uattr->size)) 30 9 return -EFAULT; 10 11 // sanity checks 12 if (size > PAGE_SIZE || 13 size < PERF_ATTR_SIZE_VER0) 14 return -EINVAL; 15 16 // second fetch 17 if (copy_from_user(attr, uattr, size)) 18 return -EFAULT; 19 20 ...... 21 } 22 23 // BUG: when attr->size is used later 24 memcpy(buf, attr, attr->size); Adapted from perf_copy_attr in file kernel/events/core.c � 13

  14. Why Double-Fetch? 1 static int perf_copy_attr_simplified 30 bytes 2 (struct perf_event_attr __user *uattr, 3 struct perf_event_attr *attr) { 30 30 4 5 u32 size; 4 bytes 6 7 // first fetch 8 if (get_user(size, &uattr->size)) 30 9 return -EFAULT; 10 11 // sanity checks 12 if (size > PAGE_SIZE || 13 size < PERF_ATTR_SIZE_VER0) 14 return -EINVAL; 15 16 // second fetch 17 if (copy_from_user(attr, uattr, size)) 18 return -EFAULT; 19 20 ...... 21 } 22 23 // BUG: when attr->size is used later 24 memcpy(buf, attr, attr->size); Adapted from perf_copy_attr in file kernel/events/core.c � 14

  15. Why Double-Fetch? 1 static int perf_copy_attr_simplified 30 bytes 2 (struct perf_event_attr __user *uattr, 3 struct perf_event_attr *attr) { 30 30 4 5 u32 size; 4 bytes 6 7 // first fetch 8 if (get_user(size, &uattr->size)) 30 9 return -EFAULT; 10 11 // sanity checks 12 if (size > PAGE_SIZE || 13 size < PERF_ATTR_SIZE_VER0) 14 return -EINVAL; 15 16 // second fetch 17 if (copy_from_user(attr, uattr, size)) 30 18 return -EFAULT; 19 20 ...... 21 } 22 23 // BUG: when attr->size is used later 24 memcpy(buf, attr, attr->size); Adapted from perf_copy_attr in file kernel/events/core.c � 15

  16. Why Double-Fetch? 1 static int perf_copy_attr_simplified 30 bytes 2 (struct perf_event_attr __user *uattr, 3 struct perf_event_attr *attr) { 30 4 5 u32 size; 4 bytes 6 7 // first fetch 8 if (get_user(size, &uattr->size)) 30 9 return -EFAULT; 10 11 // sanity checks 12 if (size > PAGE_SIZE || 13 size < PERF_ATTR_SIZE_VER0) 14 return -EINVAL; 15 16 // second fetch 17 if (copy_from_user(attr, uattr, size)) 30 18 return -EFAULT; 19 20 ...... 21 } 22 23 // BUG: when attr->size is used later 24 memcpy(buf, attr, attr->size); Adapted from perf_copy_attr in file kernel/events/core.c � 16

  17. What Goes Wrong in This Process?

  18. Up-until First-Fetch 1 static int perf_copy_attr_simplified ?? bytes 2 (struct perf_event_attr __user *uattr, 3 struct perf_event_attr *attr) { 30 30 4 5 u32 size; 4 bytes 6 7 // first fetch 8 if (get_user(size, &uattr->size)) 30 9 return -EFAULT; 10 11 // sanity checks 12 if (size > PAGE_SIZE || 13 size < PERF_ATTR_SIZE_VER0) 14 return -EINVAL; 15 16 // second fetch 17 if (copy_from_user(attr, uattr, size)) 18 return -EFAULT; 19 20 ...... 21 } 22 23 // BUG: when attr->size is used later 24 memcpy(buf, attr, attr->size); Adapted from perf_copy_attr in file kernel/events/core.c � 18

  19. Wrong Assumption: Atomicity in Syscall 1 static int perf_copy_attr_simplified 30 bytes 2 (struct perf_event_attr __user *uattr, 3 struct perf_event_attr *attr) { 65535 30 4 5 u32 size; 4 bytes 6 7 // first fetch 8 if (get_user(size, &uattr->size)) 30 9 return -EFAULT; 10 11 // sanity checks 12 if (size > PAGE_SIZE || 13 size < PERF_ATTR_SIZE_VER0) 14 return -EINVAL; 15 16 // second fetch 17 if (copy_from_user(attr, uattr, size)) 18 return -EFAULT; 19 20 ...... 21 } 22 23 // BUG: when attr->size is used later 24 memcpy(buf, attr, attr->size); Adapted from perf_copy_attr in file kernel/events/core.c � 19

  20. Wrong Assumption: Atomicity in Syscall 1 static int perf_copy_attr_simplified 30 bytes 2 (struct perf_event_attr __user *uattr, 3 struct perf_event_attr *attr) { 65535 65535 4 5 u32 size; 4 bytes 6 7 // first fetch 8 if (get_user(size, &uattr->size)) 30 9 return -EFAULT; 10 11 // sanity checks 12 if (size > PAGE_SIZE || 13 size < PERF_ATTR_SIZE_VER0) 14 return -EINVAL; 15 16 // second fetch 17 if (copy_from_user(attr, uattr, size)) 65535 18 return -EFAULT; 19 20 ...... 21 } 22 23 // BUG: when attr->size is used later 24 memcpy(buf, attr, attr->size); Adapted from perf_copy_attr in file kernel/events/core.c � 20

  21. When The Exploit Happens 1 static int perf_copy_attr_simplified 30 bytes 2 (struct perf_event_attr __user *uattr, 3 struct perf_event_attr *attr) { 65535 4 5 u32 size; 4 bytes 6 7 // first fetch 8 if (get_user(size, &uattr->size)) 30 9 return -EFAULT; 10 11 // sanity checks 12 if (size > PAGE_SIZE || 13 size < PERF_ATTR_SIZE_VER0) 14 return -EINVAL; 15 16 // second fetch 17 if (copy_from_user(attr, uattr, size)) 65535 18 return -EFAULT; 19 20 ...... 21 } 22 23 // BUG: when attr->size is used later kernel information leak! 24 copy_to_user(ubuf, attr, attr->size); Adapted from perf_copy_attr in file kernel/events/core.c � 21

  22. Why Double-Fetch is Prevalent in Kernels? 1. Size checking 2. Dependency look-up 3. Protocol/signature check 4. Information guessing 5. ……

  23. Double-Fetch: Dependency Lookup Adapted from __mptctl_ioctl in file drivers/message/fusion/mptctl.c � 23

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend