Landon Cox March 3 2017 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 ID: 654112
Download Presentation The PPT/PDF document "Shreds: Fine-grained Execution Units wit..." is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.
Slide1
Shreds: Fine-grained Execution Units with Private Memory
Landon Cox
March
3,
2017Slide2
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 threadsSlide3
Parts of a process
Process
Thread 1
Thread 2
Page table
File descriptors
Stack 1
Stack 2
TCP
socket
Open file
Readable pages
Writable pages
Each thread has its own stack, but everything else
is share: same pages, file descriptorsSlide4
Parts of a
process
Process
Thread 1
Thread 2
Page table
File descriptors
Stack 1
Stack 2
TCP
socket
Open file
Readable pages
Writable pages
Threads
can run in parallel on
different cores.
Threads are not well isolated
from each other.Slide5
Parts of a process (revised)
Process
Thread 1
Thread 2
Page table
File descriptors
Stack 1
Stack 2
TCP
socket
Open file
Readable pages
Writable pages
If one thread fails,
entire process fails.Slide6
Parts of a process (revised)
Process
Thread 2
Page table
File descriptors
Stack 1
Stack 2
TCP
socket
Open file
Readable pages
Writable pages
Compromising a thread, compromises all data.Slide7
Parts of a process (revised)
Thread 2
Stack 1
Stack 2
TCP
socket
Open file
Readable pages
Writable pages
Compromising a thread, compromises all data.Slide8
Parts of a process (revised)
Thread 2
Stack 1
Stack 2
TCP
socket
Open file
Readable pages
Writable pages
See:
heartbleed
,
cloudbleed
, etc.Slide9
HeartbleedSlide10
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 methodEnter a shred using:
shred_enterExit a shred using: shred_exit
A shred can access secrets in a private memory pool (s-pool)Slide11
Shred protection guarantees
Exclusive access to an s-pool
Only associated shreds can access data in an s-pool
Other threads, unassociated shreds
No leaks
S-pool data cannot be copied w/o sanitization
Use static analysis to identify outgoing data flows
Untampered executionShred code cannot be changed or routed elsewhere
i.e., control-flow integrity w/i shred (including libs)
S-driver
S-compilerSlide12
Shred protection guarantees
Exclusive access to an s-pool
Only associated shreds can access data in an s-pool
Other threads, unassociated shreds
S-driverSlide13
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 DACRNo-access mode: all accesses to domain memory failManager mode: all access to domain memory are allowed
Client mode: all accesses obey page protectionsSlide14
Two-level
table
0
1
…
?
0:
PhysPage
, Res, Prot
1:
PhysPage
, Res, Prot
…
Level 1
?
Level 2
0:
PhysPage
, Res, Prot
1:
PhysPage
, Res, Prot
…
?
1023
1023:
PhysPage
, Res, Prot
1023:
PhysPage
, Res, Prot
NULL
NULL
Domain
0
Domain
0
Domain
0
4-bit flag in top-level entrySlide15
Two-level table
0
1
…
?
0:
PhysPage
, Res, Prot
1:
PhysPage
, Res, Prot
…
Level 1
?
Level 2
0:
PhysPage
, Res, Prot
1:
PhysPage
, Res, Prot
…
?
1023
1023:
PhysPage
, Res, Prot
1023:
PhysPage
, Res, Prot
NULL
NULL
Domain
0
Domain
0
Domain
0
All memory under domain 0Slide16
Two-level table
0
1
…
?
0:
PhysPage
, Res, Prot
1:
PhysPage
, Res, Prot
…
Level 1
?
Level 2
0:
PhysPage
, Res, Prot
1:
PhysPage
, Res, Prot
…
?
1023
1023:
PhysPage
, Res, Prot
1023:
PhysPage
, Res, Prot
NULL
NULL
Domain
0
Domain
0
Domain
1
Top 4MB now in domain 1Slide17
Two-level table
0
1
…
?
0:
PhysPage
, Res, Prot
1:
PhysPage
, Res, Prot
…
Level 1
?
Level 2
0:
PhysPage
, Res, Prot
1:
PhysPage
, Res, Prot
…
?
1023
1023:
PhysPage
, Res, Prot
1023:
PhysPage
, Res, Prot
NULL
NULL
Domain
2
Domain
0
Domain
1
Can put other regions
under other domainsSlide18
Two-level table
0
1
…
?
0:
PhysPage
, Res, Prot
1:
PhysPage
, Res, Prot
…
Level 1
?
Level 2
0:
PhysPage
, Res, Prot
1:
PhysPage
, Res, Prot
…
?
1023
1023:
PhysPage
, Res, Prot
1023:
PhysPage
, Res, Prot
NULL
NULL
Domain
2
Domain
0
Domain
1
Each core has a 32-bit DACRSlide19
Two-level table
0
1
…
?
0:
PhysPage
, Res, Prot
1:
PhysPage
, Res, Prot
…
Level 1
?
Level 2
0:
PhysPage
, Res, Prot
1:
PhysPage
, Res, Prot
…
?
1023
1023:
PhysPage
, Res, Prot
1023:
PhysPage
, Res, Prot
NULL
NULL
Domain
2
Domain
0
Domain
1
16 domains x 2 mode bitsSlide20
Two-level table
0
1
…
?
0:
PhysPage
, Res, Prot
1:
PhysPage
, Res, Prot
…
Level 1
?
Level 2
0:
PhysPage
, Res, Prot
1:
PhysPage
, Res, Prot
…
?
1023
1023:
PhysPage
, Res, Prot
1023:
PhysPage
, Res, Prot
NULL
NULL
Domain
2
Domain
0
Domain
1
Mode bits encode client, no-access, manager modesSlide21
Two-level table
0
1
…
?
0:
PhysPage
, Res, Prot
1:
PhysPage
, Res, Prot
…
Level 1
?
Level 2
0:
PhysPage
, Res, Prot
1:
PhysPage
, Res, Prot
…
?
1023
1023:
PhysPage
, Res, Prot
1023:
PhysPage
, Res, Prot
NULL
NULL
Domain
2
Domain
0
Domain
1
Note changing DACR does not require TLB flush!Slide22
Two-level table
0
1
…
?
0:
PhysPage
, Res, Prot
1:
PhysPage
, Res, Prot
…
Level 1
?
Level 2
0:
PhysPage
, Res, Prot
1:
PhysPage
, Res, Prot
…
?
1023
1023:
PhysPage
, Res, Prot
1023:
PhysPage
, Res, Prot
NULL
NULL
Domain
2
Domain
0
Domain
1
M
ode change should be faster than page changeSlide23
Two-level table
0
1
…
?
0:
PhysPage
, Res, Prot
1:
PhysPage
, Res, Prot
…
Level 1
?
Level 2
0:
PhysPage
, Res, Prot
1:
PhysPage
, Res, Prot
…
?
1023
1023:
PhysPage
, Res, Prot
1023:
PhysPage
, Res, Prot
NULL
NULL
Domain
2
Domain
0
Domain
1
Problem with only 16 domains?Slide24
15
14
…
10
9
8
7
6
5
4
3
2
1
0
Linux
No access
Page permissions
Unused
Every s-pool is assigned a memory domain (e.g., 3-7)Slide25
15
14
…
10
9
8
7
6
5
4
3
2
1
0
Linux
No access
Page permissions
Unused
Assignments change depending on if
shred is active and on which core.Slide26
15
14
…
10
9
8
7
6
5
4
3
2
1
0
Linux
No access
Page permissions
Unused
Each core
gets an exclusive domainSlide27
15
14
…
10
9
8
7
6
5
4
3
2
1
0
While shred is active on core, its s-pool is tagged w/ core’s green domain.
All inactive shreds’ s-pools are tagged w/ red domain.Slide28
15
14
…
10
9
8
7
6
5
4
3
2
1
0
Say we load
shred 0 onto core 0.
S0Slide29
15
14
…
10
9
8
7
6
5
4
3
2
1
0
Which domain does S0’s s-pool need to be tagged with?
S0Slide30
15
14
…
10
9
8
7
6
5
4
3
2
1
0
Why will S0 be able to access its s-pool?
S0Slide31
15
14
…
10
9
8
7
6
5
4
3
2
1
0
Why can’t other shreds access
S0’s s-pool?
S0Slide32
15
14
…
10
9
8
7
6
5
4
3
2
1
0
Can S0 run in parallel on > 1 core?
S0Slide33
15
14
…
10
9
8
7
6
5
4
3
2
1
0
How do we tag S0’s s-pool when it’s done? Why?
S0Slide34
15
14
…
10
9
8
7
6
5
4
3
2
1
0
What happens to the TLB on when an
s-pool’s tag changes?
S0Slide35
15
14
…
10
9
8
7
6
5
4
3
2
1
0
Where does a shred’s stack have to reside? Why?
S0Slide36
int
http_request_parse
(server *
srv
,
connection *con) {
… /* inside the request parsing loop */
char *cur; /* current parsing offset */
char auth_str[] = "Authorization";
int
auth_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();
int pw_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
();
}
…
}Slide37
int
http_request_parse
(server *
srv
,
connection *con) {
… /* inside the request parsing loop */
char *cur; /* current parsing offset */
char auth_str[] = "Authorization";
int
auth_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();
int pw_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.Slide38
int
http_request_parse
(server *
srv
,
connection *con) {
… /* inside the request parsing loop */
char *cur; /* current parsing offset */
char auth_str[] = "Authorization";
int
auth_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();
int pw_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.Slide39
int
http_request_parse
(server *
srv
,
connection *con) {
… /* inside the request parsing loop */
char *cur; /* current parsing offset */
char auth_str[] = "Authorization";
int
auth_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();
int pw_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.Slide40
int
http_request_parse
(server *
srv
,
connection *con) {
… /* inside the request parsing loop */
char *cur; /* current parsing offset */
char auth_str[] = "Authorization";
int
auth_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();
int pw_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.Slide41
int
http_request_parse
(server *
srv
,
connection *con) {
… /* inside the request parsing loop */
char *cur; /* current parsing offset */
char auth_str[] = "Authorization";
int
auth_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();
int pw_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-poolSlide42
int
http_request_parse
(server *
srv
,
connection *con) {
… /* inside the request parsing loop */
char *cur; /* current parsing offset */
char auth_str[] = "Authorization";
int
auth_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();
int pw_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.Slide43
int
http_request_parse
(server *
srv
,
connection *con) {
… /* inside the request parsing loop */
char *cur; /* current parsing offset */
char auth_str[] = "Authorization";
int
auth_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();
int pw_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 passwordSlide44
int
http_request_parse
(server *
srv
,
connection *con) {
… /* inside the request parsing loop */
char *cur; /* current parsing offset */
char auth_str[] = "Authorization";
int
auth_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();
int pw_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.Slide45
int
http_request_parse
(server *
srv
,
connection *con) {
… /* inside the request parsing loop */
char *cur; /* current parsing offset */
char auth_str[] = "Authorization";
int
auth_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();
int pw_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.Slide46
Switch performance
Comparing switch times
Shred exit
Intra-process thread switch
Process switch
How does this compare to
lwCs?Which approach is better? When?