Linux ã«ãŒãã«ã®ã»ãã¥ãªãã£ããã®æ©èœãããã³ Seccomp
BPF ã¯ãå®å®æ§ãã»ãã¥ãªãã£ãé床ãç ç²ã«ããããšãªãã«ãŒãã«ãæ¡åŒµãã匷åãªæ¹æ³ãæäŸããŸãã ãã®ãããã«ãŒãã«éçºè ã¯ãBPF ããã°ã©ã ã§ãµããŒãããã Seccomp ãã£ã«ã¿ãŒ (Seccomp BPF ãšãåŒã°ããŸã) ãå®è£ ããããšã§ããã®å€çšéæ§ãå©çšã㊠Seccomp ã®ããã»ã¹åé¢ãæ¹åããã®ãåŸçã§ãããšèããŸããã ãã®ç« ã§ã¯ãSeccomp ãšã¯äœãããŸããã®äœ¿çšæ¹æ³ã«ã€ããŠèª¬æããŸãã 次ã«ãBPF ããã°ã©ã ã䜿çšã㊠Seccomp ãã£ã«ã¿ãŒãäœæããæ¹æ³ãåŠã³ãŸãã ãã®åŸãLinux ã»ãã¥ãªã㣠ã¢ãžã¥ãŒã«ã®ã«ãŒãã«ã«å«ãŸããçµã¿èŸŒã¿ BPF ããã¯ãèŠãŠãããŸãã
Linux ã»ãã¥ãªã㣠ã¢ãžã¥ãŒã« (LSM) ã¯ãæšæºåãããæ¹æ³ã§ããŸããŸãªã»ãã¥ãªã㣠ã¢ãã«ãå®è£ ããããã«äœ¿çšã§ããäžé£ã®æ©èœãæäŸãããã¬ãŒã ã¯ãŒã¯ã§ãã LSM ã¯ãApparmorãSELinuxãTomoyo ãªã©ã®ã«ãŒãã« ãœãŒã¹ ããªãŒã§çŽæ¥äœ¿çšã§ããŸãã
ãŸã㯠Linux ã®æ©èœã«ã€ããŠèª¬æããŸãããã
æ©èœ
Linux ã®æ©èœã®æ¬è³ªã¯ãç¹å®ã®ã¿ã¹ã¯ãå®è¡ããããã«éç¹æš©ããã»ã¹ã®ã¢ã¯ã»ã¹èš±å¯ãä»äžããå¿ èŠãããããšã§ããããã®ç®ç㧠suid ã䜿çšãããããã®ä»ã®æ¹æ³ã§ããã»ã¹ã«ç¹æš©ãäžãããããããšã§ãæ»æã®å¯èœæ§ãæžãããããã»ã¹ãç¹å®ã®ã¿ã¹ã¯ãå®è¡ã§ããããã«ããå¿ èŠããããŸãã ããšãã°ãã¢ããªã±ãŒã·ã§ã³ãç¹æš©ããŒã (ããšãã° 80) ãéãå¿ èŠãããå Žåãããã»ã¹ã root ãšããŠå®è¡ãã代ããã«ãåçŽã« CAP_NET_BIND_SERVICE æ©èœãäžããããšãã§ããŸãã
main.go ãšããååã® Go ããã°ã©ã ãèããŠã¿ãŸãããã
package main
import (
"net/http"
"log"
)
func main() {
log.Fatalf("%v", http.ListenAndServe(":80", nil))
}
ãã®ããã°ã©ã ã¯ãããŒã 80 (ããã¯ç¹æš©ããŒãã§ã) 㧠HTTP ãµãŒããŒã«ãµãŒãã¹ãæäŸããŸãã éåžžãã³ã³ãã€ã«çŽåŸã«å®è¡ããŸãã
$ go build -o capabilities main.go
$ ./capabilities
ãã ããroot æš©éãä»äžããŠããªãããããã®ã³ãŒãã¯ããŒãããã€ã³ããããšãã«ãšã©ãŒãã¹ããŒããŸãã
2019/04/25 23:17:06 listen tcp :80: bind: permission denied
exit status 1
capsh (ã·ã§ã« ãããŒãžã£ãŒ) ã¯ãç¹å®ã®æ©èœã»ãããåããã·ã§ã«ãå®è¡ããããŒã«ã§ãã
ãã®å Žåããã§ã«è¿°ã¹ãããã«ãå®å šãª root æš©éãä»äžãã代ããã«ãããã°ã©ã å ã«æ¢ã«ååšããä»ã®ãã¹ãŠã®æ©èœãšãšãã« cap_net_bind_service æ©èœãæäŸããããšã§ãç¹æš©ããŒã ãã€ã³ãã£ã³ã°ãæå¹ã«ããããšãã§ããŸãã ãããè¡ãã«ã¯ãããã°ã©ã ã capsh ã§å²ã¿ãŸãã
# capsh --caps='cap_net_bind_service+eip cap_setpcap,cap_setuid,cap_setgid+ep'
--keep=1 --user="nobody"
--addamb=cap_net_bind_service -- -c "./capabilities"
ãã®ããŒã ã«ã€ããŠå°ãç解ããŠã¿ãŸãããã
- capsh - capsh ãã·ã§ã«ãšããŠäœ¿çšããŸãã
- âcaps='cap_net_bind_service+eip cap_setpcap,cap_setuid,cap_setgid+ep' - ãŠãŒã¶ãŒãå€æŽããå¿ èŠããããã (root ãšããŠå®è¡ããããªã)ãcap_net_bind_service ãšãŠãŒã¶ãŒ ID ãå®éã«å€æŽããæ©èœãæå®ããŸãã root ã誰ã«ãäžããŸãããã€ãŸããcap_setuid ãš cap_setgid ã§ãã
- âkeep=1 â root ã¢ã«ãŠã³ãããåãæ¿ãããšãã«ãã€ã³ã¹ããŒã«ãããŠããæ©èœãä¿æããããšããŸãã
- âuser=ânobodyâ â ããã°ã©ã ãå®è¡ãããšã³ã ãŠãŒã¶ãŒã¯èª°ã§ããããŸããã
- âaddamb=cap_net_bind_service â root ã¢ãŒãããåãæ¿ããåŸã®é¢é£æ©èœã®ã¯ãªã¢ãèšå®ããŸãã
- - -c "./capabilities" - ããã°ã©ã ãå®è¡ããã ãã§ãã
ãªã³ã¯ãããæ©èœã¯ãçŸåšã®ããã°ã©ã ã execve() ã䜿çšããŠåããã°ã©ã ãå®è¡ãããšãã«åããã°ã©ã ã«ç¶æ¿ãããç¹å¥ãªçš®é¡ã®æ©èœã§ãã é¢é£ä»ããèš±å¯ãããŠããæ©èœãã€ãŸãç°å¢æ©èœã®ã¿ãç¶æ¿ã§ããŸãã
--caps ãªãã·ã§ã³ã§æ©èœãæå®ããåŸã+eip ãäœãæå³ããã®ãçåã«æããããããããŸããã ãããã®ãã©ã°ã¯ã次ã®æ©èœã決å®ããããã«äœ¿çšãããŸãã
- ã¢ã¯ãã£ãåããå¿ èŠããããŸã (p)ã
- 䜿çšå¯èœ (e);
- åããã»ã¹ã«ç¶æ¿ã§ããŸã (i)ã
cap_net_bind_service ã䜿çšãããã®ã§ãããã e ãã©ã°ã§è¡ãå¿ èŠããããŸãã 次ã«ãã³ãã³ãã§ã·ã§ã«ãèµ·åããŸãã ããã«ããæ©èœãã€ããªãå®è¡ãããi ãã©ã°ã§ããŒã¯ããå¿ èŠããããŸãã æåŸã«ãp ã䜿çšããŠãã®æ©èœãæå¹ã«ããŸã (UID ãå€æŽããã«ãããè¡ããŸãã)ã cap_net_bind_service+eip ã®ããã«ãªããŸãã
çµæã¯ssã§ç¢ºèªã§ããŸãã ããŒãžã«åãŸãããã«åºåãå°ãçãããŠã¿ãŸãããããã ããé¢é£ããããŒããš 0 以å€ã®ãŠãŒã¶ãŒ ID (ãã®å Žå㯠65) ã衚瀺ãããŸãã
# ss -tulpn -e -H | cut -d' ' -f17-
128 *:80 *:*
users:(("capabilities",pid=30040,fd=3)) uid:65534 ino:11311579 sk:2c v6only:0
ãã®äŸã§ã¯ capsh ã䜿çšããŸããããlibcap ã䜿çšããŠã·ã§ã«ãäœæããããšãã§ããŸãã 詳现ã«ã€ããŠã¯ããman 3 libcapããåç §ããŠãã ããã
ããã°ã©ã ãäœæãããšããéçºè ã¯å®è¡æã«ããã°ã©ã ã«å¿ èŠãªãã¹ãŠã®æ©èœãäºåã«ç¥ã£ãŠããããã§ã¯ãããŸããã ããã«ããããã®æ©èœã¯æ°ããããŒãžã§ã³ã§ã¯å€æŽãããå¯èœæ§ããããŸãã
ããã°ã©ã ã®æ©èœãããæ·±ãç解ããã«ã¯ãcap_capable ã«ãŒãã«é¢æ°ã® kprobe ãèšå®ãã BCC 察å¿ããŒã«ã䜿çšããŸãã
/usr/share/bcc/tools/capable
TIME UID PID TID COMM CAP NAME AUDIT
10:12:53 0 424 424 systemd-udevd 12 CAP_NET_ADMIN 1
10:12:57 0 1103 1101 timesync 25 CAP_SYS_TIME 1
10:12:57 0 19545 19545 capabilities 10 CAP_NET_BIND_SERVICE 1
cap_capable ã«ãŒãã«é¢æ°ã§ bpftrace ãšã¯ã³ã©ã€ã㌠kprobe ã䜿çšããããšã§ãåãããšãå®çŸã§ããŸãã
bpftrace -e
'kprobe:cap_capable {
time("%H:%M:%S ");
printf("%-6d %-6d %-16s %-4d %dn", uid, pid, comm, arg2, arg3);
}'
| grep -i capabilities
kprobe åŸã«ããã°ã©ã ã®æ©èœãæå¹ã«ãªã£ãŠããå Žåã次ã®ãããªåºåã衚瀺ãããŸãã
12:01:56 1000 13524 capabilities 21 0
12:01:56 1000 13524 capabilities 21 0
12:01:56 1000 13524 capabilities 21 0
12:01:56 1000 13524 capabilities 12 0
12:01:56 1000 13524 capabilities 12 0
12:01:56 1000 13524 capabilities 12 0
12:01:56 1000 13524 capabilities 12 0
12:01:56 1000 13524 capabilities 10 1
1 çªç®ã®åã¯ããã»ã¹ã«å¿ èŠãªæ©èœã§ããããã®åºåã«ã¯éç£æ»ã€ãã³ããå«ãŸããŠããããããã¹ãŠã®éç£æ»ãã§ãã¯ã衚瀺ãããæåŸã«ç£æ»ãã©ã° (åºåã®æåŸ) ã 10 ã«èšå®ãããå¿ èŠãªæ©èœã衚瀺ãããŸããç§ãã¡ãèå³ãããã®ã¯ CAP_NET_BIND_SERVICE ã§ãããã¯ãã¡ã€ã« include/uapi/linux/ability.h ã®ã«ãŒãã« ãœãŒã¹ ã³ãŒãã§èå¥å XNUMX ã®å®æ°ãšããŠå®çŸ©ãããŠããŸãã
/* Allows binding to TCP/UDP sockets below 1024 */
/* Allows binding to ATM VCIs below 32 */
#define CAP_NET_BIND_SERVICE 10<source lang="go">
runC ã Docker ãªã©ã®ã³ã³ãããŒã®æ©èœã¯ãå€ãã®å Žåãéç¹æš©ã¢ãŒãã§ã®å®è¡ãèš±å¯ããããã«å®è¡æã«æå¹ã«ãªããŸãããèš±å¯ãããã®ã¯ãã»ãšãã©ã®ã¢ããªã±ãŒã·ã§ã³ã®å®è¡ã«å¿ èŠãªæ©èœã®ã¿ã§ãã ã¢ããªã±ãŒã·ã§ã³ãç¹å®ã®æ©èœãå¿ èŠãšããå ŽåãDocker 㯠--cap-add ã䜿çšããŠãããã®æ©èœãæäŸã§ããŸãã
docker run -it --rm --cap-add=NET_ADMIN ubuntu ip link add dummy0 type dummy
ãã®ã³ãã³ãã¯ã³ã³ããã« CAP_NET_ADMIN æ©èœãäžãããããã¯ãŒã¯ ãªã³ã¯ãæ§æã㊠dummy0 ã€ã³ã¿ãŒãã§ã€ã¹ãè¿œå ã§ããããã«ããŸãã
次ã®ã»ã¯ã·ã§ã³ã§ã¯ããã£ã«ã¿ãªã³ã°ãªã©ã®æ©èœã®äœ¿çšæ¹æ³ã説æããŸãããç¬èªã®ãã£ã«ã¿ãããã°ã©ã ã§å®è£ ã§ããå¥ã®ææ³ã䜿çšããŸãã
ã»ã³ã³ã
Seccomp 㯠Secure Computing ã®ç¥ã§ãLinux ã«ãŒãã«ã«å®è£ ãããã»ãã¥ãªãã£å±€ã§ãéçºè ãç¹å®ã®ã·ã¹ãã ã³ãŒã«ããã£ã«ã¿ãªã³ã°ã§ããããã«ããŸãã Seccomp ã®æ©èœã¯ Linux ã«å¹æµããŸãããç¹å®ã®ã·ã¹ãã ã³ãŒã«ã管çã§ãããããLinux ã«æ¯ã¹ãŠã¯ããã«æè»ã§ãã
Seccomp ãš Linux ã®æ©èœã¯çžäºã«æä»çã§ã¯ãªããäž¡æ¹ã®ã¢ãããŒãã®å©ç¹ãåŸãããã«äžç·ã«äœ¿çšãããããšããããããŸãã ããšãã°ãããã»ã¹ã« CAP_NET_ADMIN æ©èœãäžããŠãããœã±ããæ¥ç¶ã®åãå ¥ããèš±å¯ãããaccept ããã³ accept4 ã·ã¹ãã ã³ãŒã«ããããã¯ãããå ŽåããããŸãã
Seccomp ãã£ã«ã¿ãªã³ã°æ¹åŒã¯ãSECCOMP_MODE_FILTER ã¢ãŒãã§åäœãã BPF ãã£ã«ã¿ã«åºã¥ããŠããããã±ãããšåæ§ã«ã·ã¹ãã ã³ãŒã« ãã£ã«ã¿ãªã³ã°ãå®è¡ãããŸãã
Seccomp ãã£ã«ã¿ãŒã¯ãPR_SET_SECCOMP æäœãéã㊠prctl ã䜿çšããŠããŒããããŸãã ãããã®ãã£ã«ã¿ã¯ãseccomp_data æ§é äœã§è¡šããã Seccomp ãã±ããããšã«å®è¡ããã BPF ããã°ã©ã ã®åœ¢åŒããšããŸãã ãã®æ§é äœã«ã¯ãåç §ã¢ãŒããã¯ãã£ãã·ã¹ãã ã³ãŒã«æã®ããã»ããµåœä»€ãžã®ãã€ã³ã¿ãããã³ uint64 ã§è¡šãããæ倧 XNUMX ã€ã®ã·ã¹ãã ã³ãŒã«åŒæ°ãå«ãŸããŠããŸãã
linux/seccomp.h ãã¡ã€ã«å ã®ã«ãŒãã« ãœãŒã¹ ã³ãŒãããã® seccomp_data æ§é ã¯æ¬¡ã®ããã«ãªããŸãã
struct seccomp_data {
int nr;
__u32 arch;
__u64 instruction_pointer;
__u64 args[6];
};
ãã®æ§é ãããããããã«ãã·ã¹ãã ã³ãŒã«ããã®åŒæ°ããŸãã¯äž¡æ¹ã®çµã¿åããã«ãã£ãŠãã£ã«ã¿ãªã³ã°ã§ããŸãã
å Seccomp ãã±ãããåä¿¡ããåŸããã£ã«ã¿ãŒã¯æçµçãªæ±ºå®ãäžãã次ã«äœããã¹ãããã«ãŒãã«ã«äŒããåŠçãå®è¡ããå¿ èŠããããŸãã æçµçãªæ±ºå®ã¯æ»ãå€ïŒã¹ããŒã¿ã¹ã³ãŒãïŒã®ããããã§è¡šãããŸãã
- SECCOMP_RET_KILL_PROCESS - ãã®ããã«å®è¡ãããªãã£ãã·ã¹ãã ã³ãŒã«ããã£ã«ã¿ãªã³ã°ããçŽåŸã«ããã»ã¹å šäœã匷å¶çµäºããŸãã
- SECCOMP_RET_KILL_THREAD - ãã®ããã«å®è¡ãããªãã£ãã·ã¹ãã ã³ãŒã«ããã£ã«ã¿ãªã³ã°ããåŸãããã«çŸåšã®ã¹ã¬ãããçµäºããŸãã
â SECCOMP_RET_KILL â SECCOMP_RET_KILL_THREAD ã®ãšã€ãªã¢ã¹ãäžäœäºææ§ã®ããã«æ®ãããŠããŸãã
- SECCOMP_RET_TRAP - ã·ã¹ãã ã³ãŒã«ã¯çŠæ¢ãããã·ã¹ãã ã³ãŒã«ãåŒã³åºããã¿ã¹ã¯ã« SIGSYS (Bad System Call) ã·ã°ãã«ãéä¿¡ãããŸãã
- SECCOMP_RET_ERRNO - ã·ã¹ãã ã³ãŒã«ã¯å®è¡ããããSECCOMP_RET_DATA ãã£ã«ã¿ãŒã®æ»ãå€ã®äžéšã errno å€ãšããŠãŠãŒã¶ãŒç©ºéã«æž¡ãããŸãã ãšã©ãŒã®åå ã«å¿ããŠãç°ãªã errno å€ãè¿ãããŸãã ãšã©ãŒçªå·ã®ãªã¹ãã¯æ¬¡ã®ã»ã¯ã·ã§ã³ã«èšèŒãããŠããŸãã
- SECCOMP_RET_TRACE - ptrace ãã¬ãŒãµã«éç¥ããããã«äœ¿çšãããŸãã - PTRACE_O_TRACESECCOMP ã䜿çšããŠããã®ããã»ã¹ã確èªããã³å¶åŸ¡ããããã«ã·ã¹ãã ã³ãŒã«ãå®è¡ããããšãã«ã€ã³ã¿ãŒã»ããããŸãã ãã¬ãŒãµãæ¥ç¶ãããŠããªãå Žåã¯ãšã©ãŒãè¿ãããerrno ã -ENOSYS ã«èšå®ãããã·ã¹ãã ã³ãŒã«ã¯å®è¡ãããŸããã
- SECCOMP_RET_LOG - ã·ã¹ãã ã³ãŒã«ã解決ããããã°ã«èšé²ãããŸãã
- SECCOMP_RET_ALLOW - ã·ã¹ãã ã³ãŒã«ã¯åã«èš±å¯ãããŸãã
ptrace ã¯ãtracee ãšåŒã°ããããã»ã¹ã«ãã¬ãŒã¹ ã¡ã«ããºã ãå®è£ ããããã®ã·ã¹ãã ã³ãŒã«ã§ãããããã»ã¹ã®å®è¡ãç£èŠããã³å¶åŸ¡ããæ©èœãåããŠããŸãã ãã¬ãŒã¹ ããã°ã©ã ã¯ãå®è¡ã«å¹æçã«åœ±é¿ãäžãããã¬ãŒã¹å¯Ÿè±¡ã®ã¡ã¢ãª ã¬ãžã¹ã¿ãå€æŽã§ããŸãã Seccomp ã³ã³ããã¹ãã§ã¯ãSECCOMP_RET_TRACE ã¹ããŒã¿ã¹ ã³ãŒãã«ãã£ãŠããªã¬ãŒããããšãã« ptrace ã䜿çšãããããããã¬ãŒãµã¯ã·ã¹ãã ã³ãŒã«ã®å®è¡ãé²æ¢ããç¬èªã®ããžãã¯ãå®è£ ã§ããŸãã
Seccomp ãšã©ãŒ
Seccomp ã䜿çšããŠãããšãã«ãSECCOMP_RET_ERRNO åã®æ»ãå€ã«ãã£ãŠèå¥ãããããŸããŸãªãšã©ãŒãçºçããããšããããŸãã ãšã©ãŒãå ±åããã«ã¯ãseccomp ã·ã¹ãã ã³ãŒã«ã¯ 1 ã§ã¯ãªã -0 ãè¿ããŸãã
次ã®ãšã©ãŒãçºçããå¯èœæ§ããããŸãã
- EACCESS - åŒã³åºãå ã¯ã·ã¹ãã ã³ãŒã«ãè¡ãããšãèš±å¯ãããŸããã ããã¯éåžžãCAP_SYS_ADMIN æš©éããªãããprctl ã䜿çšã㊠no_new_privs ãèšå®ãããŠããªãããã«çºçããŸã (ããã«ã€ããŠã¯åŸã§èª¬æããŸã)ã
â EFAULT â æž¡ãããåŒæ° (seccomp_data æ§é äœã®åŒæ°) ã«æå¹ãªã¢ãã¬ã¹ããããŸããã
â EINVAL â ããã«ã¯ XNUMX ã€ã®çç±ãèããããŸãã
- èŠæ±ãããæäœã¯äžæã§ããããçŸåšã®æ§æã®ã«ãŒãã«ã«ãã£ãŠãµããŒããããŠããŸããã
-æå®ããããã©ã°ã¯ãèŠæ±ãããæäœã«å¯ŸããŠç¡å¹ã§ãã
-operation ã«ã¯ BPF_ABS ãå«ãŸããŠããŸãããæå®ããããªãã»ããã«åé¡ããããseccomp_data æ§é äœã®ãµã€ãºãè¶ ããå¯èœæ§ããããŸãã
- ãã£ã«ã¿ãŒã«æž¡ãããåœä»€ã®æ°ãæ倧å€ãè¶ ããŠããŸãã
â ENOMEM â ããã°ã©ã ãå®è¡ããã®ã«ååãªã¡ã¢ãªããããŸããã
- EOPNOTSUPP - æäœã¯ãSECCOMP_GET_ACTION_AVAIL ã§ã¢ã¯ã·ã§ã³ãå©çšå¯èœã§ããããšã瀺ããŸããããã«ãŒãã«ã¯åŒæ°ã§ã®æ»ãããµããŒãããŠããŸããã
â ESRCH â å¥ã®ã¹ããªãŒã ãåæãããšãã«åé¡ãçºçããŸããã
- ENOSYS - SECCOMP_RET_TRACE ã¢ã¯ã·ã§ã³ã«é¢é£ä»ãããããã¬ãŒãµãŒã¯ãããŸããã
prctl ã¯ããŠãŒã¶ãŒç©ºéããã°ã©ã ããã€ã ãšã³ãã£ã¢ã³ãã¹ã¬ããåãå®å šãªèšç®ã¢ãŒã (Seccomp)ãç¹æš©ãPerf ã€ãã³ããªã©ã®ããã»ã¹ã®ç¹å®ã®åŽé¢ãæäœ (èšå®ããã³ååŸ) ã§ããããã«ããã·ã¹ãã ã³ãŒã«ã§ãã
Seccomp ã¯ãµã³ãããã¯ã¹ ãã¯ãããžã®ããã«èŠãããããããŸããããããã§ã¯ãããŸããã Seccomp ã¯ããŠãŒã¶ãŒããµã³ãããã¯ã¹ ã¡ã«ããºã ãéçºã§ããããã«ãããŠãŒãã£ãªãã£ã§ãã 次ã«ãSeccomp ã·ã¹ãã ã³ãŒã«ã«ãã£ãŠçŽæ¥åŒã³åºããããã£ã«ã¿ãŒã䜿çšããŠããŠãŒã¶ãŒ ã€ã³ã¿ã©ã¯ã·ã§ã³ ããã°ã©ã ãã©ã®ããã«äœæãããããèŠãŠã¿ãŸãããã
BPF Seccomp ãã£ã«ã¿ãŒã®äŸ
ããã§ã¯ãåã«èª¬æãã次㮠XNUMX ã€ã®ã¢ã¯ã·ã§ã³ãçµã¿åãããæ¹æ³ã瀺ããŸãã
â Seccomp BPF ããã°ã©ã ãäœæããŸããããã¯ãè¡ããã決å®ã«å¿ããŠç°ãªãæ»ãã³ãŒããæã€ãã£ã«ã¿ãŒãšããŠäœ¿çšãããŸãã
â prctl ã䜿çšããŠãã£ã«ã¿ãŒãããŒãããŸãã
ãŸããæšæºã©ã€ãã©ãªãš Linux ã«ãŒãã«ããã®ããããŒãå¿ èŠã§ãã
#include <errno.h>
#include <linux/audit.h>
#include <linux/bpf.h>
#include <linux/filter.h>
#include <linux/seccomp.h>
#include <linux/unistd.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/prctl.h>
#include <unistd.h>
ãã®äŸãè©Šãåã«ãã«ãŒãã«ã CONFIG_SECCOMP ããã³ CONFIG_SECCOMP_FILTER ã y ã«èšå®ããŠã³ã³ãã€ã«ãããŠããããšã確èªããå¿ èŠããããŸãã åäœäžã®ãã·ã³ã§ã¯ã次ã®ããã«ããŠããã確èªã§ããŸãã
cat /proc/config.gz| zcat | grep -i CONFIG_SECCOMP
ã³ãŒãã®æ®ãã®éšåã¯ãXNUMX ã€ã®éšåãããªã install_filter é¢æ°ã§ãã æåã®éšåã«ã¯ãBPF ãã£ã«ã¿ãªã³ã°æé ã®ãªã¹ããå«ãŸããŠããŸãã
static int install_filter(int nr, int arch, int error) {
struct sock_filter filter[] = {
BPF_STMT(BPF_LD + BPF_W + BPF_ABS, (offsetof(struct seccomp_data, arch))),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arch, 0, 3),
BPF_STMT(BPF_LD + BPF_W + BPF_ABS, (offsetof(struct seccomp_data, nr))),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, nr, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (error & SECCOMP_RET_DATA)),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
};
ãã®åœä»€ã¯ãlinux/filter.h ãã¡ã€ã«ã§å®çŸ©ãããŠãã BPF_STMT ããã³ BPF_JUMP ãã¯ãã䜿çšããŠèšå®ãããŸãã
æé ãèŠãŠãããŸãããã
- BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, Arch))) - ã·ã¹ãã 㯠BPF_LD ããã¯ãŒã BPF_W ã®åœ¢åŒã§ããŒãããã³èç©ããŸãããã±ãã ããŒã¿ã¯åºå®ãªãã»ãã BPF_ABS ã«é 眮ãããŸãã
- BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, Arch, 0, 3) - BPF_JEQ ã䜿çšããŠãBPF_K ã¢ãã¥ã ã¬ãŒã¿å®æ°ã®ã¢ãŒããã¯ãã£å€ã Arch ãšçãããã©ããããã§ãã¯ããŸãã ããã§ããã°ããªãã»ãã 0 ã§æ¬¡ã®åœä»€ã«ãžã£ã³ãããŸããããã§ãªãå Žåã¯ããªãã»ãã 3 (ãã®å Žå) ã§ãžã£ã³ãããŠãã¢ãŒããäžèŽããªããããšã©ãŒãã¹ããŒããŸãã
- BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, nr))) - BPF_ABS ã®åºå®ãªãã»ããã«å«ãŸããã·ã¹ãã ã³ãŒã«çªå·ã§ãã BPF_W ãšããåèªã®åœ¢åŒã§ BPF_LD ããããŒãããã³èç©ãããŸãã
â BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, nr, 0, 1) â ã·ã¹ãã ã³ãŒã«çªå·ãš nr å€æ°ã®å€ãæ¯èŒããŸãã çããå Žåã¯æ¬¡ã®åœä»€ã«é²ã¿ãã·ã¹ãã ã³ãŒã«ãç¡å¹ã«ããçãããªãå Žå㯠SECCOMP_RET_ALLOW ã§ã·ã¹ãã ã³ãŒã«ãèš±å¯ããŸãã
- BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (error & SECCOMP_RET_DATA)) - BPF_RET ã§ããã°ã©ã ãçµäºãããã®çµæãerr å€æ°ã®çªå·ãå«ããšã©ãŒ SECCOMP_RET_ERRNO ãçæãããŸãã
- BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW) - BPF_RET ã§ããã°ã©ã ãçµäºããSECCOMP_RET_ALLOW ã䜿çšããŠã·ã¹ãã ã³ãŒã«ãå®è¡ã§ããããã«ããŸãã
SECCOMP 㯠CBPF ã§ã
ãªãã³ã³ãã€ã«ããã ELF ãªããžã§ã¯ãã JIT ã³ã³ãã€ã«ããã C ããã°ã©ã ã®ä»£ããã«åœä»€ã®ãªã¹ãã䜿çšãããã®ãçåã«æããããããããŸãããããã«ã¯XNUMXã€ã®çç±ããããŸãã
⢠第äžã«ãSeccomp 㯠eBPF ã§ã¯ãªã cBPF (ã¯ã©ã·ã㯠BPF) ã䜿çšããŸããã€ãŸããäŸã«èŠãããããã«ãã¬ãžã¹ã¿ã¯ãªããæåŸã®èšç®çµæãä¿åããã¢ãã¥ã ã¬ãŒã¿ã®ã¿ããããŸãã
⢠第 XNUMX ã«ãSeccomp 㯠BPF åœä»€ã®é åãžã®ãã€ã³ã¿ãçŽæ¥åãå ¥ããŸããããã以å€ã¯åãå ¥ããŸããã ç§ãã¡ã䜿çšãããã¯ãã¯ãããã°ã©ãã䜿ããããæ¹æ³ã§ãããã®åœä»€ãæå®ããã®ã«åœ¹ç«ã€ã ãã§ãã
ãã®ã¢ã»ã³ããªãç解ããããã«ããã«å©ããå¿ èŠãªå Žåã¯ãåãããšãè¡ãç䌌ã³ãŒããæ€èšããŠãã ããã
if (arch != AUDIT_ARCH_X86_64) {
return SECCOMP_RET_ALLOW;
}
if (nr == __NR_write) {
return SECCOMP_RET_ERRNO;
}
return SECCOMP_RET_ALLOW;
socket_filter æ§é äœã§ãã£ã«ã¿ãŒ ã³ãŒããå®çŸ©ããåŸãã³ãŒããšãã£ã«ã¿ãŒã®èšç®ãããé·ããå«ã sock_fprog ãå®çŸ©ããå¿ èŠããããŸãã ãã®ããŒã¿æ§é ã¯ãåŸã§å®è¡ããããã»ã¹ã宣èšããããã®åŒæ°ãšããŠå¿ èŠã§ãã
struct sock_fprog prog = {
.len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),
.filter = filter,
};
install_filter é¢æ°ã§ããã¹ãããšã¯ XNUMX ã€ã ãæ®ã£ãŠããŸããããã¯ããã°ã©ã èªäœãããŒãããããšã§ãã ãããè¡ãã«ã¯ãprctl ã䜿çšããã»ãã¥ã¢ ã³ã³ãã¥ãŒãã£ã³ã° ã¢ãŒãã«å ¥ããªãã·ã§ã³ãšã㊠PR_SET_SECCOMP ãéžæããŸãã 次ã«ãsock_fprog åã® prog å€æ°ã«å«ãŸãã SECCOMP_MODE_FILTER ã䜿çšããŠãã£ã«ã¿ãŒãããŒãããããã«ã¢ãŒãã«æ瀺ããŸãã
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
perror("prctl(PR_SET_SECCOMP)");
return 1;
}
return 0;
}
æåŸã«ãinstall_filter é¢æ°ã䜿çšã§ããŸããããã®åã«ãprctl ã䜿çšããŠçŸåšã®å®è¡ã«å¯Ÿã㊠PR_SET_NO_NEW_PRIVS ãèšå®ããå¿ èŠããããŸããããã«ãããåããã»ã¹ã芪ããã»ã¹ãããå€ãã®æš©éãåãåãç¶æ³ãåé¿ã§ããŸãã ããã«ãããroot æš©éããªããŠããinstall_filter é¢æ°ã§æ¬¡ã® prctl åŒã³åºããè¡ãããšãã§ããŸãã
ããã§ãinstall_filter é¢æ°ãåŒã³åºãããšãã§ããŸãã X86-64 ã¢ãŒããã¯ãã£ã«é¢é£ãããã¹ãŠã®æžã蟌ã¿ã·ã¹ãã ã³ãŒã«ããããã¯ãããã¹ãŠã®è©Šè¡ããããã¯ããã¢ã¯ã»ã¹èš±å¯ãäžããã ãã«ããŠã¿ãŸãããã ãã£ã«ã¿ãŒãã€ã³ã¹ããŒã«ããåŸãæåã®åŒæ°ã䜿çšããŠå®è¡ãç¶è¡ããŸãã
int main(int argc, char const *argv[]) {
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
perror("prctl(NO_NEW_PRIVS)");
return 1;
}
install_filter(__NR_write, AUDIT_ARCH_X86_64, EPERM);
return system(argv[1]);
}
å§ããŸãããã ããã°ã©ã ãã³ã³ãã€ã«ããã«ã¯ãclang ãŸã㯠gcc ã䜿çšã§ããŸãããããã«ããŠããç¹å¥ãªãªãã·ã§ã³ãªã㧠main.c ãã¡ã€ã«ãã³ã³ãã€ã«ããã ãã§ãã
clang main.c -o filter-write
åè¿°ã®ãšãããããã°ã©ã å ã®ãã¹ãŠã®ãšã³ããªããããã¯ããŸããã ããããã¹ãããã«ã¯ãäœããåºåããããã°ã©ã ãå¿ èŠã§ããls ãåè£ã®ããã§ãã 圌女ã¯éåžžã次ã®ããã«è¡åããŸãã
ls -la
total 36
drwxr-xr-x 2 fntlnz users 4096 Apr 28 21:09 .
drwxr-xr-x 4 fntlnz users 4096 Apr 26 13:01 ..
-rwxr-xr-x 1 fntlnz users 16800 Apr 28 21:09 filter-write
-rw-r--r-- 1 fntlnz users 19 Apr 28 21:09 .gitignore
-rw-r--r-- 1 fntlnz users 1282 Apr 28 21:08 main.c
çŽ æŽãããïŒ ã©ãã㌠ããã°ã©ã ã®äœ¿çšæ¹æ³ã¯æ¬¡ã®ããã«ãªããŸãããã¹ããããããã°ã©ã ãæåã®åŒæ°ãšããŠæž¡ãã ãã§ãã
./filter-write "ls -la"
ãã®ããã°ã©ã ãå®è¡ãããšãå®å šã«ç©ºã®åºåãçæãããŸãã ãã ããstrace ã䜿çšãããšãäœãèµ·ãã£ãŠãããã確èªã§ããŸãã
strace -f ./filter-write "ls -la"
äœæ¥ã®çµæã¯å€§å¹ ã«ççž®ãããŠããŸããããã®å¯Ÿå¿ããéšåã§ã¯ãã¬ã³ãŒãã EPERM ãšã©ãŒ (æ§æãããã®ãšåããã®) ã§ãããã¯ãããŠããããšã瀺ãããŠããŸãã ããã¯ãããã°ã©ã ã write ã·ã¹ãã ã³ãŒã«ã«ã¢ã¯ã»ã¹ã§ããªããããäœãåºåããªãããšãæå³ããŸãã
[pid 25099] write(2, "ls: ", 4) = -1 EPERM (Operation not permitted)
[pid 25099] write(2, "write error", 11) = -1 EPERM (Operation not permitted)
[pid 25099] write(2, "n", 1) = -1 EPERM (Operation not permitted)
ããã§ãSeccomp BPF ãã©ã®ããã«æ©èœããããç解ããããã䜿çšããŠäœãã§ãããã«ã€ããŠããç解ã§ããŸããã ããããcBPF ã®ä»£ããã« eBPF ã䜿çšããŠåãããšãå®çŸããŠããã®èœåãæ倧éã«æŽ»çšããããšæããŸããã?
eBPF ããã°ã©ã ã«ã€ããŠèãããšããã»ãšãã©ã®äººã¯åã«ããã°ã©ã ãäœæãã管çè æš©éã§ããŒãããã ãã ãšèããŸãã ãã®ã¹ããŒãã¡ã³ãã¯äžè¬ã«çå®ã§ãããã«ãŒãã«ã¯ããŸããŸãªã¬ãã«ã§ eBPF ãªããžã§ã¯ããä¿è·ããããã®äžé£ã®ã¡ã«ããºã ãå®è£ ããŠããŸãã ãããã®ã¡ã«ããºã 㯠BPF LSM ãã©ãããšåŒã°ããŸãã
BPF LSM ãã©ãã
ã¢ãŒããã¯ãã£ã«äŸåããªãã·ã¹ãã ã€ãã³ãã®ç£èŠãæäŸããããã«ãLSM ã¯ãã©ããã®æŠå¿µãå®è£ ããŠããŸãã ãã㯠ã³ãŒã«ã¯æè¡çã«ã¯ã·ã¹ãã ã³ãŒã«ãšäŒŒãŠããŸãããã·ã¹ãã ããç¬ç«ããŠãããã€ã³ãã©ã¹ãã©ã¯ãã£ãšçµ±åãããŠããŸãã LSM ã¯ãæœè±¡åã¬ã€ã€ãŒããããŸããŸãªã¢ãŒããã¯ãã£ã§ã·ã¹ãã ã³ãŒã«ãåŠçãããšãã«çºçããåé¡ãåé¿ããã®ã«åœ¹ç«ã€æ°ããæŠå¿µãæäŸããŸãã
ãã®èšäºã®å·çæç¹ã§ã¯ãã«ãŒãã«ã«ã¯ BPF ããã°ã©ã ã«é¢é£ä»ãããã XNUMX ã€ã®ããã¯ããããSELinux ã¯ããããå®è£ ããå¯äžã®çµã¿èŸŒã¿ LSM ã§ãã
ãã©ããã®ãœãŒã¹ ã³ãŒãã¯ããã¡ã€ã« include/linux/security.h ã®ã«ãŒãã« ããªãŒã«ãããŸãã
extern int security_bpf(int cmd, union bpf_attr *attr, unsigned int size);
extern int security_bpf_map(struct bpf_map *map, fmode_t fmode);
extern int security_bpf_prog(struct bpf_prog *prog);
extern int security_bpf_map_alloc(struct bpf_map *map);
extern void security_bpf_map_free(struct bpf_map *map);
extern int security_bpf_prog_alloc(struct bpf_prog_aux *aux);
extern void security_bpf_prog_free(struct bpf_prog_aux *aux);
ããããã®é¢æ°ã¯ãå®è¡ã®ããŸããŸãªæ®µéã§åŒã³åºãããŸãã
â security_bpf â å®è¡ããã BPF ã·ã¹ãã ã³ãŒã«ã®åæãã§ãã¯ãå®è¡ããŸãã
- security_bpf_map - ã«ãŒãã«ããããã®ãã¡ã€ã«èšè¿°åãè¿ããšãããã§ãã¯ããŸãã
- security_bpf_prog - ã«ãŒãã«ã eBPF ããã°ã©ã ã®ãã¡ã€ã«èšè¿°åãè¿ããšãããã§ãã¯ããŸãã
â security_bpf_map_alloc â BPF ãããå ã®ã»ãã¥ãªã㣠ãã£ãŒã«ããåæåãããŠãããã©ããã確èªããŸãã
- security_bpf_map_free - BPF ãããå ã§ã»ãã¥ãªã㣠ãã£ãŒã«ããã¯ãªã¢ãããŠãããã©ããã確èªããŸãã
â security_bpf_prog_alloc â ã»ãââã¥ãªã㣠ãã£ãŒã«ãã BPF ããã°ã©ã å ã§åæåãããŠãããã©ããã確èªããŸãã
- security_bpf_prog_free - BPF ããã°ã©ã å ã§ã»ãã¥ãªã㣠ãã£ãŒã«ããã¯ãªã¢ãããŠãããã©ããã確èªããŸãã
ããŠãããããã¹ãŠãèŠãŠãLSM BPF ã€ã³ã¿ãŒã»ãã¿ãŒã®èåŸã«ããèãæ¹ã¯ããã¹ãŠã® eBPF ãªããžã§ã¯ãã«ä¿è·ãæäŸããé©åãªæš©éãæã€ãŠãŒã¶ãŒã ããã«ãŒããããã°ã©ã ã§æäœãå®è¡ã§ããããã«ãããšãããã®ã§ãã
ãµããªãŒ
ã»ãã¥ãªãã£ã¯ãä¿è·ããããã®ãã¹ãŠã«å¯ŸããŠç»äžçãªæ¹æ³ã§å®è£ ã§ãããã®ã§ã¯ãããŸããã ããŸããŸãªã¬ãã«ããã³ããŸããŸãªæ¹æ³ã§ã·ã¹ãã ãä¿è·ã§ããããšãéèŠã§ãã ä¿¡ããããªããããããŸããããã·ã¹ãã ãä¿è·ããæåã®æ¹æ³ã¯ãããŸããŸãªç«å ŽããããŸããŸãªã¬ãã«ã®ä¿è·ãçµç¹ããXNUMX ã€ã®ã¬ãã«ã®ã»ãã¥ãªãã£ãäœäžãããŠãã·ã¹ãã å šäœãžã®ã¢ã¯ã»ã¹ãèš±å¯ãããªãããã«ããããšã§ãã ã³ã¢éçºè ã¯ãããŸããŸãªã¬ã€ã€ãŒãšã¿ãããã€ã³ãã®ã»ãããæäŸãããšããçŽ æŽãããä»äºãããŠãããŸããã ã¬ã€ã€ãŒãšã¯äœãããŸãããããæäœããããã« BPF ããã°ã©ã ã䜿çšããæ¹æ³ã«ã€ããŠååã«ç解ã§ããããšãé¡ã£ãŠããŸãã
èè ã«ã€ããŠ
ããããã»ã«ã©ãã© Netlify ã® CTO ã§ãã 圌㯠Docker ãµããŒãã«æºãããRuncãGoãBCC ããŒã«ããã®ä»ã®ãªãŒãã³ãœãŒã¹ ãããžã§ã¯ãã®éçºã«è²¢ç®ããŸããã Docker ãããžã§ã¯ããš Docker ãã©ã°ã€ã³ ãšã³ã·ã¹ãã ã®éçºã«é¢ããä»äºã§ç¥ãããŠããŸãã David ã¯ãã¬ãŒã ã°ã©ãã«éåžžã«æ ç±ãæã£ãŠãããåžžã«ããã©ãŒãã³ã¹ã®æé©åã«åªããŠããŸãã
ãã¬ã³ãã©ãã©ã³ã¿ã Sysdig ã®ãªãŒãã³ãœãŒã¹ ããŒã ã«æå±ããŠãããã«ãŒãã« ã¢ãžã¥ãŒã«ãš eBPF ãä»ããŠã³ã³ãã ã©ã³ã¿ã€ã ã»ãã¥ãªãã£ãšç°åžžæ€åºãæäŸãã Cloud Native Computing Foundation ãããžã§ã¯ãã§ãã Falco ã«äž»ã«çŠç¹ãåœãŠãŠããŸãã 圌ã¯ãåæ£ã·ã¹ãã ããœãããŠã§ã¢å®çŸ©ãããã¯ãŒãã³ã°ãLinux ã«ãŒãã«ãããã³ããã©ãŒãã³ã¹åæã«æ ç±ã泚ãã§ããŸãã
» ãã®æ¬ã®è©³çŽ°ã«ã€ããŠã¯ããã¡ããã芧ãã ããã
»
»
Khabrozhiteley ã®å Žåãã¯ãŒãã³äœ¿çšã§ 25% å²åŒ - Linux
çŽçã®æžç±ããæ¯æãããã ããšãé»åæžç±ãé»åã¡ãŒã«ã§éä¿¡ãããŸãã
åºæïŒ habr.com