Overview and Recent Developments: seccomp and small LSMs Linux - - PowerPoint PPT Presentation
Overview and Recent Developments: seccomp and small LSMs Linux - - PowerPoint PPT Presentation
Overview and Recent Developments: seccomp and small LSMs Linux Security Summit EU October 26, 2018 Edinburgh, Scotland Kees (Case) Cook keescook@chromium.org @kees_cook https://outflux.net/slides/2018/lss-eu/seccomp.pdf Agenda
Agenda
- Background
– what’s a “small” LSM?
- LoadPin
– purpose, recent development, and demo
- Yama
– purpose, recent development, and demo
- seccomp
– why is seccomp not an LSM? – purpose, matching, filters – recent development – demo
Background
- Regular LSMs (SELinux, AppArmor, Smack,
TOMOYO) have a comprehensive policy language covering a full Mandatory Access Control system
- “small” LSMs have a very narrow (or fixed) policy
LoadPin: Overview
- Built with C
O N F I G _ S E C U R I T Y _ L O A D P I N = y
- If you think C
O N F I G _ M O D U L E _ S I G _ F O R C E = y is redundant in your environment, LoadPin is for you!
– Chrome OS uses d
m
- v
e r i t y to provide a cryptographically verified read-only root filesystem
– There is no need to sign modules – they just have to come only from
the root filesystem
- Also protects other files the kernel reads:
– kexec images, firmware, security policy, certs, etc
NOT ACTUAL LOGO
LoadPin: Recent developments
- Thankfully pretty stable (maybe only Chrome OS uses it?)
- v4.20
– human readable device name in initialization output – boot param name changing from “enabled” to “enforce”
LoadPin: Demo
# d f d f
- h
h / t m / t m p / t r / t r u s u s t e t e d F i l e s y s t e m S i z e U s e d A v a i l U s e % M
- u
n t e d
- n
/ d e v / r
- t
2 4 G 1 7 G 6 . 4 G 7 2 % / / d e v / l
- p
4 8 8 M 9 5 6 K 4 5 2 M 1 % / t r u s t e d # i n i n s m s m
- d
- d
/ t / t r u r u s t e s t e d / t / t e s e s t _ t _ m
- d
m
- d
u l e u l e . k . k
- [
. . ] L
- a
d P i n : l
- p
( 7 : ) : w r i t a b l e [ . . ] L
- a
d P i n : e n f
- r
c e m e n t c a n b e d i s a b l e d . [ . . ] L
- a
d P i n : k e r n e l
- m
- d
u l e p i n n e d
- b
j = " / t r u s t e d / t e s t _ m
- d
u l e . k
- "
p i d = 3 2 8 c m d l i n e = " i n s m
- d
/ t r u s t e d / t e s t _ m
- d
u l e . k
- "
[ . . ] t e s t _ m
- d
u l e : H e l l
- ,
w
- r
l d # r m r m m
- m
- d
d t e s t e s t _ m t _ m
- d
- d
u l e u l e [ . . ] t e s t _ m
- d
u l e : G
- d
b y e # i n i n s m s m
- d
- d
/ t / t m p m p / t e / t e s t s t _ m _ m
- d
u
- d
u l e l e . k
- .
k
- i
n s m
- d
: E R R O R : c
- u
l d n
- t
i n s e r t m
- d
u l e / t m p / t e s t _ m
- d
u l e . k
- :
O p e r a t i
- n
n
- t
p e r m i t t e d [ . . ] L
- a
d P i n : k e r n e l
- m
- d
u l e d e n i e d
- b
j = " / t m p / t e s t _ m
- d
u l e . k
- "
p i d = 3 2 1 5 c m d l i n e = " i n s m
- d
/ t m p / t e s t _ m
- d
u l e . k
- "
# u m u m
- u
- u
n t n t / t / t r u r u s t e s t e d [ . . ] L
- a
d P i n : u m
- u
n t p i n n e d f s : r e f u s i n g f u r t h e r l
- a
d s
Yama: Overview
- Built with C
O N F I G _ S E C U R I T Y _ Y A M A = y
- The first “stacked” LSM (sorry not sorry)
- Narrows scope of ptracing from “same uid” to “ancestor and
explicit whitelist”
- Basic goal is to expand the time window needed to steal a
user’s credentials after successfully breaking into a machine
NOT ACTUAL LOGO
Yama: Recent developments
- Also pretty stable (and many distros use it!)
– (I just had to write this in a slide, didn’t I? syzkaller just sent me an
RCU bug it found in Yama’s task walking...)
- I may have future work cut out for me
– Jann Horn has started looking at bypasses …
Yama: Demo
s y s t e m d , 1 , r
- t
|
- d
a e m
- n
, 2 2 1 4 ,
- t
h e r u s e r |
- b
a s h , 2 2 2 3 , k e e s | `
- s
e c r e t , 2 2 3 | `
- g
d b , 2 2 3 5 | `
- p
r
- g
r a m , 2 2 3 6 `
- b
a s h , 3 1 1 , k e e s |
- c
r a s h i n g
- p
r
- g
r a m , 3 1 4 5 | `
- e
v i l
- a
t t a c k e r , 3 2 8 5 `
- c
r a s h
- h
a n d l e r , 3 2 8 6
Before Yama: "evil-attacker" wants to read memory
- f "daemon", but gets blocked by
DAC (kees != otheruser): ptrace(PTRACE_ATTACH, 2214) → EPERM But it can read “secret” (same uid, but started in the past): ptrace(PTRACE_ATTACH, 2230) → ok
Yama: Demo
s y s t e m d , 1 , r
- t
|
- d
a e m
- n
, 2 2 1 4 ,
- t
h e r u s e r |
- b
a s h , 2 2 2 3 , k e e s | |
- s
e c r e t , 2 2 3 | `
- g
d b , 2 2 3 5 | `
- p
r
- g
r a m , 2 2 3 6 `
- b
a s h , 3 1 1 , k e e s |
- c
r a s h i n g
- p
r
- g
r a m , 3 1 4 5 | `
- e
v i l
- a
t t a c k e r , 3 2 8 5 `
- c
r a s h
- h
a n d l e r , 3 2 8 6
With Yama: "evil-attacker" wants to read memory of "secret", but gets blocked (not in ancestry tree): ptrace(PTRACE_ATTACH, 2230) → EPERM
Yama: Demo
s y s t e m d , 1 , r
- t
|
- d
a e m
- n
, 2 2 1 4 ,
- t
h e r u s e r |
- b
a s h , 2 2 2 3 , k e e s | |
- s
e c r e t , 2 2 3 | `
- g
d b , 2 2 3 5 | `
- p
r
- g
r a m , 2 2 3 6 `
- b
a s h , 3 1 1 , k e e s |
- c
r a s h i n g
- p
r
- g
r a m , 3 1 4 5 | `
- e
v i l
- a
t t a c k e r , 3 2 8 5 `
- c
r a s h
- h
a n d l e r , 3 2 8 6
With Yama: "gdb" wants to read memory of "program" and is fine (gdb is in ancestory tree): ptrace(PTRACE_ATTACH, 2236) → ok
Yama: Demo
s y s t e m d , 1 , r
- t
|
- d
a e m
- n
, 2 2 1 4 ,
- t
h e r u s e r |
- b
a s h , 2 2 2 3 , k e e s | `
- s
e c r e t , 2 2 3 | `
- g
d b , 2 2 3 5 | `
- p
r
- g
r a m , 2 2 3 6 `
- b
a s h , 3 1 1 , k e e s |
- c
r a s h i n g
- p
r
- g
r a m , 3 1 4 5 | `
- e
v i l
- a
t t a c k e r , 3 2 8 5 `
- c
r a s h
- h
a n d l e r , 3 2 8 6
But ancestory tree checking can break crash handlers: "crash-handler" wants to read "crashing-program", but gets blocked: ptrace(PTRACE_ATTACH, 3145) → EPERM
Yama: Demo
s y s t e m d , 1 , r
- t
|
- d
a e m
- n
, 2 2 1 4 ,
- t
h e r u s e r |
- b
a s h , 2 2 2 3 , k e e s | `
- s
e c r e t , 2 2 3 | `
- g
d b , 2 2 3 5 | `
- p
r
- g
r a m , 2 2 3 6 `
- b
a s h , 3 1 1 , k e e s |
- c
r a s h i n g
- p
r
- g
r a m , 3 1 4 5 | `
- e
v i l
- a
t t a c k e r , 3 2 8 5 `
- c
r a s h
- h
a n d l e r , 3 2 8 6
so "crashing-program" declares "crash-handler" can read its memory: prctl(PR_SET_PTRACER, 3286) now "crash-handler" can read memory of "crashing-program": ptrace(PTRACE_ATTACH, 3145) → ok
seccomp: Overview
- Not an LSM. More low-level: it filters system calls
- n
- _
n e w _ p r i v s saves the day against setuid issues
- As seen in Chrome, Chrome OS, Android, Docker, systemd
and Firefox, QEMU, OpenSSH, vsftpd, LXD, Tor, the list goes on…
- Easy to add seccomp to your code!
– To quickly wrap a program, use m
i n i j a i l
- S
p
- l
i c y . t x t
– To use normal filtering, you want l
i b s e c c
- m
p
– To do really special things, you’ll need to learn BPF
- actually a subset of classic BPF (not eBPF)
NOT ACTUAL LOGO
seccomp: Filter matching
- filter can match anything in the seccomp BPF “packet data”:
s t r u c t s e c c
- m
p _ d a t a { i n t n r ; / * S y s t e m c a l l n u m b e r * / _ _ u 3 2 a r c h ; / * A U D I T _ A R C H _ * < l i n u x / a u d i t . h > * / _ _ u 6 4 i n s t r u c t i
- n
_ p
- i
n t e r ; / * C P U i n s t r u c t i
- n
p
- i
n t e r * / _ _ u 6 4 a r g s [ 6 ] ; / * U p t
- 6
s y s t e m c a l l a r g s * / } ;
- Can not read process memory (e.g. filename arg contents) – would be racey
seccomp: Filter results
- S
E C C O M P _ R E T _ A L L O W : continue with syscall
- S
E C C O M P _ R E T _ L O G : emit audit record and continue
- S
E C C O M P _ R E T _ T R A C E : generate P T R A C E _ E V E N T _ S E C C O M P
- S
E C C O M P _ R E T _ E R R N O : skip syscall, return specified e r r n
- S
E C C O M P _ R E T _ T R A P : deliver S I G S Y S signal
- S
E C C O M P _ R E T _ K I L L _ T H R E A D : kill the thread
- S
E C C O M P _ R E T _ K I L L _ P R O C E S S : kill the process (thread group)
seccomp: Recent developments
- Tycho Andersen suffering endless discussion on how to add
S E C C O M P _ R E T _ U S E R _ N O T I F
– Basically S
E C C O M P _ R E T _ T R A C E using a file descriptor instead of ptrace
- We know what it won’t be, at least:
– Not NLA structs – Not eBPF (“eBPF will never block userspace”)
seccomp: Demo
$ . / m i n i j a i l
- S
c a t . p
- l
i c y / b i n / c a t c a t . p
- l
i c y $ e c h
- $
? 1 3 4 ( S I G A B R T ) $ t a i l
- n
2 / v a r / l
- g
/ s y s l
- g
. . . c a t : l i b m i n i j a i l [ 4 2 5 3 2 ] : p r c t l ( s e c c
- m
p _ f i l t e r ) f a i l e d : P e r m i s s i
- n
d e n i e d . . . m i n i j a i l : l i b m i n i j a i l [ 4 2 5 3 1 ] : c h i l d p r
- c
e s s 4 2 5 3 2 r e c e i v e d s i g n a l 6 $ e r r n
- s
e a r c h d e n i e d E A C C E S 1 3 P e r m i s s i
- n
d e n i e d $ m a n s e c c
- m
p . . . E A C C E S T h e c a l l e r d i d n
- t
h a v e t h e C A P _ S Y S _ A D M I N c a p a b i l i t y i n i t s u s e r n a m e s p a c e ,
- r
h a d n
- t
s e t n
- _
n e w _ p r i v s b e f
- r
e u s i n g S E C ‐ C O M P _ S E T _ M O D E _ F I L T E R . . . . $ . / m i n i j a i l
- h
| g r e p p r i v s
- n
: S e t n
- _
n e w _ p r i v s .
seccomp: Demo
$ . / m i n i j a i l
- n
S c a t . p
- l
i c y / b i n / c a t c a t . p
- l
i c y
- p
e n a t : 1 f s t a t : 1 m m a p : 1 f a d v i s e 6 4 : 1 r e a d : 1 w r i t e : 1 m u n m a p : 1 c l
- s
e : 1 e x i t _ g r
- u
p : 1 $ h e a d
- n
1 c a t
- e
i n v a l . p
- l
i c y
- p
e n a t : r e t u r n E I N V A L $ . / m i n i j a i l
- n
S c a t
- e
i n v a l . p
- l
i c y / b i n / c a t c a t . p
- l
i c y / b i n / c a t : c a t . p
- l
i c y : I n v a l i d a r g u m e n t
seccomp: Demo
$ . / m i n i j a i l
- n
S c a t . p
- l
i c y / b i n / l s c a t . p
- l
i c y $ e c h
- $
? 2 5 3 $ t a i l
- n
1 / v a r / l
- g
/ s y s l
- g
. . . m i n i j a i l : l i b m i n i j a i l [ 4 3 8 5 3 ] : c h i l d p r
- c
e s s 4 3 8 5 4 r e c e i v e d s i g n a l 3 1 $ k i l l
- l
3 1 S Y S $ c p c a t . p
- l
i c y l s . p
- l
i c y $ s t r a c e
- f
. / m i n i j a i l
- n
S l s . p
- l
i c y / b i n / l s l s . p
- l
i c y . . . [ p i d 4 1 2 6 ] i
- c
t l ( 1 , T C G E T S < u n f i n i s h e d . . . > ) = ? [ p i d 4 1 2 6 ] + + + k i l l e d b y S I G S Y S ( c
- r
e d u m p e d ) + + + . . . $ e c h
- “
i
- c
t l : a r g = = 1 ” > > l s . p
- l
i c y