Overview and Recent Developments: Seccomp and Small Lsms
Total Page:16
File Type:pdf, Size:1020Kb
Overview and Recent Developments: seccomp and small LSMs Linux Security Summit EU October 26, 2018 Edinburgh, Scotland Kees (“Case”) Cook [email protected] @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 CONFIG_SECURITY_LOADPIN=y ● If you think CONFIG_MODULE_SIG_FORCE=y is redundant in your environment, LoadPin is for you! – Chrome OS uses dm-verity 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 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 # df -h /tm" /tr#$ted File$ystem Size Used Avail U$e% Mounted )* !dev!root 24G 17G /0,G .2% ! !dev!%))p0 ,22M 94/5 ,4+M 1% /tr#$ted # insmod /trusted/test_module06) 7008 LoadPi*9 lo)"1 :.91;9 writ'=%e 7008 LoadPi*9 enfor>ement >'n be di$'=led0 7008 LoadPi*9 kernel-module pinned )=?="/tr#$ted/test_module06)" pid=3+12 cmdline="insmod /tr#$ted/test_module06)@ 7008 test_module: He%%), world # rmmod test_module 7008 test_module: G)odbye # insmod /tmp/test_module06) insm)d: ERROR: c)#%d not i*$ert module /tmp/test_module.6): Oper'tion not permitted 7008 LoadPi*9 kernel-module denied )=?="/tm"!test_module.6)@ pid=A+15 cmdline="i*$mod /tmp/test_module06)@ # um)#nt /trusted 7008 LoadPi*9 um)#*t pinned fs: refusing further %oad$ Yama: Overview ● Built with CONFIG_SECURITY_YAMA=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 $y$temdC-Cr))t Before Yama: E-d'em)*C++-,C)t er#$er "evil-attacker" wants to read memory E-='$ C+++AC6ee$ of "daemon", but gets blocked by E F-$e>retC++A1 DAC (kees != otheruser): ptrace(PTRACE_ATTACH, 2214) E F-Dd=C++A4 → EPERM E F-"r)Dr'mC++A/ F-='$ CA-1-C6ee$ But it can read “secret” (same uid, but E->r'$ i*D-"r)Dr'mCA-,4 started in the past): ptrace(PTRACE_ATTACH, 2230) E F-evi%-'tt'>6erCA+24 → ok F->r'$ - '*d%erCA+2/ Yama: Demo $y$temdC-Cr))t With Yama: E-d'em)*C++-,C)t er#$er E-='$ C+++AC6ee$ "evil-attacker" wants to read memory of "secret", but gets E E-$e>retC++A1 blocked (not in ancestry tree): E F-Dd=C++A4 E F-"r)Dr'mC++A/ ptrace(PTRACE_ATTACH, 2230) F-='$ CA-1-C6ee$ → EPERM E->r'$ i*D-"r)Dr'mCA-,4 E F-evi%-'tt'>6erCA+24 F->r'$ - '*d%erCA+2/ Yama: Demo $y$temdC-Cr))t With Yama: E-d'em)*C++-,C)t er#$er E-='$ C+++AC6ee$ "gdb" wants to read memory of "program" and is fine (gdb is in E E-$e>retC++A1 ancestory tree): E F-Dd=C++A4 E F-"r)Dr'mC++A/ ptrace(PTRACE_ATTACH, 2236) F-='$ CA-1-C6ee$ → ok E->r'$ i*D-"r)Dr'mCA-,4 E F-evi%-'tt'>6erCA+24 F->r'$ - '*d%erCA+2/ Yama: Demo $y$temdC-Cr))t But ancestory tree checking can break crash handlers: E-d'em)*C++-,C)t er#$er E-='$ C+++AC6ee$ "crash-handler" wants to read E F-$e>retC++A1 "crashing-program", but gets E F-Dd=C++A4 blocked: E F-"r)Dr'mC++A/ ptrace(PTRACE_ATTACH, 3145) F-='$ CA-1-C6ee$ → EPERM E->r'$ i*D-"r)Dr'mCA-,4 E F-evi%-'tt'>6erCA+24 F->r'$ - '*d%erCA+2/ Yama: Demo $y$temdC-Cr))t so "crashing-program" declares "crash-handler" can read its E-d'em)*C++-,C)t er#$er memory: E-='$ C+++AC6ee$ prctl(PR_SET_PTRACER, 3286) E F-$e>retC++A1 E F-Dd=C++A4 now "crash-handler" can read E F-"r)Dr'mC++A/ memory of "crashing-program": F-='$ CA-1-C6ee$ ptrace(PTRACE_ATTACH, 3145) E->r'$ i*D-"r)Dr'mCA-,4 → ok E F-evi%-'tt'>6erCA+24 F->r'$ - '*d%erCA+2/ seccomp: Overview ● Not an LSM. More low-level: it filters system calls NOT ACTUAL LOGO ● *o_new_priv$ 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 minijail -S ")licy.txt – To use normal filtering, you want %ibsec>)mp – 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”: $tr#>t $ec>)mp_d't' { i*t nrI /J System >'%l *#m=er J! __#A+ ar> I /J AUDIT_ARCB_* K%i*#G!'udit0 L J! __#/, in$tr#>ti)*_p)i*terI /J CPU i*$tr#cti)* ")i*ter J! __#/, arD$7/8I /J Up t) 6 $ystem >'%% 'rg$ J! MI ● Can not read process memory (e.g. filename arg contents) – would be racey seccomp: Filter results ● SECCOMP_RET_ALLOW: continue with syscall ● SECCOMP_RET_LOG: emit audit record and continue ● SECCOMP_RET_TRACE: generate PTRACE_EOENT_SECCOMP ● SECCOMP_RET_ERRNO: skip syscall, return specified errno ● SECCOMP_RET_TRAP: deliver SIGSYS signal ● SECCOMP_RET_KILL_THREAD: kill the thread ● SECCOMP_RET_KILL_PROCESS: kill the process (thread group) seccomp: Recent developments ● Tycho Andersen suffering endless discussion on how to add SECCOMP_RET_USER_NOTIF – Basically SECCOMP_RET_TRACE 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 P 0!mi*i?'i%1 -S >'t0")%i>y !=i*!>'t >'t0")%i>y P e> ) PQ -A, :SIGARRT; P t'i% -*+ !v'r!%)D!$y$%)D 000 >'t9 %i=mi*i?'i%7,+4A+89 "r>t%:$e>>)m"_fi%ter; f'i%ed9 Permi$$i)* de*ied 000 mi*i?'i%19 %i=mi*i?'i%7,+4A-89 > i%d "r)>e$$ ,+4A+ re>eived $iD*'% / P err*) --$e'r> de*ied EACCES -A Permi$$i)* de*ied P m'* $e>>)m" 000 EACCES T e >'%%er did *)t 've t e CAP_SYS_ADMIN >'"'=i%ity i* it$ #$er *'me$"'>eC )r 'd *)t $et *)_*e<_"riv$ =ef)re #$i*D SECS COMP_SET_MODE_FILTER0 000 P 0!mi*i?'i%1 - E Dre" "riv$ -*9 Set *)_*e<_"riv$0 seccomp: Demo P 0!mi*i?'i%1 -*S >'t0")%i>y !=i*!>'t >'t0")%i>y )"e*'t9 - f$t't9 - mm'"9 - f'dvi$e/,9 - re'd9 - <rite9 - m#*m'"9 - >%)$e9 - eGit_Dr)#"9 - P e'd -*- >'t-ei*v'%0")%i>y )"e*'t9 ret#r* EINOAL P 0!mi*i?'i%1 -*S >'t-ei*v'%0")%i>y !=i*!>'t >'t0")%i>y !=i*!>'t9 >'t0")%i>y9 I*v'%id 'rD#me*t seccomp: Demo P 0!mi*i?'i%1 -*S >'t0")%i>y !=i*!%$ >'t0")%i>y P e> ) PQ +4A P t'i% -*- !v'r!%)D!$y$%)D 000 mi*i?'i%19 %i=mi*i?'i%7,A24A89 > i%d "r)>e$$ ,A24, re>eived $iD*'% A- P 6i%% -% A- SYS P >" >'t0")%i>y %$0")%i>y P $tr'>e -f 0!mi*i?'i%1 -*S %$0")%i>y !=i*!%$ %$0")%i>y 000 T 7"id ,-1+/8 i)>t%:-C TCGETS K#*fi*i$ ed 000L; = Q A PE L E TI 7"id ,-1+/8 TTT 6i%%ed =y SIGSYS :>)re d#m"ed; TTT R N Y U P 000 P HA P e> ) Ui)>t%9 'rD1 == -V LL %$0")%i>y Thoughts? Kees (“Case”) Cook [email protected] [email protected] [email protected] @kees_cook https://outflux.net/slides/2018/lss-eu/seccomp.pdf .