"Linux ๋ชจ๋‹ˆํ„ฐ๋ง์„ ์œ„ํ•œ BPF" ์ฑ…

"Linux ๋ชจ๋‹ˆํ„ฐ๋ง์„ ์œ„ํ•œ BPF" ์ฑ…์•ˆ๋…•ํ•˜์„ธ์š”, ์นด๋ธŒ๋กœ ์ฃผ๋ฏผ ์—ฌ๋Ÿฌ๋ถ„! BPF ๊ฐ€์ƒ ๋จธ์‹ ์€ Linux ์ปค๋„์˜ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ตฌ์„ฑ ์š”์†Œ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด ์‹œ์Šคํ…œ ์—”์ง€๋‹ˆ์–ด๊ฐ€ ๊ฒฐํ•จ์„ ์ฐพ์•„๋‚ด๊ณ  ๊ฐ€์žฅ ๋ณต์žกํ•œ ๋ฌธ์ œ๋„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ปค๋„์˜ ๋™์ž‘์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๊ณ  ์ˆ˜์ •ํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•, ์ปค๋„์˜ ์ด๋ฒคํŠธ๋ฅผ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ• ๋“ฑ์„ ๋ฐฐ์šฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. David Calavera์™€ Lorenzo Fontana๋Š” BPF์˜ ํž˜์„ ํ™œ์šฉํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ค„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์„ฑ๋Šฅ ์ตœ์ ํ™”, ๋„คํŠธ์›Œํ‚น, ๋ณด์•ˆ์— ๋Œ€ํ•œ ์ง€์‹์„ ํ™•์žฅํ•˜์„ธ์š”. - BPF๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Linux ์ปค๋„์˜ ๋™์ž‘์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๊ณ  ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค. - ์ปค๋„์„ ๋‹ค์‹œ ์ปดํŒŒ์ผํ•˜๊ฑฐ๋‚˜ ์‹œ์Šคํ…œ์„ ์žฌ๋ถ€ํŒ…ํ•  ํ•„์š” ์—†์ด ์ปค๋„ ์ด๋ฒคํŠธ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค. โ€” C, Go ๋˜๋Š” Python์—์„œ ํŽธ๋ฆฌํ•œ ์ฝ”๋“œ ์˜ˆ์ œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. - BPF ํ”„๋กœ๊ทธ๋žจ ์ˆ˜๋ช…์ฃผ๊ธฐ๋ฅผ ์†Œ์œ ํ•˜์—ฌ ์ œ์–ดํ•˜์„ธ์š”.

Linux ์ปค๋„ ๋ณด์•ˆ, ๊ธฐ๋Šฅ ๋ฐ Seccomp

BPF๋Š” ์•ˆ์ •์„ฑ, ๋ณด์•ˆ ๋˜๋Š” ์†๋„๋ฅผ ํฌ์ƒํ•˜์ง€ ์•Š๊ณ  ์ปค๋„์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ•๋ ฅํ•œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ด์œ ๋กœ ์ปค๋„ ๊ฐœ๋ฐœ์ž๋Š” Seccomp BPF๋ผ๊ณ ๋„ ์•Œ๋ ค์ง„ BPF ํ”„๋กœ๊ทธ๋žจ์—์„œ ์ง€์›ํ•˜๋Š” Seccomp ํ•„ํ„ฐ๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ Seccomp์˜ ํ”„๋กœ์„ธ์Šค ๊ฒฉ๋ฆฌ๋ฅผ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์€ ์ƒ๊ฐ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ์žฅ์—์„œ๋Š” Seccomp๊ฐ€ ๋ฌด์—‡์ด๋ฉฐ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉ๋˜๋Š”์ง€ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ BPF ํ”„๋กœ๊ทธ๋žจ์„ ์‚ฌ์šฉํ•˜์—ฌ Seccomp ํ•„ํ„ฐ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ด…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ Linux ๋ณด์•ˆ ๋ชจ๋“ˆ์šฉ ์ปค๋„์— ํฌํ•จ๋œ ๋‚ด์žฅ BPF ํ›„ํฌ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

