/
Shreds: Fine-grained Execution Units with Private Memory Shreds: Fine-grained Execution Units with Private Memory

Shreds: Fine-grained Execution Units with Private Memory - PowerPoint Presentation

sherrill-nordquist
sherrill-nordquist . @sherrill-nordquist
Follow
381 views
Uploaded On 2018-03-17

Shreds: Fine-grained Execution Units with Private Memory - PPT Presentation

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

auth len cur str len auth str cur res prot physpage domain passwd shred level string 1023 int pool

Share:

Link:

Embed:

Download Presentation from below link

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.


Presentation Transcript

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?