"Linux Monitoring အတွက် BPF" စာအုပ်

"Linux Monitoring အတွက် BPF" စာအုပ်မင်္ဂလာပါ Khabro နေထိုင်သူများ။ BPF virtual machine သည် Linux kernel ၏ အရေးကြီးဆုံး အစိတ်အပိုင်းများထဲမှ တစ်ခုဖြစ်သည်။ ၎င်း၏မှန်ကန်သောအသုံးပြုမှုသည် စနစ်အင်ဂျင်နီယာများအား ချို့ယွင်းချက်များကိုရှာဖွေနိုင်ပြီး အရှုပ်ထွေးဆုံးပြဿနာများကိုပင် ဖြေရှင်းနိုင်စေမည်ဖြစ်သည်။ Kernel ၏ အပြုအမူကို စောင့်ကြည့်ပြီး ပြုပြင်မွမ်းမံသည့် ပရိုဂရမ်များကို မည်သို့ရေးရမည်နည်း၊ kernel အတွင်းရှိ အဖြစ်အပျက်များကို စောင့်ကြည့်ရန် ကုဒ်ကို ဘေးကင်းစွာ အကောင်အထည်ဖော်နည်းနှင့် အခြားအရာများစွာကို လေ့လာနိုင်မည်ဖြစ်သည်။ David Calavera နှင့် Lorenzo Fontana တို့သည် BPF ၏ပါဝါကိုဖွင့်ရန်ကူညီလိမ့်မည်။ စွမ်းဆောင်ရည် အကောင်းဆုံးဖြစ်အောင်၊ ကွန်ရက်ချိတ်ဆက်မှု၊ လုံခြုံရေးဆိုင်ရာ သင်၏အသိပညာကို ချဲ့ထွင်ပါ။ - Linux kernel ၏အပြုအမူကိုစောင့်ကြည့်ရန်နှင့်ပြုပြင်ရန် BPF ကိုသုံးပါ။ - kernel ကို ပြန်လည်ပေါင်းစည်းရန် သို့မဟုတ် စနစ်ကို ပြန်လည်စတင်ရန် မလိုအပ်ဘဲ kernel ဖြစ်ရပ်များကို လုံခြုံစွာ စောင့်ကြည့်ရန် ကုဒ်ကို ထည့်သွင်းပါ။ — C၊ Go သို့မဟုတ် Python တွင် အဆင်ပြေသော ကုဒ်နမူနာများကို သုံးပါ။ - BPF ပရိုဂရမ်၏ဘဝသံသရာကိုပိုင်ဆိုင်ခြင်းဖြင့်ထိန်းချုပ်ပါ။

Linux Kernel လုံခြုံရေး၊ ၎င်း၏အင်္ဂါရပ်များနှင့် Seccomp

BPF သည် တည်ငြိမ်မှု၊ လုံခြုံရေး သို့မဟုတ် မြန်နှုန်းကို မထိခိုက်စေဘဲ kernel ကို တိုးချဲ့ရန် အစွမ်းထက်သောနည်းလမ်းကို ပံ့ပိုးပေးပါသည်။ ဤအကြောင်းကြောင့်၊ kernel developer များသည် Seccomp BPF ဟုလည်းသိကြသော BPF ပရိုဂရမ်များမှပံ့ပိုးသော Seccomp စစ်ထုတ်မှုများကိုအကောင်အထည်ဖော်ခြင်းဖြင့် Seccomp တွင် လုပ်ငန်းစဉ်အထီးကျန်မှုကို မြှင့်တင်ရန် ၎င်း၏ဘက်စုံစွမ်းပကားကို အသုံးပြုရန် အကြံကောင်းဖြစ်မည်ဟု ယူဆပါသည်။ ဤအခန်းတွင် Seccomp သည် အဘယ်အရာနှင့် ၎င်းကိုအသုံးပြုကြောင်းကို ကျွန်ုပ်တို့ရှင်းပြပါမည်။ ထို့နောက် BPF ပရိုဂရမ်များကို အသုံးပြု၍ Seccomp filters များကို မည်သို့ရေးရမည်ကို လေ့လာရမည်ဖြစ်ပါသည်။ ၎င်းနောက်၊ Linux လုံခြုံရေး modules အတွက် kernel တွင်ပါရှိသော built-in BPF ချိတ်များကို ကြည့်ရှုပါမည်။

Linux Security Modules (LSM) သည် စံသတ်မှတ်ထားသည့်ပုံစံဖြင့် အမျိုးမျိုးသော လုံခြုံရေးမော်ဒယ်များကို အကောင်အထည်ဖော်ရန် အသုံးပြုနိုင်သည့် လုပ်ဆောင်ချက်များအစုံကို ထောက်ပံ့ပေးသည့် မူဘောင်တစ်ခုဖြစ်သည်။ LSM ကို Apparmor၊ SELinux နှင့် Tomoyo ကဲ့သို့သော kernel ရင်းမြစ်သစ်တွင် တိုက်ရိုက်အသုံးပြုနိုင်ပါသည်။

Linux ၏စွမ်းရည်များကို ဆွေးနွေးခြင်းဖြင့် စတင်ကြပါစို့။

အခွင့်အလမ်း

Linux ၏စွမ်းဆောင်နိုင်မှု၏အနှစ်သာရမှာ သင်သည် အချို့သောလုပ်ငန်းတာဝန်တစ်ခုလုပ်ဆောင်ရန် အခွင့်ထူးမခံရသေးသော လုပ်ငန်းစဉ်ကို ခွင့်ပြုချက်ပေးရန် လိုအပ်သည်၊ သို့သော် ထိုရည်ရွယ်ချက်အတွက် suid ကိုမသုံးဘဲ သို့မဟုတ် အခြားနည်းဖြင့် လုပ်ငန်းစဉ်ကို အခွင့်ထူးခံဖြစ်စေရန်၊ တိုက်ခိုက်မှုဖြစ်နိုင်ခြေကို လျှော့ချရန်နှင့် လုပ်ငန်းစဉ်အချို့ကို လုပ်ဆောင်ရန် ခွင့်ပြုခြင်းပင်ဖြစ်သည်။ ဥပမာအားဖြင့်၊ သင့်အပလီကေးရှင်းသည် အခွင့်ထူးခံဆိပ်ကမ်းကိုဖွင့်ရန် လိုအပ်ပါက၊ လုပ်ငန်းစဉ်ကို root အဖြစ်လုပ်ဆောင်မည့်အစား 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