LSM(Linux ๋ณด์•ˆ ๋ชจ๋“ˆ)์€ ํ‘œ์ค€ํ™”๋œ ๋ฐฉ์‹์œผ๋กœ ๋‹ค์–‘ํ•œ ๋ณด์•ˆ ๋ชจ๋ธ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ ์„ธํŠธ๋ฅผ ์ œ๊ณตํ•˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. LSM์€ Apparmor, SELinux ๋ฐ Tomoyo์™€ ๊ฐ™์€ ์ปค๋„ ์†Œ์Šค ํŠธ๋ฆฌ์—์„œ ์ง์ ‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Linux์˜ ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด ๋…ผ์˜ํ•˜๋Š” ๊ฒƒ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ธฐ๋Šฅ

Linux ๊ธฐ๋Šฅ์˜ ํ•ต์‹ฌ์€ ํŠน์ • ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ๊ถŒํ•œ์ด ์—†๋Š” ํ”„๋กœ์„ธ์Šค ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•ด์•ผ ํ•˜์ง€๋งŒ ํ•ด๋‹น ๋ชฉ์ ์œผ๋กœ suid๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ํ”„๋กœ์„ธ์Šค์— ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜์—ฌ ๊ณต๊ฒฉ ๊ฐ€๋Šฅ์„ฑ์„ ์ค„์ด๊ณ  ํ”„๋กœ์„ธ์Šค๊ฐ€ ํŠน์ • ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ—ˆ์šฉํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋ฃจํŠธ๋กœ ํ”„๋กœ์„ธ์Šค๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋Œ€์‹  ๊ถŒํ•œ ์žˆ๋Š” ํฌํŠธ(์˜ˆ: 80)๋ฅผ ์—ด์–ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ๊ฐ„๋‹จํžˆ 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

๊ทธ๋Ÿฌ๋‚˜ ๋ฃจํŠธ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ด ์ฝ”๋“œ๋Š” ํฌํŠธ๋ฅผ ๋ฐ”์ธ๋”ฉํ•  ๋•Œ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

2019/04/25 23:17:06 listen tcp :80: bind: permission denied
exit status 1

capsh(์‰˜ ๊ด€๋ฆฌ์ž)๋Š” ํŠน์ • ๊ธฐ๋Šฅ ์„ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‰˜์„ ์‹คํ–‰ํ•˜๋Š” ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.

์ด ๊ฒฝ์šฐ ์ด๋ฏธ ์–ธ๊ธ‰ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ์ „์ฒด ๋ฃจํŠธ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜๋Š” ๋Œ€์‹  ์ด๋ฏธ ํ”„๋กœ๊ทธ๋žจ์— ์žˆ๋Š” ๋‹ค๋ฅธ ๋ชจ๋“  ๊ธฐ๋Šฅ๊ณผ ํ•จ๊ป˜ 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' - ์‚ฌ์šฉ์ž๋ฅผ ๋ณ€๊ฒฝํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์—(๋ฃจํŠธ๋กœ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์ง€ ์•Š์Œ) cap_net_bind_service์™€ ์‹ค์ œ๋กœ ์‚ฌ์šฉ์ž ID๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ๋‹ค์Œ์—์„œ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์•„๋ฌด๋„, ์ฆ‰ cap_setuid ๋ฐ cap_setgid์— ๋ฃจํŠธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
  • โ€”keep=1 โ€” ๋ฃจํŠธ ๊ณ„์ •์—์„œ ์ „ํ™˜ํ•  ๋•Œ ์„ค์น˜๋œ ๊ธฐ๋Šฅ์„ ์œ ์ง€ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
  • โ€”user=โ€œnobodyโ€ โ€” ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•˜๋Š” ์ตœ์ข… ์‚ฌ์šฉ์ž๋Š” ๋ˆ„๊ตฌ๋„ ์•„๋‹™๋‹ˆ๋‹ค.
  • โ€”addamb=cap_net_bind_service โ€” ๋ฃจํŠธ ๋ชจ๋“œ์—์„œ ์ „ํ™˜ํ•œ ํ›„ ๊ด€๋ จ ๊ธฐ๋Šฅ ์ง€์šฐ๊ธฐ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  • - -c "./capability" - ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์—ฐ๊ฒฐ๋œ ๊ธฐ๋Šฅ์€ ํ˜„์žฌ ํ”„๋กœ๊ทธ๋žจ์ด 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 ์ปค๋„ ํ•จ์ˆ˜์—์„œ ๋‹จ์ผ ๋ผ์ด๋„ˆ kprobe์™€ ํ•จ๊ป˜ bpftrace๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋™์ผํ•œ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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๋กœ ์„ค์ •๋œ ํ•„์ˆ˜ ๊ธฐ๋Šฅ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ๊ด€์‹ฌ์„ ๊ฐ–๊ณ  ์žˆ๋Š” ๊ฒƒ์€ CAP_NET_BIND_SERVICE์ž…๋‹ˆ๋‹ค. ์ด๋Š” ์‹๋ณ„์ž 10์„ ๊ฐ–๋Š” include/uapi/linux/ability.h ํŒŒ์ผ์˜ ์ปค๋„ ์†Œ์Šค ์ฝ”๋“œ์—์„œ ์ƒ์ˆ˜๋กœ ์ •์˜๋ฉ๋‹ˆ๋‹ค.

