1 / 47

Shreds: Fine-grained Execution Units with Private Memory

Shreds: Fine-grained Execution Units with Private Memory. Landon Cox February 21, 2018. Parts of a process. Threads Sequences of executing instructions Active: do things Address space Data the process uses as it runs Passive: acted upon by threads File descriptors

shodgson
Download Presentation

Shreds: Fine-grained Execution Units with Private Memory

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Shreds: Fine-grained Execution Units with Private Memory Landon Cox February 21, 2018

  2. Parts of a process • Threads • Sequences of executing instructions • Active: do things • Address space • Data the process uses as it runs • Passive: acted upon by threads • File descriptors • Communication channels (e.g., files, sockets, pipes) • Passive: read-from/written-to by threads

  3. Parts of a process Process Thread 1 Thread 2 File descriptors Page table Stack 1 Stack 2 Readable pages Writable pages TCP socket Open file Each thread has its own stack, but everything else is share: same pages, file descriptors

  4. Parts of a process Threads are not well isolated from each other. Process Thread 1 Thread 2 File descriptors Page table Stack 1 Stack 2 Readable pages Writable pages TCP socket Open file Threads can run in parallel on different cores.

  5. Parts of a process (revised) Process Thread 1 Thread 2 File descriptors Page table Stack 1 Stack 2 Readable pages Writable pages TCP socket Open file If one thread fails, entire process fails.

  6. Parts of a process (revised) Process Thread 2 File descriptors Page table Stack 1 Stack 2 Readable pages Writable pages TCP socket Open file Compromising a thread, compromises all data.

  7. Parts of a process (revised) Thread 2 Stack 1 Stack 2 Readable pages Writable pages TCP socket Open file Compromising a thread, compromises all data.

  8. Parts of a process (revised) Thread 2 Stack 1 Stack 2 Readable pages Writable pages TCP socket Open file See: heartbleed, cloudbleed, etc.

  9. Heartbleed

  10. Threads vs shreds • How do you define a thread’s work? • Pass in a starting method • The thread exits when the starting function exits • What part of the address space can a thread access? • A thread can access any read- or write-enabled page • All threads are bound by the same protections • A shred’s work can be more or less than a method • Enter a shred using: shred_enter • Exit a shred using: shred_exit • A shred can access secrets in a private memory pool (s-pool)

  11. Shred protection guarantees • Exclusive access to an s-pool • Only associated shreds can access data in an s-pool • Other threads, unassociated shreds cannot access • No leaks • S-pool data cannot be copied w/o sanitization • Use static analysis to identify outgoing data flows • Untampered execution • Shred code cannot be changed or routed elsewhere • i.e., control-flow integrity w/i shred (including libs) S-driver S-compiler

  12. Shred protection guarantees • Exclusive access to an s-pool • Only associated shreds can access data in an s-pool • Other threads, unassociated shreds cannot access S-driver

  13. S-driver • ARM memory domains • Provide memory-access control independent of page protections • 4-bit tags specified in top-level page tables • Access level for each domain set via per-core register (DACR) • MMU checks domain access for virtual memory address • Three access levels specified in DACR • No-access mode: all accesses to domain memory fail • Manager mode: all access to domain memory are allowed • Client mode: all accesses obey page protections

  14. Two-level table 4-bit flag in top-level entry 0 1 … ? 1023 Level 1 Domain 0 Domain 0 Domain 0 NULL NULL Level 2 0: PhysPage, Res, Prot 0: PhysPage, Res, Prot 1: PhysPage, Res, Prot 1: PhysPage, Res, Prot … … 1023: PhysPage, Res, Prot ? 1023: PhysPage, Res, Prot ?

  15. Two-level table All memory under domain 0 0 1 … ? 1023 Level 1 Domain 0 Domain 0 Domain 0 NULL NULL Level 2 0: PhysPage, Res, Prot 0: PhysPage, Res, Prot 1: PhysPage, Res, Prot 1: PhysPage, Res, Prot … … 1023: PhysPage, Res, Prot ? 1023: PhysPage, Res, Prot ?

  16. Two-level table Top 4MB now in domain 1 0 1 … ? 1023 Level 1 Domain 0 Domain 1 Domain 0 NULL NULL Level 2 0: PhysPage, Res, Prot 0: PhysPage, Res, Prot 1: PhysPage, Res, Prot 1: PhysPage, Res, Prot … … 1023: PhysPage, Res, Prot ? 1023: PhysPage, Res, Prot ?

  17. Two-level table Can put other regions under other domains 0 1 … ? 1023 Level 1 Domain 0 Domain 1 Domain 2 NULL NULL Level 2 0: PhysPage, Res, Prot 0: PhysPage, Res, Prot 1: PhysPage, Res, Prot 1: PhysPage, Res, Prot … … 1023: PhysPage, Res, Prot ? 1023: PhysPage, Res, Prot ?

  18. Two-level table 0 1 … ? 1023 Level 1 Domain 0 Domain 1 Domain 2 NULL NULL Level 2 0: PhysPage, Res, Prot 0: PhysPage, Res, Prot 1: PhysPage, Res, Prot 1: PhysPage, Res, Prot … … 1023: PhysPage, Res, Prot ? 1023: PhysPage, Res, Prot ? Each core has a 32-bit DACR

  19. Two-level table 0 1 … ? 1023 Level 1 Domain 0 Domain 1 Domain 2 NULL NULL Level 2 0: PhysPage, Res, Prot 0: PhysPage, Res, Prot 1: PhysPage, Res, Prot 1: PhysPage, Res, Prot … … 1023: PhysPage, Res, Prot ? 1023: PhysPage, Res, Prot ? 16 domains x 2 mode bits

  20. Two-level table 0 1 … ? 1023 Level 1 Domain 0 Domain 1 Domain 2 NULL NULL Level 2 0: PhysPage, Res, Prot 0: PhysPage, Res, Prot 1: PhysPage, Res, Prot 1: PhysPage, Res, Prot … … 1023: PhysPage, Res, Prot ? 1023: PhysPage, Res, Prot ? Mode bits encode client, no-access, manager modes

  21. Two-level table 0 1 … ? 1023 Level 1 Domain 0 Domain 1 Domain 2 NULL NULL Level 2 0: PhysPage, Res, Prot 0: PhysPage, Res, Prot 1: PhysPage, Res, Prot 1: PhysPage, Res, Prot … … 1023: PhysPage, Res, Prot ? 1023: PhysPage, Res, Prot ? Note changing DACR does not require TLB flush!

  22. Two-level table 0 1 … ? 1023 Level 1 Domain 0 Domain 1 Domain 2 NULL NULL Level 2 0: PhysPage, Res, Prot 0: PhysPage, Res, Prot 1: PhysPage, Res, Prot 1: PhysPage, Res, Prot … … 1023: PhysPage, Res, Prot ? 1023: PhysPage, Res, Prot ? Mode change should be faster than page change

  23. Two-level table Problem with only 16 domains? 0 1 … ? 1023 Level 1 Domain 0 Domain 1 Domain 2 NULL NULL Level 2 0: PhysPage, Res, Prot 0: PhysPage, Res, Prot 1: PhysPage, Res, Prot 1: PhysPage, Res, Prot … … 1023: PhysPage, Res, Prot ? 1023: PhysPage, Res, Prot ?

  24. Linux Page permissions Unused No access 15 14 … 10 9 8 7 6 5 4 3 2 1 0 Every s-pool is assigned a memory domain (e.g., 3-7)

  25. Linux Page permissions Unused No access 15 14 … 10 9 8 7 6 5 4 3 2 1 0 Assignments change depending on if shred is active and on which core.

  26. Linux Page permissions Unused No access 15 14 … 10 9 8 7 6 5 4 3 2 1 0 Each core gets an exclusive domain

  27. 15 14 … 10 9 8 7 6 5 4 3 2 1 0 All inactive shreds’ s-pools are tagged w/ red domain. While shred is active on core, its s-pool is tagged w/ core’s green domain.

  28. Say we load shred 0 onto core 0. 15 14 … 10 9 8 7 6 5 4 3 2 1 0 S0

  29. Which domain does S0’s s-pool need to be tagged with? 15 14 … 10 9 8 7 6 5 4 3 2 1 0 S0

  30. Why will S0 be able to access its s-pool? 15 14 … 10 9 8 7 6 5 4 3 2 1 0 S0

  31. Why can’t other shreds access S0’s s-pool? 15 14 … 10 9 8 7 6 5 4 3 2 1 0 S0

  32. Can S0 run in parallel on > 1 core? 15 14 … 10 9 8 7 6 5 4 3 2 1 0 S0

  33. How do we tag S0’s s-pool when it’s done? Why? 15 14 … 10 9 8 7 6 5 4 3 2 1 0 S0

  34. What happens to the TLB on when an s-pool’s tag changes? 15 14 … 10 9 8 7 6 5 4 3 2 1 0 S0

  35. Where does a shred’s stack have to reside? Why? 15 14 … 10 9 8 7 6 5 4 3 2 1 0 S0

  36. inthttp_request_parse(server *srv, connection *con) { … /* inside the request parsing loop */ char *cur; /* current parsing offset */ char auth_str[] = "Authorization"; intauth_str_len = strlen(auth_str); if (strncmp(cur, auth_str, auth_str_len)==0){ shred_enter(AUTH_PASSWD_POOL); /* object holding passwd in spool */ data_string *ds = s_ds_init(); intpw_len = get_passwd_length(cur); cur += auth_str_len + 1; buffer_copy_string_len(ds->key, auth_str, auth_str_len); buffer_copy_string_len(ds->value, cur, pw_len); /* add ds to header pointer array */ array_insert_unique(parsed_headers, ds); /* only related shreds can deref ds */ /* wipe out passwd from input stream */ memset(cur, 0, pw_len); cur += pw_len; shred_exit(); } … }

  37. inthttp_request_parse(server *srv, connection *con) { … /* inside the request parsing loop */ char *cur; /* current parsing offset */ char auth_str[] = "Authorization"; intauth_str_len = strlen(auth_str); if (strncmp(cur, auth_str, auth_str_len)==0){ shred_enter(AUTH_PASSWD_POOL); /* object holding passwd in spool */ data_string *ds = s_ds_init(); intpw_len = get_passwd_length(cur); cur += auth_str_len + 1; buffer_copy_string_len(ds->key, auth_str, auth_str_len); buffer_copy_string_len(ds->value, cur, pw_len); /* add ds to header pointer array */ array_insert_unique(parsed_headers, ds); /* only related shreds can deref ds */ /* wipe out passwd from input stream */ memset(cur, 0, pw_len); cur += pw_len; shred_exit(); } … } Parse authorization request.

  38. inthttp_request_parse(server *srv, connection *con) { … /* inside the request parsing loop */ char *cur; /* current parsing offset */ char auth_str[] = "Authorization"; intauth_str_len = strlen(auth_str); if (strncmp(cur, auth_str, auth_str_len)==0){ shred_enter(AUTH_PASSWD_POOL); /* object holding passwd in spool */ data_string *ds = s_ds_init(); intpw_len = get_passwd_length(cur); cur += auth_str_len + 1; buffer_copy_string_len(ds->key, auth_str, auth_str_len); buffer_copy_string_len(ds->value, cur, pw_len); /* add ds to header pointer array */ array_insert_unique(parsed_headers, ds); /* only related shreds can deref ds */ /* wipe out passwd from input stream */ memset(cur, 0, pw_len); cur += pw_len; shred_exit(); } … } Enter authorization shred.

  39. inthttp_request_parse(server *srv, connection *con) { … /* inside the request parsing loop */ char *cur; /* current parsing offset */ char auth_str[] = "Authorization"; intauth_str_len = strlen(auth_str); if (strncmp(cur, auth_str, auth_str_len)==0){ shred_enter(AUTH_PASSWD_POOL); /* object holding passwd in spool */ data_string *ds = s_ds_init(); intpw_len = get_passwd_length(cur); cur += auth_str_len + 1; buffer_copy_string_len(ds->key, auth_str, auth_str_len); buffer_copy_string_len(ds->value, cur, pw_len); /* add ds to header pointer array */ array_insert_unique(parsed_headers, ds); /* only related shreds can deref ds */ /* wipe out passwd from input stream */ memset(cur, 0, pw_len); cur += pw_len; shred_exit(); } … } Allocate a new string in the s-pool.

  40. inthttp_request_parse(server *srv, connection *con) { … /* inside the request parsing loop */ char *cur; /* current parsing offset */ char auth_str[] = "Authorization"; intauth_str_len = strlen(auth_str); if (strncmp(cur, auth_str, auth_str_len)==0){ shred_enter(AUTH_PASSWD_POOL); /* object holding passwd in spool */ data_string *ds = s_ds_init(); intpw_len = get_passwd_length(cur); cur += auth_str_len + 1; buffer_copy_string_len(ds->key, auth_str, auth_str_len); buffer_copy_string_len(ds->value, cur, pw_len); /* add ds to header pointer array */ array_insert_unique(parsed_headers, ds); /* only related shreds can deref ds */ /* wipe out passwd from input stream */ memset(cur, 0, pw_len); cur += pw_len; shred_exit(); } … } Move input to the password data.

  41. inthttp_request_parse(server *srv, connection *con) { … /* inside the request parsing loop */ char *cur; /* current parsing offset */ char auth_str[] = "Authorization"; intauth_str_len = strlen(auth_str); if (strncmp(cur, auth_str, auth_str_len)==0){ shred_enter(AUTH_PASSWD_POOL); /* object holding passwd in spool */ data_string *ds = s_ds_init(); intpw_len = get_passwd_length(cur); cur += auth_str_len + 1; buffer_copy_string_len(ds->key, auth_str, auth_str_len); buffer_copy_string_len(ds->value, cur, pw_len); /* add ds to header pointer array */ array_insert_unique(parsed_headers, ds); /* only related shreds can deref ds */ /* wipe out passwd from input stream */ memset(cur, 0, pw_len); cur += pw_len; shred_exit(); } … } Copy the password into the s-pool

  42. inthttp_request_parse(server *srv, connection *con) { … /* inside the request parsing loop */ char *cur; /* current parsing offset */ char auth_str[] = "Authorization"; intauth_str_len = strlen(auth_str); if (strncmp(cur, auth_str, auth_str_len)==0){ shred_enter(AUTH_PASSWD_POOL); /* object holding passwd in spool */ data_string *ds = s_ds_init(); intpw_len = get_passwd_length(cur); cur += auth_str_len + 1; buffer_copy_string_len(ds->key, auth_str, auth_str_len); buffer_copy_string_len(ds->value, cur, pw_len); /* add ds to header pointer array */ array_insert_unique(parsed_headers, ds); /* only related shreds can deref ds */ /* wipe out passwd from input stream */ memset(cur, 0, pw_len); cur += pw_len; shred_exit(); } … } Mark the authorization header as parsed.

  43. inthttp_request_parse(server *srv, connection *con) { … /* inside the request parsing loop */ char *cur; /* current parsing offset */ char auth_str[] = "Authorization"; intauth_str_len = strlen(auth_str); if (strncmp(cur, auth_str, auth_str_len)==0){ shred_enter(AUTH_PASSWD_POOL); /* object holding passwd in spool */ data_string *ds = s_ds_init(); intpw_len = get_passwd_length(cur); cur += auth_str_len + 1; buffer_copy_string_len(ds->key, auth_str, auth_str_len); buffer_copy_string_len(ds->value, cur, pw_len); /* add ds to header pointer array */ array_insert_unique(parsed_headers, ds); /* only related shreds can deref ds */ /* wipe out passwd from input stream */ memset(cur, 0, pw_len); cur += pw_len; shred_exit(); } … } Delete the password

  44. inthttp_request_parse(server *srv, connection *con) { … /* inside the request parsing loop */ char *cur; /* current parsing offset */ char auth_str[] = "Authorization"; intauth_str_len = strlen(auth_str); if (strncmp(cur, auth_str, auth_str_len)==0){ shred_enter(AUTH_PASSWD_POOL); /* object holding passwd in spool */ data_string *ds = s_ds_init(); intpw_len = get_passwd_length(cur); cur += auth_str_len + 1; buffer_copy_string_len(ds->key, auth_str, auth_str_len); buffer_copy_string_len(ds->value, cur, pw_len); /* add ds to header pointer array */ array_insert_unique(parsed_headers, ds); /* only related shreds can deref ds */ /* wipe out passwd from input stream */ memset(cur, 0, pw_len); cur += pw_len; shred_exit(); } … } Advance the input data.

  45. inthttp_request_parse(server *srv, connection *con) { … /* inside the request parsing loop */ char *cur; /* current parsing offset */ char auth_str[] = "Authorization"; intauth_str_len = strlen(auth_str); if (strncmp(cur, auth_str, auth_str_len)==0){ shred_enter(AUTH_PASSWD_POOL); /* object holding passwd in spool */ data_string *ds = s_ds_init(); intpw_len = get_passwd_length(cur); cur += auth_str_len + 1; buffer_copy_string_len(ds->key, auth_str, auth_str_len); buffer_copy_string_len(ds->value, cur, pw_len); /* add ds to header pointer array */ array_insert_unique(parsed_headers, ds); /* only related shreds can deref ds */ /* wipe out passwd from input stream */ memset(cur, 0, pw_len); cur += pw_len; shred_exit(); } … } Exit the shred.

  46. Switch performance • Comparing switch times • Shred exit • Intra-process thread switch • Process switch • How does this compare to lwCs? • Which approach is better? When?

  47. Course administration • Mid-term exam • One week from today • Will cover everything through today • Project 2 • Will be released later today (due after the mid-term) • Research Project • Suggestions have been posted

More Related