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 ● 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 NOT ACTUAL LOGO ● 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 is redundant in your O N F I G _ M O D U L E _ S I G _ F O R C E = y environment, LoadPin is for you! – Chrome OS uses d to provide a cryptographically verified m - v e r i t y 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
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 d f f - - h h / / t t m m p / / t t r r u u s s t t e 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 o u n t e d o n / d e v / r o o t 2 4 G 1 7 G 6 . 4 G 7 2 % / / d e v / l o o p 0 4 8 8 M 9 5 6 K 4 5 2 M 1 % / t r u s t e d # i i n n s s m m o o d d / / t t r r u u s s t t e e d / / t t e e s s t t _ _ m m o o d d u u l l e e . . k k o [ . . ] L o a d P i n : l o o p 0 ( 7 : 0 ) : w r i t a b l e [ . . ] L o a d P i n : e n f o r c e m e n t c a n b e d i s a b l e d . [ . . ] L o a d P i n : k e r n e l - m o d u l e p i n n e d o b j = " / t r u s t e d / t e s t _ m o d u l e . k o " p i d = 3 2 0 8 c m d l i n e = " i n s m o d / t r u s t e d / t e s t _ m o d u l e . k o " [ . . ] t e s t _ m o d u l e : H e l l o , w o r l d # r r m m m m o o d d t t e e s s t t _ _ m m o o d d u u l l e e [ . . ] t e s t _ m o d u l e : G o o d b y e # i i n n s s m m o o d d / / t t m m p p / / t t e e s s t t _ _ m m o o d d u u l l e e . . k k o o i n s m o d : E R R O R : c o u l d n o t i n s e r t m o d u l e / t m p / t e s t _ m o d u l e . k o : O p e r a t i o n n o t p e r m i t t e d [ . . ] L o a d P i n : k e r n e l - m o d u l e d e n i e d o b j = " / t m p / t e s t _ m o d u l e . k o " p i d = 3 2 1 5 c m d l i n e = " i n s m o d / t m p / t e s t _ m o d u l e . k o " # u u m m o o u u n n t t / / t t r r u u s s t t e e d [ . . ] L o a d P i n : u m o 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 o 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 NOT ACTUAL LOGO ● 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
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 Before Yama: s y s t e m d , 1 , r o o t | - d a e m o n , 2 2 1 4 , o t h e r u s e r "evil-attacker" wants to read memory | - b a s h , 2 2 2 3 , k e e s of "daemon", but gets blocked by DAC (kees != otheruser): | ` - s e c r e t , 2 2 3 0 ptrace(PTRACE_ATTACH, 2214) | ` - g d b , 2 2 3 5 → EPERM | ` - p r o g r a m , 2 2 3 6 ` - b a s h , 3 1 0 1 , k e e s But it can read “secret” (same uid, but started in the past): | - c r a s h i n g - p r o g r a m , 3 1 4 5 ptrace(PTRACE_ATTACH, 2230) | ` - e v i l - a t t a c k e r , 3 2 8 5 → ok ` - c r a s h - h a n d l e r , 3 2 8 6
Yama: Demo With Yama: s y s t e m d , 1 , r o o t | - d a e m o n , 2 2 1 4 , o t h e r u s e r "evil-attacker" wants to read | - b a s h , 2 2 2 3 , k e e s memory of "secret", but gets | | - s e c r e t , 2 2 3 0 blocked (not in ancestry tree): | ` - g d b , 2 2 3 5 | ` - p r o g r a m , 2 2 3 6 ptrace(PTRACE_ATTACH, 2230) ` - b a s h , 3 1 0 1 , k e e s → EPERM | - c r a s h i n g - p r o 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
Yama: Demo With Yama: s y s t e m d , 1 , r o o t | - d a e m o n , 2 2 1 4 , o t h e r u s e r "gdb" wants to read memory of | - b a s h , 2 2 2 3 , k e e s "program" and is fine (gdb is in | | - s e c r e t , 2 2 3 0 ancestory tree): | ` - g d b , 2 2 3 5 | ` - p r o g r a m , 2 2 3 6 ptrace(PTRACE_ATTACH, 2236) ` - b a s h , 3 1 0 1 , k e e s → ok | - c r a s h i n g - p r o 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
Yama: Demo But ancestory tree checking can s y s t e m d , 1 , r o o t break crash handlers: | - d a e m o n , 2 2 1 4 , o t h e r u s e r | - b a s h , 2 2 2 3 , k e e s "crash-handler" wants to read | ` - s e c r e t , 2 2 3 0 "crashing-program", but gets blocked: | ` - g d b , 2 2 3 5 ptrace(PTRACE_ATTACH, 3145) | ` - p r o g r a m , 2 2 3 6 → EPERM ` - b a s h , 3 1 0 1 , k e e s | - c r a s h i n g - p r o 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
Yama: Demo so "crashing-program" declares s y s t e m d , 1 , r o o t "crash-handler" can read its | - d a e m o n , 2 2 1 4 , o t h e r u s e r memory: | - b a s h , 2 2 2 3 , k e e s prctl(PR_SET_PTRACER, 3286) | ` - s e c r e t , 2 2 3 0 | ` - g d b , 2 2 3 5 now "crash-handler" can read memory of "crashing-program": | ` - p r o g r a m , 2 2 3 6 ptrace(PTRACE_ATTACH, 3145) ` - b a s h , 3 1 0 1 , k e e s → ok | - c r a s h i n g - p r o 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
seccomp: Overview ● Not an LSM. More low-level: it filters system calls NOT ACTUAL LOGO ● n saves the day against setuid issues o _ n e w _ p r i v s ● 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 o l i c y . t x t – To use normal filtering, you want l i b s e c c o m p – To do really special things, you’ll need to learn BPF actually a subset of classic BPF (not eBPF) ●
seccomp: Filter matching ● filter can match anything in the seccomp BPF “packet data”: s t r u c t s e c c o 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 o n _ p o i n t e r ; / * C P U i n s t r u c t i o n p o i n t e r * / _ _ u 6 4 a r g s [ 6 ] ; / * U p t o 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
Recommend
More recommend