သို့သော်၊ ကျွန်ုပ်တို့သည် root အခွင့်ထူးများကို မပေးသောကြောင့်၊ port ကို binding လုပ်သောအခါ၊ ဤကုဒ်သည် အမှားအယွင်းဖြစ်သွားသည်-

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

capsh (shell manager) သည် တိကျသောစွမ်းရည်အစုံဖြင့် shell တစ်ခုကို run သည့်ကိရိယာတစ်ခုဖြစ်သည်။

ဤကိစ္စတွင်၊ ဖော်ပြထားပြီးဖြစ်သည့်အတိုင်း၊ အပြည့်အဝရပိုင်ခွင့်များကို ပေးမည့်အစား၊ ပရိုဂရမ်တွင်ရှိပြီးသားအရာအားလုံးနှင့်အတူ cap_net_bind_service စွမ်းရည်ကို ပေးခြင်းဖြင့် သင်သည် privileged port binding ကို ဖွင့်နိုင်သည်။ ၎င်းကိုလုပ်ဆောင်ရန် ကျွန်ုပ်တို့၏ပရိုဂရမ်ကို 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 ကို shell အဖြစ်အသုံးပြုပါ။
  • —caps='cap_net_bind_service+eip cap_setpcap,cap_setuid,cap_setgid+ep' - ကျွန်ုပ်တို့သည် အသုံးပြုသူကို ပြောင်းလဲရန် လိုအပ်သောကြောင့် (ကျွန်ုပ်တို့သည် root အနေဖြင့် မလုပ်ဆောင်လိုပါ) cap_net_bind_service ကို သတ်မှတ်ပေးမည်ဖြစ်ပြီး အသုံးပြုသူ ID ကို အမှန်တကယ် ပြောင်းလဲနိုင်စေမည်ဖြစ်သည်။ cap_setuid နှင့် cap_setgid ကို မည်သူမှ root လုပ်ပါ။
  • —keep=1 — ကျွန်ုပ်တို့သည် root အကောင့်မှပြောင်းသောအခါတွင် ထည့်သွင်းထားသောစွမ်းရည်များကို ထိန်းသိမ်းထားလိုပါသည်။
  • —user=“nobody” — ပရိုဂရမ်ကို အသုံးပြုသူသည် မည်သူမျှ ဖြစ်မည်မဟုတ်ပေ။
  • —addamb=cap_net_bind_service — အမြစ်မုဒ်မှပြောင်းပြီးနောက် သက်ဆိုင်ရာစွမ်းရည်များကို ရှင်းလင်းသတ်မှတ်ပါ။
  • - -c "./capabilities" - ပရိုဂရမ်ကို run လိုက်ပါ။

ချိတ်ဆက်ထားသောစွမ်းရည်များသည် လက်ရှိပရိုဂရမ်က ၎င်းတို့ကို execve() ကိုအသုံးပြု၍ လုပ်ဆောင်သည့်အခါ ကလေးပရိုဂရမ်များမှ အမွေဆက်ခံသည့် အထူးစွမ်းရည်တစ်မျိုးဖြစ်သည်။ ဆက်စပ်နိုင်ခွင့်ရှိသော စွမ်းရည်များသာ သို့မဟုတ် တနည်းအားဖြင့် ပတ်ဝန်းကျင်စွမ်းရည်များအဖြစ် အမွေဆက်ခံနိုင်ပါသည်။

--caps ရွေးချယ်မှုတွင် လုပ်နိုင်စွမ်းကို သတ်မှတ်ပြီးနောက် +eip က ဘာကိုဆိုလိုသည်ကို သင်အံ့သြနေပေမည်။ စွမ်းရည်ကို ဆုံးဖြတ်ရန် ဤအလံများကို အသုံးပြုသည်-

- activated ဖြစ်ရမည် (p);

- အသုံးပြုရန် (င);

- ကလေးလုပ်ငန်းစဉ်များဖြင့် အမွေဆက်ခံနိုင်သည် (i)။

cap_net_bind_service ကို အသုံးပြုလိုသောကြောင့်၊ ၎င်းကို e အလံဖြင့် ပြုလုပ်ရန် လိုအပ်ပါသည်။ ထို့နောက် command တွင် shell ကိုစတင်ပါမည်။ ၎င်းသည် လုပ်ဆောင်နိုင်စွမ်း binary ကို လုပ်ဆောင်မည်ဖြစ်ပြီး ၎င်းကို i အလံဖြင့် အမှတ်အသားပြုရန် လိုအပ်သည်။ နောက်ဆုံးတွင်၊ ကျွန်ုပ်တို့သည် အင်္ဂါရပ်ကို ဖွင့်ထားစေလိုသည် (ကျွန်ုပ်တို့သည် UID ကို မပြောင်းလဲဘဲ ၎င်းကို p ဖြင့် ပြုလုပ်ခဲ့သည်)။ cap_net_bind_service+eip ဖြစ်ပုံရသည်။

ss ကိုအသုံးပြု၍ ရလဒ်ကိုသင်စစ်ဆေးနိုင်သည်။ စာမျက်နှာပေါ်တွင် အံဝင်ခွင်ကျဖြစ်စေရန် အထွက်ကို အနည်းငယ် အတိုချုံးကြပါစို့၊ သို့သော် ၎င်းသည် 0 မှလွဲ၍ အခြားဆက်စပ်သော port နှင့် အသုံးပြုသူ 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 ကိုအသုံးပြု၍ shell ကိုရေးနိုင်သည်။ ပိုမိုသိရှိလိုပါက၊ man 3 libcap ကိုကြည့်ပါ။