/* 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_O_TRACESECCOMP๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ptrace ์ถ”์ ์ž์—๊ฒŒ ์•Œ๋ฆฌ๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ถ”์  ํ”„๋กœ๊ทธ๋žจ์ด ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์ง€ ์•Š์œผ๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐ˜ํ™˜๋˜๊ณ  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 โ€” ์—ฌ๊ธฐ์—๋Š” ๋„ค ๊ฐ€์ง€ ์ด์œ ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

-์š”์ฒญํ•œ ์ž‘์—…์ด ์•Œ ์ˆ˜ ์—†๊ฑฐ๋‚˜ ํ˜„์žฌ ๊ตฌ์„ฑ์˜ ์ปค๋„์—์„œ ์ง€์›๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

-์ง€์ •๋œ ํ”Œ๋ž˜๊ทธ๊ฐ€ ์š”์ฒญ๋œ ์ž‘์—…์— ๋Œ€ํ•ด ์œ ํšจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

-์ž‘์—…์—๋Š” BPF_ABS๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์ง€๋งŒ ์ง€์ •๋œ ์˜คํ”„์…‹์— ๋ฌธ์ œ๊ฐ€ ์žˆ์–ด seccomp_data ๊ตฌ์กฐ์˜ ํฌ๊ธฐ๋ฅผ ์ดˆ๊ณผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

-ํ•„ํ„ฐ์— ์ „๋‹ฌ๋œ ๋ช…๋ น ์ˆ˜๊ฐ€ ์ตœ๋Œ€๊ฐ’์„ ์ดˆ๊ณผํ•ฉ๋‹ˆ๋‹ค.

โ€” ENOMEM โ€” ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•˜๊ธฐ์— ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋ถ€์กฑํ•ฉ๋‹ˆ๋‹ค.

- EOPNOTSUPP - SECCOMP_GET_ACTION_AVAIL์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์—…์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ์„ ๋‚˜ํƒ€๋‚ด๋Š” ์ž‘์—…์ด์ง€๋งŒ ์ปค๋„์€ ์ธ์ˆ˜ ๋ฐ˜ํ™˜์„ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

โ€” ESRCH โ€” ๋‹ค๋ฅธ ์ŠคํŠธ๋ฆผ์„ ๋™๊ธฐํ™”ํ•  ๋•Œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

- ENOSYS - SECCOMP_RET_TRACE ์ž‘์—…์— ์—ฐ๊ฒฐ๋œ ์ถ”์  ํ”„๋กœ๊ทธ๋žจ์ด ์—†์Šต๋‹ˆ๋‹ค.

prctl์€ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„ ํ”„๋กœ๊ทธ๋žจ์ด ๋ฐ”์ดํŠธ ์—”๋””์•ˆ, ์Šค๋ ˆ๋“œ ์ด๋ฆ„, ๋ณด์•ˆ ๊ณ„์‚ฐ ๋ชจ๋“œ(Seccomp), ๊ถŒํ•œ, Perf ์ด๋ฒคํŠธ ๋“ฑ๊ณผ ๊ฐ™์€ ํ”„๋กœ์„ธ์Šค์˜ ํŠน์ • ์ธก๋ฉด์„ ์กฐ์ž‘(์„ค์ • ๋ฐ ๊ฐ€์ ธ์˜ค๊ธฐ)ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ์‹œ์Šคํ…œ ํ˜ธ์ถœ์ž…๋‹ˆ๋‹ค.

Seccomp๋Š” ์ƒŒ๋“œ๋ฐ•์Šค ๊ธฐ์ˆ ์ฒ˜๋Ÿผ ๋ณด์ผ ์ˆ˜๋„ ์žˆ์ง€๋งŒ ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Seccomp๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ƒŒ๋“œ๋ฐ•์Šค ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ์ž…๋‹ˆ๋‹ค. ์ด์ œ Seccomp ์‹œ์Šคํ…œ ํ˜ธ์ถœ์— ์˜ํ•ด ์ง์ ‘ ํ˜ธ์ถœ๋˜๋Š” ํ•„ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ƒํ˜ธ ์ž‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด ์–ด๋–ป๊ฒŒ ์ƒ์„ฑ๋˜๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

BPF Seccomp ํ•„ํ„ฐ ์˜ˆ

์—ฌ๊ธฐ์„œ๋Š” ์•ž์—์„œ ์„ค๋ช…ํ•œ ๋‘ ๊ฐ€์ง€ ์ž‘์—…์„ ๊ฒฐํ•ฉํ•˜๋Š” ๋ฐฉ๋ฒ•, ์ฆ‰ ๋‹ค์Œ์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

โ€” ์šฐ๋ฆฌ๋Š” ๋‚ด๋ฆฐ ๊ฒฐ์ •์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๋ฐ˜ํ™˜ ์ฝ”๋“œ๋ฅผ ๊ฐ–๋Š” ํ•„ํ„ฐ๋กœ ์‚ฌ์šฉ๋  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

๋‚˜๋จธ์ง€ ์ฝ”๋“œ๋Š” ๋‘ ๋ถ€๋ถ„์œผ๋กœ ๊ตฌ์„ฑ๋œ 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_W๋ผ๋Š” ๋‹จ์–ด์˜ ํ˜•ํƒœ๋กœ BPF_LD์—์„œ ๋กœ๋“œ ๋ฐ ๋ˆ„์ ๋˜๋ฉฐ, ํŒจํ‚ท ๋ฐ์ดํ„ฐ๋Š” ๊ณ ์ • ์˜คํ”„์…‹ BPF_ABS์— ์œ„์น˜ํ•ฉ๋‹ˆ๋‹ค.

- BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arch, 0, 3) - ๋ˆ„์‚ฐ๊ธฐ ์ƒ์ˆ˜ BPF_K์˜ ์•„ํ‚คํ…์ฒ˜ ๊ฐ’์ด arch์™€ ๊ฐ™์€์ง€ BPF_JEQ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์˜คํ”„์…‹ 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 | (์˜ค๋ฅ˜ & 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 ํ”„๋กœ๊ทธ๋žจ ๋Œ€์‹  ๋ช…๋ น ๋ชฉ๋ก์ด ์‚ฌ์šฉ๋˜๋Š” ์ด์œ ๊ฐ€ ๊ถ๊ธˆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—๋Š” ๋‘ ๊ฐ€์ง€ ์ด์œ ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

โ€ข ์ฒซ์งธ, Seccomp๋Š” eBPF๊ฐ€ ์•„๋‹Œ cBPF(ํด๋ž˜์‹ BPF)๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๋ ˆ์ง€์Šคํ„ฐ๋Š” ์—†์ง€๋งŒ ์˜ˆ์ œ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด ๋งˆ์ง€๋ง‰ ๊ณ„์‚ฐ ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ˆ„์‚ฐ๊ธฐ๋งŒ ์žˆ์Šต๋‹ˆ๋‹ค.

โ€ข ๋‘˜์งธ, Seccomp๋Š” BPF ๋ช…๋ น์–ด ๋ฐฐ์—ด์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋ฅผ ์ง์ ‘ ๋ฐ›์•„๋“ค์ด๊ณ  ๋‹ค๋ฅธ ์–ด๋–ค ๊ฒƒ๋„ ๋ฐ›์•„๋“ค์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•œ ๋งคํฌ๋กœ๋Š” ํ”„๋กœ๊ทธ๋ž˜๋จธ ์นœํ™”์ ์ธ ๋ฐฉ์‹์œผ๋กœ ์ด๋Ÿฌํ•œ ๋ช…๋ น์„ ์ง€์ •ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

์ด ์–ด์…ˆ๋ธ”๋ฆฌ๋ฅผ ์ดํ•ดํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋” ํ•„์š”ํ•˜๋ฉด ๋™์ผํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์˜์‚ฌ์ฝ”๋“œ๋ฅผ ๊ณ ๋ คํ•˜์„ธ์š”.

if (arch != AUDIT_ARCH_X86_64) {
    return SECCOMP_RET_ALLOW;
}
if (nr == __NR_write) {
    return SECCOMP_RET_ERRNO;
}
return SECCOMP_RET_ALLOW;

์†Œ์ผ“_ํ•„ํ„ฐ ๊ตฌ์กฐ์—์„œ ํ•„ํ„ฐ ์ฝ”๋“œ๋ฅผ ์ •์˜ํ•œ ํ›„ ์ฝ”๋“œ์™€ ๊ณ„์‚ฐ๋œ ํ•„ํ„ฐ ๊ธธ์ด๋ฅผ ํฌํ•จํ•˜๋Š” sock_fprog๋ฅผ ์ •์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋Š” ๋‚˜์ค‘์— ์‹คํ–‰ํ•  ํ”„๋กœ์„ธ์Šค๋ฅผ ์„ ์–ธํ•˜๊ธฐ ์œ„ํ•œ ์ธ์ˆ˜๋กœ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

struct sock_fprog prog = {
   .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),
   .filter = filter,
};

install_filter ํ•จ์ˆ˜์—์„œ ํ•ด์•ผ ํ•  ์ผ์€ ๋‹จ ํ•˜๋‚˜๋ฟ์ž…๋‹ˆ๋‹ค. ํ”„๋กœ๊ทธ๋žจ ์ž์ฒด๋ฅผ ๋กœ๋“œํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค! ์ด๋ฅผ ์œ„ํ•ด ๋ณด์•ˆ ์ปดํ“จํŒ… ๋ชจ๋“œ๋กœ ๋“ค์–ด๊ฐ€๊ธฐ ์œ„ํ•œ ์˜ต์…˜์œผ๋กœ PR_SET_SECCOMP๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ prctl์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ 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๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•˜๋ฉฐ ์ด๋ฅผ ํ†ตํ•ด ํ•˜์œ„ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ƒ์œ„ ํ”„๋กœ์„ธ์Šค๋ณด๋‹ค ๋” ๋งŽ์€ ๊ถŒํ•œ์„ ๋ฐ›๋Š” ์ƒํ™ฉ์„ ๋ฐฉ์ง€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ฃจํŠธ ๊ถŒํ•œ ์—†์ด 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 ๊ฐœ์ฒด์— ๋Œ€ํ•œ ๋ณดํ˜ธ๋ฅผ ์ œ๊ณตํ•˜์—ฌ ์ ์ ˆํ•œ ๊ถŒํ•œ์ด ์žˆ๋Š” ์‚ฌ์šฉ์ž๋งŒ ์นด๋“œ์™€ ํ”„๋กœ๊ทธ๋žจ์— ๋Œ€ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ณด์žฅํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค.

๊ฐœ์š”

๋ณด์•ˆ์€ ๋ณดํ˜ธํ•˜๋ ค๋Š” ๋ชจ๋“  ๊ฒƒ์— ๋Œ€ํ•ด ์ผ๋ฅ ์ ์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค. ๋‹ค์–‘ํ•œ ์ˆ˜์ค€๊ณผ ๋ฐฉ์‹์œผ๋กœ ์‹œ์Šคํ…œ์„ ๋ณดํ˜ธํ•  ์ˆ˜ ์žˆ๋Š” ๋Šฅ๋ ฅ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ๋ฏฟ๊ฑฐ๋‚˜ ๋ง๊ฑฐ๋‚˜, ์‹œ์Šคํ…œ์„ ๋ณดํ˜ธํ•˜๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์€ ๋‹ค์–‘ํ•œ ์œ„์น˜์—์„œ ๋‹ค์–‘ํ•œ ๋ณดํ˜ธ ์ˆ˜์ค€์„ ๊ตฌ์„ฑํ•˜์—ฌ ํ•œ ์ˆ˜์ค€์˜ ๋ณด์•ˆ์„ ๋‚ฎ์ถ”์–ด๋„ ์ „์ฒด ์‹œ์Šคํ…œ์— ๋Œ€ํ•œ ์•ก์„ธ์Šค๊ฐ€ ํ—ˆ์šฉ๋˜์ง€ ์•Š๋„๋ก ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•ต์‹ฌ ๊ฐœ๋ฐœ์ž๋“ค์€ ์šฐ๋ฆฌ์—๊ฒŒ ๋‹ค์–‘ํ•œ ๋ ˆ์ด์–ด์™€ ์ ‘์ ์„ ์ œ๊ณตํ•˜๋Š” ์ผ์„ ํ›Œ๋ฅญํ•˜๊ฒŒ ํ•ด๋ƒˆ์Šต๋‹ˆ๋‹ค. ๋ ˆ์ด์–ด๊ฐ€ ๋ฌด์—‡์ธ์ง€, BPF ํ”„๋กœ๊ทธ๋žจ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์—…ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ž˜ ์ดํ•ดํ•˜์…จ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์ €์ž ์†Œ๊ฐœ

๋ฐ์ด๋น„๋“œ ์นผ๋ผ๋ฒ ๋ผ Netlify์˜ CTO์ž…๋‹ˆ๋‹ค. ๊ทธ๋Š” Docker ์ง€์› ๋ถ„์•ผ์—์„œ ์ผํ–ˆ์œผ๋ฉฐ Runc, Go, BCC ๋„๊ตฌ ๋ฐ ๊ธฐํƒ€ ์˜คํ”ˆ ์†Œ์Šค ํ”„๋กœ์ ํŠธ ๊ฐœ๋ฐœ์— ๊ธฐ์—ฌํ–ˆ์Šต๋‹ˆ๋‹ค. Docker ํ”„๋กœ์ ํŠธ ์ž‘์—…๊ณผ Docker ํ”Œ๋Ÿฌ๊ทธ์ธ ์ƒํƒœ๊ณ„ ๊ฐœ๋ฐœ๋กœ ์œ ๋ช…ํ•ฉ๋‹ˆ๋‹ค. David๋Š” Flame ๊ทธ๋ž˜ํ”„์— ๋งค์šฐ ์—ด์ •์ ์ด๋ฉฐ ํ•ญ์ƒ ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ๋ชจ์ƒ‰ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋กœ๋ Œ์กฐ ํฐํƒ€๋‚˜ Sysdig์˜ ์˜คํ”ˆ ์†Œ์Šค ํŒ€์—์„œ ์ผํ•˜๋ฉฐ ์ฃผ๋กœ ์ปค๋„ ๋ชจ๋“ˆ๊ณผ eBPF๋ฅผ ํ†ตํ•ด ์ปจํ…Œ์ด๋„ˆ ๋Ÿฐํƒ€์ž„ ๋ณด์•ˆ๊ณผ ์ด์ƒ ํƒ์ง€๋ฅผ ์ œ๊ณตํ•˜๋Š” Cloud Native Computing Foundation ํ”„๋กœ์ ํŠธ์ธ Falco์— ์ค‘์ ์„ ๋‘๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Š” ๋ถ„์‚ฐ ์‹œ์Šคํ…œ, ์†Œํ”„ํŠธ์›จ์–ด ์ •์˜ ๋„คํŠธ์›Œํ‚น, Linux ์ปค๋„ ๋ฐ ์„ฑ๋Šฅ ๋ถ„์„์— ์—ด์ •์„ ๊ฐ–๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

ยป ์ฑ…์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋‹ค์Œ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐœํ–‰์ธ์˜ ์›น์‚ฌ์ดํŠธ
ยป ์ฐจ๋ก€
ยป ๋ฐœ์ทŒ

Khabrozhiteley์˜ ๊ฒฝ์šฐ ์ฟ ํฐ์„ ์‚ฌ์šฉํ•˜์—ฌ 25% ํ• ์ธ์„ ๋ฐ›์œผ์„ธ์š” - Linux

์ข…์ด์ฑ…์„ ๊ฒฐ์ œํ•˜์‹œ๋ฉด ์ „์ž์ฑ…์ด ์ด๋ฉ”์ผ๋กœ ๋ฐœ์†ก๋ฉ๋‹ˆ๋‹ค.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€