ပရိုဂရမ်တွေရေးတဲ့အခါ၊ ဆော့ဖ်ဝဲရေးသားသူဟာ ပရိုဂရမ်လည်ပတ်နေချိန်မှာ လိုအပ်နေတဲ့ အင်္ဂါရပ်အားလုံးကို ကြိုမသိတတ်ပါဘူး။ ထို့အပြင်၊ ဤအင်္ဂါရပ်များသည် ဗားရှင်းအသစ်များတွင် ပြောင်းလဲနိုင်သည်။

ကျွန်ုပ်တို့၏ပရိုဂရမ်၏စွမ်းရည်များကို ပိုမိုကောင်းမွန်စွာနားလည်ရန်၊ cap_capable kernel လုပ်ဆောင်ချက်အတွက် 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 kernel လုပ်ဆောင်ချက်ရှိ one-liner 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 ဖြစ်ပြီး၊ ၎င်းကို ဖိုင်ရှိ kernel အရင်းအမြစ်ကုဒ်တွင် ကိန်းသေအဖြစ် သတ်မှတ်ထားသည်-

/* 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 အင်တာဖေ့စ်ကို ထည့်ရန် ကွန်ရက်လင့်ခ်တစ်ခုကို စီစဉ်သတ်မှတ်နိုင်စေမည်ဖြစ်သည်။

နောက်အပိုင်းတွင် စစ်ထုတ်ခြင်းကဲ့သို့သော အင်္ဂါရပ်များကို မည်သို့အသုံးပြုရမည်ကို ပြသထားသော်လည်း ကျွန်ုပ်တို့၏ကိုယ်ပိုင် filter များကို ပရိုဂရမ်စနစ်တကျအကောင်အထည်ဖော်နိုင်စေမည့် မတူညီသောနည်းပညာကို အသုံးပြုထားသည်။

Seccomp

Seccomp သည် Secure Computing ကို ကိုယ်စားပြုပြီး အချို့သော စနစ်ခေါ်ဆိုမှုများကို developer များအား စစ်ထုတ်ခွင့်ပြုသည့် Linux kernel တွင် အကောင်အထည်ဖော်သည့် လုံခြုံရေးအလွှာတစ်ခုဖြစ်သည်။ Seccomp သည် Linux နှင့် ယှဉ်နိုင်သော်လည်း၊ အချို့သော စနစ်ခေါ်ဆိုမှုများကို စီမံခန့်ခွဲနိုင်စွမ်းသည် ၎င်းတို့နှင့် နှိုင်းယှဉ်ပါက ပိုမိုပြောင်းလွယ်ပြင်လွယ်ရှိစေသည်။

Seccomp နှင့် Linux အင်္ဂါရပ်များသည် အပြန်အလှန်သီးသန့်မဟုတ်သည့်အပြင် ချဉ်းကပ်မှုနှစ်ခုစလုံးမှ အကျိုးရှိစေရန် မကြာခဏ အတူတကွအသုံးပြုကြသည်။ ဥပမာအားဖြင့်၊ သင်သည် CAP_NET_ADMIN စွမ်းရည်ကို လုပ်ငန်းစဉ်တစ်ခု ပေးလိုသော်လည်း ၎င်းကို socket ချိတ်ဆက်မှုများကို လက်ခံရန်၊ လက်ခံခြင်းနှင့် လက်ခံခြင်း 4 စနစ်ခေါ်ဆိုမှုများကို ပိတ်ဆို့ခြင်းမှ ခွင့်မပြုပါ။

Seccomp စစ်ထုတ်ခြင်းနည်းလမ်းသည် SECOMP_MODE_FILTER မုဒ်တွင် လုပ်ဆောင်နေသော BPF စစ်ထုတ်မှုများအပေါ် အခြေခံထားပြီး စနစ်ခေါ်ဆိုမှု စစ်ထုတ်ခြင်းအား ပက်ကတ်များအတွက်ကဲ့သို့ အလားတူနည်းလမ်းဖြင့် လုပ်ဆောင်ပါသည်။

PR_SET_SECOMP လည်ပတ်မှုမှတဆင့် prctl ကို အသုံးပြု၍ Seccomp စစ်ထုတ်မှုများကို တင်ထားသည်။ ဤစစ်ထုတ်မှုများသည် seccomp_data ဖွဲ့စည်းပုံဖြင့်ကိုယ်စားပြုသော Seccomp ပက်ကတ်တစ်ခုစီအတွက် လုပ်ဆောင်သည့် BPF ပရိုဂရမ်၏ပုံစံဖြစ်သည်။ ဤဖွဲ့စည်းပုံတွင် အကိုးအကားဗိသုကာ၊ စနစ်ခေါ်ဆိုချိန်တွင် ပရိုဆက်ဆာလမ်းညွှန်ချက်တစ်ခုနှင့် uint64 အဖြစ်ဖော်ပြသော အများဆုံးခြောက်ခုသော စနစ်ခေါ်ဆိုမှုဆိုင်ရာ အကြောင်းပြချက်များ ပါဝင်ပါသည်။

၎င်းသည် linux/seccomp.h ဖိုင်ရှိ kernel အရင်းအမြစ်ကုဒ်မှ seccomp_data တည်ဆောက်ပုံနှင့် တူသည်-

struct seccomp_data {
int nr;
      __u32 arch;
      __u64 instruction_pointer;
      __u64 args[6];
};

ဤဖွဲ့စည်းပုံမှ သင်တွေ့မြင်ရသည့်အတိုင်း၊ ကျွန်ုပ်တို့သည် စနစ်ခေါ်ဆိုမှု၊ ၎င်း၏ အကြောင်းပြချက်များ၊ သို့မဟုတ် နှစ်ခုလုံးကို ပေါင်းစပ်ခြင်းဖြင့် စစ်ထုတ်နိုင်ပါသည်။

Seccomp packet တစ်ခုစီကို လက်ခံရရှိပြီးနောက်၊ filter သည် နောက်ဆုံးဆုံးဖြတ်ချက်တစ်ခုချရန်နှင့် kernel ကို ဘာဆက်လုပ်ရမည်နည်း။ နောက်ဆုံးဆုံးဖြတ်ချက်ကို ပြန်ပေးတန်ဖိုးများ (အခြေအနေကုဒ်များ) မှ ထုတ်ဖော်သည်။

- SECOMP_RET_KILL_PROCESS - ၎င်းကြောင့် မလုပ်ဆောင်နိုင်သော စနစ်ခေါ်ဆိုမှုကို စစ်ထုတ်ပြီးနောက် လုပ်ငန်းစဉ်တစ်ခုလုံးကို ချက်ချင်းသတ်ပစ်သည်။

- SECOMP_RET_KILL_THREAD - ဤအရာကြောင့် မလုပ်ဆောင်နိုင်သော စနစ်ခေါ်ဆိုမှုတစ်ခုကို စစ်ထုတ်ပြီးနောက် ချက်ချင်းပင် လက်ရှိစာတွဲကို ရပ်စဲသည်။

— SECOMP_RET_KILL — SECOMP_RET_KILL_THREAD အတွက် နံမည်၊ နောက်ပြန်လိုက်ဖက်နိုင်စေရန် ချန်ထားခဲ့သည်။

- SECOMP_RET_TRAP - စနစ်ခေါ်ဆိုမှုကို တားမြစ်ထားပြီး SIGSYS (Bad System Call) အချက်ပြမှုကို ၎င်းကိုခေါ်ဆိုသည့်လုပ်ငန်းတာဝန်ထံ ပေးပို့သည်။

- SECOMP_RET_ERRNO - စနစ်ခေါ်ဆိုမှုအား လုပ်ဆောင်ခြင်းမရှိပါ၊ နှင့် SECOMP_RET_DATA စစ်ထုတ်ခြင်း၏တစ်စိတ်တစ်ပိုင်းကို errno တန်ဖိုးအဖြစ် အသုံးပြုသူနေရာသို့ လွှဲပြောင်းပေးပါသည်။ အမှား၏အကြောင်းရင်းပေါ်မူတည်၍ မတူညီသော errno တန်ဖိုးများကို ပြန်ပေးသည်။ နောက်အပိုင်းတွင် အမှားနံပါတ်များစာရင်းကို ပေးထားသည်။

- SECOMP_RET_TRACE - ထိုလုပ်ငန်းစဉ်ကိုကြည့်ရှုရန်နှင့် ထိန်းချုပ်ရန်အတွက် စနစ်ခေါ်ဆိုမှုကို လုပ်ဆောင်သည့်အခါ ကြားဖြတ်ရန် - PTRACE_O_TRACESECCOMP ကို ​​အသုံးပြု၍ ptrace ခြေရာခံကို အကြောင်းကြားရန် အသုံးပြုပါသည်။ ခြေရာခံကိရိယာကို မချိတ်ဆက်ပါက အမှားအယွင်းတစ်ခု ပြန်လာသည်၊ errno ကို -ENOSYS ဟုသတ်မှတ်ထားပြီး စနစ်ခေါ်ဆိုမှုကို လုပ်ဆောင်မည်မဟုတ်ပါ။

- SECOMP_RET_LOG - စနစ်ခေါ်ဆိုမှုကို ဖြေရှင်းပြီး အကောင့်ဝင်ထားသည်။

- SECOMP_RET_ALLOW - စနစ်ခေါ်ဆိုမှုကို ရိုးရှင်းစွာ ခွင့်ပြုထားသည်။

ptrace သည် tracee ဟုခေါ်သော လုပ်ငန်းစဉ်တစ်ခုတွင် ခြေရာခံယန္တရားများကို အကောင်အထည်ဖော်ရန် စနစ်ခေါ်ဆိုမှုဖြစ်ပြီး လုပ်ငန်းစဉ်၏လုပ်ဆောင်မှုကို စောင့်ကြည့်ထိန်းချုပ်နိုင်စွမ်းရှိသည်။ ခြေရာခံပရိုဂရမ်သည် လုပ်ဆောင်မှုကို ထိထိရောက်ရောက် လွှမ်းမိုးနိုင်ပြီး tracee ၏ မှတ်ဉာဏ်စာရင်းများကို မွမ်းမံနိုင်သည်။ Seccomp အကြောင်းအရာတွင် SECOMP_RET_TRACE အခြေအနေကုဒ်ဖြင့် အစပျိုးသောအခါ ptrace ကို အသုံးပြုသည်၊ ထို့ကြောင့် tracer သည် စနစ်ခေါ်ဆိုမှုကို လုပ်ဆောင်ခြင်းမှ တားဆီးနိုင်ပြီး ၎င်း၏ကိုယ်ပိုင် logic ကို အကောင်အထည်ဖေါ်ခြင်းမှ တားဆီးနိုင်ပါသည်။

Seccomp အမှားများ

ရံဖန်ရံခါ၊ Seccomp နှင့်အလုပ်လုပ်နေစဉ်၊ သင်သည် SECOMP_RET_ERRNO အမျိုးအစားပြန်တန်ဖိုးဖြင့်သတ်မှတ်ထားသော အမျိုးမျိုးသောအမှားအယွင်းများကိုကြုံတွေ့ရလိမ့်မည်။ အမှားအယွင်းတစ်ခုကို သတင်းပို့ရန်၊ seccomp စနစ်ခေါ်ဆိုမှုသည် 1 အစား -0 သို့ ပြန်သွားပါမည်။

အောက်ပါ အမှားများ ဖြစ်နိုင်သည်-

- EACCESS - ခေါ်ဆိုသူအား စနစ်ခေါ်ဆိုမှုပြုလုပ်ရန် ခွင့်မပြုပါ။ ၎င်းတွင် CAP_SYS_ADMIN အခွင့်ထူးများ မရှိသောကြောင့် သို့မဟုတ် no_new_privs ကို prctl ကို အသုံးပြု၍ မသတ်မှတ်ထားသောကြောင့် ဖြစ်တတ်သည် (ကျွန်ုပ်တို့ ဤအကြောင်းကို နောက်မှ ဆွေးနွေးပါမည်)။

— EFAULT — လွန်ခဲ့သော အကြောင်းပြချက်များ (seccomp_data တည်ဆောက်ပုံရှိ args) တွင် မှန်ကန်သောလိပ်စာ မရှိပါ။

— EINVAL — ဤနေရာတွင် အကြောင်းရင်းလေးခုရှိနိုင်သည်-

- လက်ရှိဖွဲ့စည်းပုံတွင် kernel မှ တောင်းဆိုထားသော လုပ်ဆောင်ချက်ကို မသိရှိ သို့မဟုတ် မပံ့ပိုးပါ။

- တောင်းဆိုထားသော လုပ်ဆောင်ချက်အတွက် သတ်မှတ်ထားသော အလံများသည် မမှန်ကန်ပါ။

-operation တွင် BPF_ABS ပါ၀င်သည်၊ သို့သော် seccomp_data ဖွဲ့စည်းပုံ၏ အရွယ်အစားထက် ကျော်လွန်နိုင်သော သတ်မှတ်ထားသော offset နှင့် ပြဿနာများရှိပါသည်။

- filter သို့ပေးပို့သော ညွှန်ကြားချက်အရေအတွက်သည် အများဆုံးထက် ကျော်လွန်နေပါသည်။

— ENOMEM — ပရိုဂရမ်ကိုလုပ်ဆောင်ရန် မလုံလောက်သောမှတ်ဉာဏ်၊

- EOPNOTSUPP - လုပ်ဆောင်ချက်သည် SECCOMP_GET_ACTION_AVAIL ဖြင့် လုပ်ဆောင်ချက်ကို ရရှိနိုင်သည်ဟု ညွှန်ပြသော်လည်း kernel သည် အကြောင်းပြချက်များတွင် ပြန်လာခြင်းကို မပံ့ပိုးပါ။

— ESRCH — အခြားစီးကြောင်းကို စင့်ခ်လုပ်သောအခါ ပြဿနာတစ်ခု ဖြစ်ပွားခဲ့သည်။

- ENOSYS - SECOMP_RET_TRACE လုပ်ဆောင်ချက်နှင့် တွဲထားသည့် ခြေရာခံ မရှိပါ။

prctl သည် အသုံးပြုသူ-အာကာသပရိုဂရမ်အား လုပ်ငန်းစဉ်တစ်ခု၏ သီးခြားရှုထောင့်များဖြစ်သည့် byte endianness၊ thread names၊ secure computation mode (Seccomp)၊ privileges၊ Perf events စသည်တို့ကဲ့သို့သော လုပ်ငန်းစဉ်တစ်ခုအား ကိုင်တွယ်ရန် ခွင့်ပြုသည့် စနစ်ခေါ်ဆိုမှုတစ်ခုဖြစ်သည်။

Seccomp သည် သင့်အတွက် sandbox နည်းပညာတစ်ခုကဲ့သို့ ထင်ရသော်လည်း ၎င်းသည် မဟုတ်ပါ။ Seccomp သည် အသုံးပြုသူများအား sandbox ယန္တရားတစ်ခုကို ဖန်တီးနိုင်စေမည့် အသုံးဝင်မှုတစ်ခုဖြစ်သည်။ ယခု Seccomp စနစ်ခေါ်ဆိုမှုမှ တိုက်ရိုက်ခေါ်သော စစ်ထုတ်မှုကို အသုံးပြု၍ အသုံးပြုသူ အပြန်အလှန်အကျိုးပြုသည့် ပရိုဂရမ်များကို မည်သို့ဖန်တီးထားသည်ကို ကြည့်ကြပါစို့။

BPF Seccomp Filter ဥပမာ

ဤနေရာတွင် စောစောက ဆွေးနွေးခဲ့သည့် လုပ်ဆောင်ချက်နှစ်ခုကို ပေါင်းစပ်နည်းကို ပြသပါမည်။

— ကျွန်ုပ်တို့သည် Seccomp BPF ပရိုဂရမ်ကို ရေးသားမည်ဖြစ်ပြီး၊ ဆုံးဖြတ်ချက်များပေါ်မူတည်၍ မတူညီသောပြန်ကုဒ်များပါသည့် စစ်ထုတ်မှုတစ်ခုအဖြစ် အသုံးပြုမည်ဖြစ်သည်။

— prctl ကို အသုံးပြု၍ filter ကို တင်ပါ။

ဦးစွာ သင်သည် စံစာကြည့်တိုက်နှင့် Linux kernel တို့မှ ခေါင်းစီးများ လိုအပ်သည်-

#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>

ဤဥပမာကို မကြိုးစားမီ၊ kernel ကို CONFIG_SECCOMP နှင့် CONFIG_SECOMP_FILTER ဟုသတ်မှတ်ထားခြင်းဖြင့် kernel ကို စုစည်းထားကြောင်း သေချာရပါမည်။ အလုပ်လုပ်သည့်စက်တွင် ဤကဲ့သို့စစ်ဆေးနိုင်သည်-

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_LD မှ BPF_W စကားလုံးပုံစံဖြင့် ထုပ်ပိုးပြီး ထုပ်ပိုးဒေတာသည် ပုံသေ အော့ဖ်ဆက် BPF_ABS တွင် တည်ရှိသည်။

- BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K၊ arch, 0, 3) - BPF_JEQ ကို အသုံးပြု၍ BPF_K accumulator တန်ဖိုးသည် arch နှင့် ညီမျှခြင်းရှိမရှိ စစ်ဆေးသည်။ သို့ဆိုလျှင်၊ arch နှင့် မကိုက်ညီသောကြောင့် အမှားတစ်ခုကိုပစ်ရန် offset 0 (ဤကိစ္စတွင်) မှ ခုန်တက်သည်။

- BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, nr))) - BPF_LD ၏ ပုံသေ အော့ဖ်ဆက်တွင်ပါရှိသော စနစ်ခေါ်ဆိုမှုနံပါတ်ဖြစ်သည့် BPF_W ဟူသော စကားလုံးပုံစံဖြင့် BPF_LD မှ စုစည်းလိုက်ပါသည်။

— BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, nr, 0, 1) — စနစ်ခေါ်ဆိုမှုနံပါတ်အား nr variable ၏တန်ဖိုးနှင့် နှိုင်းယှဉ်သည်။ ၎င်းတို့သည် တူညီပါက၊ နောက်ညွှန်ကြားချက်သို့ ဆက်သွားကာ စနစ်ခေါ်ဆိုမှုကို ပိတ်ပါ၊ သို့မဟုတ်ပါက စနစ်ခေါ်ဆိုမှုကို SECOMP_RET_ALLOW ဖြင့် ခွင့်ပြုပါသည်။

- BPF_STMT(BPF_RET + BPF_K, SECOMP_RET_ERRNO | (error & SECOMP_RET_DATA)) - BPF_RET ဖြင့် ပရိုဂရမ်ကို ရပ်ဆိုင်းလိုက်ပြီး ရလဒ်အနေဖြင့် SECOMP_RET_ERRNO နံပါတ်ဖြင့် err variable အမှားတစ်ခု ဖြစ်ပေါ်ပါသည်။

- BPF_STMT(BPF_RET + BPF_K၊ SECOMP_RET_ALLOW) - BPF_RET ဖြင့် ပရိုဂရမ်ကို ရပ်ဆိုင်းပြီး SECOMP_RET_ALLOW ကို အသုံးပြု၍ စနစ်ခေါ်ဆိုမှုကို လုပ်ဆောင်ခွင့်ပြုသည်။

SECOMP သည် CBPF ဖြစ်သည်။
စုစည်းထားသော ELF အရာဝတ္ထု သို့မဟုတ် JIT compiled C ပရိုဂရမ်အစား ညွှန်ကြားချက်များစာရင်းကို အဘယ်ကြောင့် အသုံးပြုရကြောင်း သင်အံ့သြနေပေမည်။

ဒီအတွက် အကြောင်းပြချက် နှစ်ခုရှိပါတယ်။

• ပထမဦးစွာ၊ Seccomp သည် cBPF (ဂန္ထဝင် BPF) ကိုအသုံးပြုပြီး eBPF မဟုတ်ဘဲ၊ ဆိုလိုသည်မှာ- ၎င်းတွင် စာရင်းသွင်းမှုများမရှိသော်လည်း နမူနာတွင်တွေ့နိုင်သည့်အတိုင်း နောက်ဆုံးတွက်ချက်မှုရလဒ်ကို သိမ်းဆည်းရန်အတွက် စုစည်းမှုတစ်ခုသာဖြစ်သည်။

• ဒုတိယ၊ Seccomp သည် BPF ညွှန်ကြားချက်များ၏ array တစ်ခုဆီသို့ ညွှန်ပြချက်ကို လက်ခံပြီး အခြားဘာမျှမရှိပါ။ ကျွန်ုပ်တို့အသုံးပြုထားသော မက်ခရိုများသည် ပရိုဂရမ်မာများအတွက် အဆင်ပြေသောနည်းလမ်းဖြင့် ဤညွှန်ကြားချက်များကို သတ်မှတ်ရာတွင် ကူညီပေးပါသည်။

ဤစည်းဝေးပွဲအား နားလည်ရန် နောက်ထပ်အကူအညီ လိုအပ်ပါက၊ တူညီသောအရာကို လုပ်ဆောင်သည့် pseudocode ကို စဉ်းစားပါ-

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

socket_filter ဖွဲ့စည်းပုံရှိ filter ကုဒ်ကို သတ်မှတ်ပြီးနောက်၊ ကုဒ်နှင့် filter ၏ တွက်ချက်ထားသော အရှည်ပါရှိသော sock_fprog ကို သတ်မှတ်ရန် လိုအပ်သည်။ နောက်ပိုင်းတွင် လုပ်ဆောင်ရန် လုပ်ငန်းစဉ်ကို ကြေညာရန်အတွက် ဤဒေတာဖွဲ့စည်းပုံသည် လိုအပ်သည်-

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

install_filter လုပ်ဆောင်ချက်တွင် လုပ်စရာတစ်ခုသာ ကျန်တော့သည် - ပရိုဂရမ်ကို သူ့ဘာသာသူ တင်ပါ။ ၎င်းကိုလုပ်ဆောင်ရန်၊ ကျွန်ုပ်တို့သည် PR_SET_SECOMP အား လုံခြုံသောကွန်ပျူတာမုဒ်သို့ဝင်ရောက်ရန် ရွေးချယ်မှုတစ်ခုအဖြစ် prctl ကိုအသုံးပြုသည်။ ထို့နောက် sock_fprog အမျိုးအစား၏ prog variable တွင်ပါရှိသော SECOMP_MODE_FILTER ကိုအသုံးပြု၍ filter ကိုဖွင့်ရန်မုဒ်အား ကျွန်ုပ်တို့ပြောသည်-

  if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
    perror("prctl(PR_SET_SECCOMP)");
    return 1;
  }
  return 0;
}

နောက်ဆုံးတွင်၊ ကျွန်ုပ်တို့သည် ကျွန်ုပ်တို့၏ install_filter လုပ်ဆောင်ချက်ကို အသုံးပြုနိုင်ပြီး၊ သို့သော် လက်ရှိလုပ်ဆောင်မှုအတွက် PR_SET_NO_NEW_PRIVS ကို သတ်မှတ်ရန် prctl ကို အသုံးပြုရန်လိုအပ်ပြီး ထို့ကြောင့် ကလေးလုပ်ငန်းစဉ်များသည် ၎င်းတို့၏မိဘများထက် ပိုမိုအခွင့်ထူးများရရှိသည့်အခြေအနေကို ရှောင်ရှားရန် လိုအပ်ပါသည်။ ဤအရာဖြင့်၊ ကျွန်ုပ်တို့သည် root လုပ်ပိုင်ခွင့်မရှိဘဲ အောက်ပါ prctl ခေါ်ဆိုမှုများကို install_filter လုပ်ဆောင်ချက်တွင် ပြုလုပ်နိုင်ပါသည်။

ယခုကျွန်ုပ်တို့သည် 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]);
 }

စလိုက်ကြစို့။ ကျွန်ုပ်တို့၏ပရိုဂရမ်ကို စုစည်းရန်အတွက် ကျွန်ုပ်တို့သည် အထူးရွေးချယ်စရာများမပါဘဲ main.c ဖိုင်ကို ပြုစုရာတွင် clang သို့မဟုတ် gcc တစ်ခုခုကို အသုံးပြုနိုင်သည်။

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

အံ့သြဖွယ်! ဤသည်မှာ ကျွန်ုပ်တို့၏ wrapper ပရိုဂရမ်ကို အသုံးပြု၍ ပုံသဏ္ဌာန်တူသည်- ကျွန်ုပ်တို့သည် ပထမအငြင်းအခုံအဖြစ် ကျွန်ုပ်တို့ စမ်းသပ်လိုသော ပရိုဂရမ်ကို ရိုးရှင်းစွာ ကျော်ဖြတ်သည်-

./filter-write "ls -la"

ကွပ်မျက်သောအခါ၊ ဤပရိုဂရမ်သည် လုံးဝအချည်းနှီးသော output ကိုထုတ်ပေးသည်။ မည်သို့ပင်ဆိုစေကာမူ၊ ကျွန်ုပ်တို့သည် အဘယ်အရာဖြစ်ပျက်နေသည်ကိုကြည့်ရန် ခြေရာကိုသုံးနိုင်သည်-

strace -f ./filter-write "ls -la"

အလုပ်၏ရလဒ်သည် အလွန်တိုတောင်းသော်လည်း ၎င်းနှင့်သက်ဆိုင်သောအပိုင်းသည် ကျွန်ုပ်တို့ပြင်ဆင်ထားသည့်အတိုင်းပင် EPERM အမှားဖြင့် မှတ်တမ်းများကို ပိတ်ဆို့ထားကြောင်း ပြသသည်။ ဆိုလိုသည်မှာ program သည် write system call ကိုဝင်ရောက်၍မရသောကြောင့် မည်သည့်အရာကိုမျှ output မပေးပါက၊

[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 ပရိုဂရမ်များအကြောင်းတွေးသောအခါ၊ လူအများစုက ၎င်းတို့ကို ရိုးရိုးရှင်းရှင်းရေးပြီး စီမံခန့်ခွဲသူအခွင့်ထူးများဖြင့် တင်သည်ဟု ထင်ကြသည်။ ဤဖော်ပြချက်သည် ယေဘူယျအားဖြင့် မှန်သော်လည်း၊ kernel သည် အဆင့်အမျိုးမျိုးတွင် eBPF အရာဝတ္ထုများကို ကာကွယ်ရန် ယန္တရားအစုတစ်ခုကို အကောင်အထည်ဖော်သည်။ ဤယန္တရားများကို BPF LSM ထောင်ချောက်များဟုခေါ်သည်။

BPF LSM ထောင်ချောက်များ

စနစ်ဖြစ်ရပ်များကို ဗိသုကာ-အမှီအခိုကင်းသောစောင့်ကြည့်မှုပေးရန်အတွက် LSM သည် ထောင်ချောက်များ၏သဘောတရားကိုအကောင်အထည်ဖော်သည်။ ချိတ်ခေါ်ဆိုမှုတစ်ခုသည် စနစ်ခေါ်ဆိုမှုတစ်ခုနှင့် နည်းပညာအရ ဆင်တူသော်လည်း စနစ်လွတ်လပ်ပြီး အခြေခံအဆောက်အအုံနှင့် ပေါင်းစပ်ထားသည်။ LSM သည် မတူညီသော ဗိသုကာများဆိုင်ရာ စနစ်ခေါ်ဆိုမှုများနှင့် ကိုင်တွယ်ရာတွင် ကြုံတွေ့ရသော ပြဿနာများကို ရှောင်ရှားနိုင်စေမည့် abstraction layer သည် အယူအဆအသစ်ကို ပေးပါသည်။

စာရေးချိန်တွင်၊ kernel တွင် BPF ပရိုဂရမ်များနှင့်ဆက်စပ်သောချိတ်ခုနစ်ခုရှိပြီး SELinux သည် ၎င်းတို့ကိုအကောင်အထည်ဖော်သည့်တစ်ခုတည်းသော built-in LSM ဖြစ်သည်။

ထောင်ချောက်များအတွက် ရင်းမြစ်ကုဒ်သည် ဖိုင်ရှိ kernel သစ်ပင်တွင် တည်ရှိသည် 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 - kernel သည် မြေပုံအတွက် ဖိုင်ဖော်ပြချက်တစ်ခုကို ပြန်ပေးသည့်အခါ စစ်ဆေးသည်။

- security_bpf_prog - kernel သည် eBPF ပရိုဂရမ်အတွက် ဖိုင်ဖော်ပြချက်တစ်ခုကို ပြန်ပေးသည့်အခါ စစ်ဆေးသည်။

— security_bpf_map_alloc — BPF မြေပုံများအတွင်း လုံခြုံရေးအကွက်ကို အစပြုထားခြင်း ရှိ၊မရှိ စစ်ဆေးသည် ။

- security_bpf_map_free - လုံခြုံရေးအကွက်ကို BPF မြေပုံများအတွင်း ရှင်းလင်းခြင်းရှိမရှိ စစ်ဆေးသည် ။

— security_bpf_prog_alloc — လုံခြုံရေးအကွက်ကို BPF ပရိုဂရမ်များအတွင်း အစပြုထားခြင်း ရှိ၊မရှိ စစ်ဆေးသည်။

- security_bpf_prog_free - လုံခြုံရေးအကွက်ကို BPF ပရိုဂရမ်များအတွင်း ရှင်းလင်းခြင်းရှိမရှိ စစ်ဆေးသည်။

ယခု ဤအရာအားလုံးကိုမြင်လျှင် ကျွန်ုပ်တို့နားလည်ပါသည်- LSM BPF ကြားဖြတ်ကိရိယာများနောက်ကွယ်ရှိ အယူအဆမှာ ၎င်းတို့သည် eBPF အရာဝတ္တုတိုင်းအတွက် အကာအကွယ်ပေးနိုင်ပြီး သင့်လျော်သောအခွင့်ထူးများရရှိသူများသာ ကတ်များနှင့် ပရိုဂရမ်များတွင် လုပ်ဆောင်ချက်များကို လုပ်ဆောင်နိုင်ကြောင်း သေချာစေပါသည်။

အကျဉ်းချုပ်

လုံခြုံရေးသည် သင်ကာကွယ်လိုသည့်အရာအားလုံးအတွက် အရွယ်အစား-အံဝင်ခွင်ကျဖြစ်စေသည့်နည်းလမ်းဖြင့် သင်အကောင်အထည်ဖော်နိုင်သော အရာမဟုတ်ပါ။ မတူညီသောအဆင့်များနှင့် မတူညီသောနည်းလမ်းများဖြင့် စနစ်များကို ကာကွယ်နိုင်စေရန် အရေးကြီးပါသည်။ ယုံသည်ဖြစ်စေ၊ မယုံသည်ဖြစ်စေ၊ စနစ်တစ်ခုကို လုံခြုံအောင်ပြုလုပ်ရန် အကောင်းဆုံးနည်းလမ်းမှာ မတူညီသောရာထူးများမှ ကာကွယ်မှုအဆင့်များကို စုစည်းထားခြင်းဖြစ်သည်၊ သို့မှသာ အဆင့်တစ်ခု၏လုံခြုံရေးကို လျှော့ချခြင်းဖြင့် စနစ်တစ်ခုလုံးကို ဝင်ရောက်ခွင့်မပြုနိုင်ပေ။ ပင်မ developer များသည် မတူညီသော အလွှာများနှင့် ထိတွေ့မှုနေရာများကို ပေးဆောင်ရန် ကောင်းမွန်သောအလုပ်များ လုပ်ဆောင်ခဲ့သည်။ အလွှာများသည် အဘယ်အလွှာများဖြစ်ပြီး ၎င်းတို့နှင့်လုပ်ဆောင်ရန် BPF ပရိုဂရမ်များကို အသုံးပြုပုံတို့ကို ကောင်းစွာနားလည်သဘောပေါက်နိုင်မည်ဟု မျှော်လင့်ပါသည်။

စာရေးဆရာများအကြောင်း

David Calavera Netlify တွင် CTO ဖြစ်သည်။ သူသည် Docker ပံ့ပိုးကူညီမှုတွင် အလုပ်လုပ်ခဲ့ပြီး Runc၊ Go နှင့် BCC ကိရိယာများအပြင် အခြားသော open source ပရောဂျက်များကို ပံ့ပိုးကူညီခဲ့သည်။ Docker ပရောဂျက်များနှင့် Docker ပလပ်အင်ဂေဟစနစ်၏ ဖွံ့ဖြိုးတိုးတက်မှုအတွက် သူ၏လုပ်ဆောင်မှုကြောင့် လူသိများသည်။ David သည် မီးတောက်ဂရပ်ဖစ်များကို အလွန်စိတ်အားထက်သန်ပြီး စွမ်းဆောင်ရည်ကို အကောင်းဆုံးဖြစ်အောင် အမြဲရှာဖွေနေပါသည်။

Lorenzo Fontana Kernel module နှင့် eBPF မှတဆင့် ကွန်တိန်နာ runtime လုံခြုံရေးနှင့် ကွဲလွဲချက်များကို သိရှိနိုင်စေရန် ပံ့ပိုးပေးသော Cloud Native Computing Foundation ပရောဂျက် Falco ကို အဓိကအာရုံစိုက်ထားသည့် Sysdig ရှိ open source အဖွဲ့တွင် အလုပ်လုပ်ပါသည်။ သူသည် ဖြန့်ဝေသည့်စနစ်များ၊ ဆော့ဖ်ဝဲလ်သတ်မှတ်ထားသော ကွန်ရက်ချိတ်ဆက်မှု၊ Linux kernel နှင့် စွမ်းဆောင်ရည်ပိုင်းခွဲခြမ်းစိတ်ဖြာမှုများကို စိတ်အားထက်သန်သူဖြစ်သည်။

» စာအုပ်နှင့်ပတ်သက်သော အသေးစိတ်အချက်အလက်များကို အောက်ပါလင့်တွင် ကြည့်ရှုနိုင်ပါသည်။ ထုတ်ဝေသူ၏ဝဘ်ဆိုဒ်
» မာတိကာ
» ကောက်နုတ်ချက်

Khabrozhiteley ကူပွန်ကိုအသုံးပြု၍ 25% လျှော့စျေးအတွက် - Linux ကို

စာအုပ်၏ စက္ကူဗားရှင်းကို ငွေပေးချေပြီးပါက အီလက်ထရွန်နစ်စာအုပ်ကို အီးမေးလ်ဖြင့် ပေးပို့မည်ဖြစ်သည်။

source: www.habr.com

မှတ်ချက် Add