පොත "ලිනක්ස් නිරීක්ෂණ සඳහා BPF"

පොත "ලිනක්ස් නිරීක්ෂණ සඳහා BPF"ආයුබෝවන්, Khabro පදිංචිකරුවන්! BPF අතථ්‍ය යන්ත්‍රය ලිනක්ස් කර්නලයේ වැදගත්ම අංගයකි. එහි නිසි භාවිතය පද්ධති ඉංජිනේරුවන්ට දෝෂ සොයා ගැනීමට සහ වඩාත් සංකීර්ණ ගැටළු පවා විසඳීමට ඉඩ සලසයි. කර්නලයේ හැසිරීම නිරීක්ෂණය කරන සහ වෙනස් කරන වැඩසටහන් ලියන ආකාරය, කර්නලයේ සිදුවීම් නිරීක්ෂණය කිරීමට කේතය ආරක්ෂිතව ක්‍රියාත්මක කරන ආකාරය සහ තවත් බොහෝ දේ ඔබ ඉගෙන ගනු ඇත. ඩේවිඩ් කැලවේරා සහ ලොරෙන්සෝ ෆොන්ටානා ඔබට BPF හි බලය අගුළු ඇරීමට උදවු කරනු ඇත. කාර්ය සාධන ප්‍රශස්තකරණය, ජාලකරණය, ආරක්ෂාව පිළිබඳ ඔබේ දැනුම පුළුල් කරන්න. - ලිනක්ස් කර්නලයේ හැසිරීම නිරීක්ෂණය කිරීමට සහ වෙනස් කිරීමට BPF භාවිතා කරන්න. - කර්නලය නැවත සම්පාදනය කිරීම හෝ පද්ධතිය නැවත ආරම්භ කිරීමකින් තොරව කර්නල් සිදුවීම් ආරක්ෂිතව නිරීක්ෂණය කිරීමට කේතය එන්නත් කරන්න. - C, Go හෝ Python හි පහසු කේත උදාහරණ භාවිතා කරන්න. - BPF වැඩසටහන් ජීවන චක්‍රය හිමිකර ගැනීමෙන් පාලනය ගන්න.

Linux Kernel Security, එහි විශේෂාංග සහ Seccomp

BPF ස්ථාවරත්වය, ආරක්ෂාව හෝ වේගය කැප නොකර කර්නලය දිගු කිරීමට ප්‍රබල ක්‍රමයක් සපයයි. මේ හේතුව නිසා, කර්නල් සංවර්ධකයින් සිතුවේ, BPF වැඩසටහන් මගින් සහය දක්වන Seccomp පෙරහන් ක්‍රියාත්මක කිරීමෙන්, Seccomp BPF ලෙසද හැඳින්වෙන, Seccomp හි ක්‍රියාවලි හුදකලාව වැඩිදියුණු කිරීම සඳහා එහි බහුකාර්යතාව භාවිතා කිරීම හොඳ අදහසකි. මෙම පරිච්ඡේදයෙන් අපි Seccomp යනු කුමක්ද සහ එය භාවිතා කරන්නේ කෙසේද යන්න පැහැදිලි කරමු. එවිට ඔබ BPF වැඩසටහන් භාවිතයෙන් Seccomp පෙරහන් ලියන ආකාරය ඉගෙන ගනු ඇත. ඊට පසු, අපි Linux ආරක්ෂක මොඩියුල සඳහා කර්නලයට ඇතුළත් කර ඇති BPF කොකු දෙස බලමු.

Linux Security Modules (LSM) යනු විවිධ ආරක්ෂක මාදිලි ප්‍රමිතිගත ආකාරයෙන් ක්‍රියාත්මක කිරීමට භාවිතා කළ හැකි කාර්යයන් සමූහයක් සපයන රාමුවකි. LSM Apparmor, SELinux සහ Tomoyo වැනි කර්නල් ප්‍රභව ගසෙහි සෘජුවම භාවිතා කළ හැක.

අපි 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

කෙසේ වෙතත්, අපි මූල වරප්‍රසාද ලබා නොදෙන බැවින්, මෙම කේතය වරාය බැඳීමේදී දෝෂයක් ඇති කරයි:

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

capsh (shell manager) යනු විශේෂිත හැකියාවන් සමූහයක් සහිත shell එකක් ධාවනය කරන මෙවලමකි.

මෙම අවස්ථාවේදී, දැනටමත් සඳහන් කර ඇති පරිදි, සම්පූර්ණ මූල අයිතිවාසිකම් ලබා දීම වෙනුවට, ඔබට දැනටමත් වැඩසටහනේ ඇති අනෙකුත් සියල්ල සමඟ 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 සහ පරිශීලක හැඳුනුම්පත ඇත්ත වශයෙන්ම වෙනස් කිරීමේ හැකියාව සඳහන් කරන්නෙමු. කිසිවෙකුට root නොවේ, එනම් cap_setuid සහ cap_setgid.
  • —keep=1 — අපට root ගිණුමෙන් මාරු වන විට ස්ථාපිත හැකියාවන් තබා ගැනීමට අවශ්‍යය.
  • —user=“කවුරුවත්” — වැඩසටහන ක්‍රියාත්මක කරන අවසාන පරිශීලකයා කිසිවෙක් නොවනු ඇත.
  • —addamb=cap_net_bind_service — මූල මාදිලියෙන් මාරු වීමෙන් පසු අදාළ හැකියාවන් ඉවත් කිරීම සකසන්න.
  • - -c "./හැකියාවන්" - වැඩසටහන ක්‍රියාත්මක කරන්න.

සම්බන්ධිත හැකියාවන් යනු වත්මන් වැඩසටහන execve() භාවිතයෙන් ක්‍රියාත්මක කරන විට ළමා වැඩසටහන් වලට උරුම වන විශේෂ ආකාරයේ හැකියාවන් වේ. සම්බන්ධ වීමට අවසර දී ඇති හැකියාවන් හෝ වෙනත් වචන වලින් කිවහොත් පාරිසරික හැකියාවන් ලෙස පමණක් උරුම විය හැකිය.

--caps විකල්පයේ හැකියාව සඳහන් කිරීමෙන් පසු +eip යනු කුමක්දැයි ඔබ කල්පනා කරනවා විය හැකිය. හැකියාව තීරණය කිරීමට මෙම කොඩි භාවිතා කරයි:

- සක්රිය කළ යුතුය (p);

- භාවිතය සඳහා පවතී (ඉ);

- ළමා ක්රියාවලීන් (i) මගින් උරුම විය හැක.

අපට cap_net_bind_service භාවිතා කිරීමට අවශ්‍ය බැවින්, අපි මෙය e ධජය සමඟ කළ යුතුයි. එවිට අපි විධානය තුළ shell එක ආරම්භ කරමු. මෙය හැකියාවන් ද්විමය ධාවනය කරන අතර අපි එය i ධජය සමඟ සලකුණු කළ යුතුය. අවසාන වශයෙන්, අපට p සමඟ විශේෂාංගය සක්‍රීය කිරීමට අවශ්‍යයි (අපි UID වෙනස් නොකර මෙය කළෙමු). එය cap_net_bind_service+eip වගේ.

ඔබට ss භාවිතයෙන් ප්‍රතිඵලය පරීක්ෂා කළ හැක. පිටුවට ගැළපෙන පරිදි ප්‍රතිදානය මඳක් කෙටි කරමු, නමුත් එය 0 හැර වෙනත් සම්බන්ධිත වරාය සහ පරිශීලක හැඳුනුම්පත පෙන්වයි, මෙම අවස්ථාවේදී 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 කර්නල් ශ්‍රිතය සඳහා 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 ශ්‍රිතයේ එක්-ලයිනර් 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 ය, එය ගොනුවේ ඇති කර්නල් ප්‍රභව කේතයේ නියතයක් ලෙස අර්ථ දක්වා ඇත ඇතුළත්/uapi/linux/ability.h හඳුනාගැනීමේ 10:

/* 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

Seccomp යනු Secure Computing සඳහා වන අතර එය ලිනක්ස් කර්නලයේ ක්‍රියාත්මක කරන ලද ආරක්ෂක ස්ථරයක් වන අතර එය සංවර්ධකයින්ට ඇතැම් පද්ධති ඇමතුම් පෙරීමට ඉඩ සලසයි. Seccomp හැකියාවන් Linux සමඟ සැසඳිය හැකි වුවද, ඇතැම් පද්ධති ඇමතුම් කළමනාකරණය කිරීමට ඇති හැකියාව ඒවාට සාපේක්ෂව එය වඩාත් නම්‍යශීලී කරයි.

Seccomp සහ Linux විශේෂාංග අන්‍යෝන්‍ය වශයෙන් බැහැර නොවන අතර ප්‍රවේශ දෙකෙන්ම ප්‍රතිලාභ ලබා ගැනීම සඳහා බොහෝ විට එකට භාවිතා වේ. උදාහරණයක් ලෙස, ඔබට CAP_NET_ADMIN හැකියාව ක්‍රියාවලියක් ලබා දීමට අවශ්‍ය විය හැකි නමුත් එයට සොකට් සම්බන්ධතා පිළිගැනීමට ඉඩ නොදෙන අතර, පිළිගැනීම සහ පිළිගන්න4 පද්ධති ඇමතුම් අවහිර කරයි.

Seccomp පෙරීමේ ක්‍රමය SECCOMP_MODE_FILTER මාදිලියේ ක්‍රියාත්මක වන BPF ෆිල්ටර මත පදනම් වන අතර, පද්ධති ඇමතුම් පෙරීම පැකට් සඳහා සිදු කරන ආකාරයටම සිදු කෙරේ.

PR_SET_SECCOMP මෙහෙයුම හරහා prctl භාවිතයෙන් Seccomp පෙරහන් පූරණය වේ. මෙම පෙරහන් seccomp_data ව්‍යුහය මගින් නියෝජනය කරන සෑම Seccomp පැකට්ටුවක් සඳහාම ක්‍රියාත්මක වන BPF වැඩසටහනක ස්වරූපය ගනී. මෙම ව්‍යුහයේ සමුද්දේශ ගෘහ නිර්මාණ ශිල්පය, පද්ධති ඇමතුමේ දී ප්‍රොසෙසර උපදෙස් සඳහා දර්ශකයක් සහ uint64 ලෙස ප්‍රකාශිත උපරිම පද්ධති ඇමතුම් තර්ක හයක් අඩංගු වේ.

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 පෙරහන් ප්‍රතිලාභ අගයෙන් කොටසක් වැරදි අගය ලෙස පරිශීලක අවකාශය වෙත යවනු ලැබේ. දෝෂයට හේතුව මත පදනම්ව, විවිධ වැරදි අගයන් ආපසු ලබා දෙනු ලැබේ. දෝෂ අංක ලැයිස්තුවක් ඊළඟ කොටසේ දක්වා ඇත.

- SECCOMP_RET_TRACE - එම ක්‍රියාවලිය දැකීමට සහ පාලනය කිරීමට පද්ධති ඇමතුමක් ක්‍රියාත්මක වන විට බාධා කිරීමට - PTRACE_O_TRACESECCOMP භාවිතයෙන් ptrace tracer වෙත දැනුම් දීමට භාවිතා කරයි. ලුහුබැඳීමක් සම්බන්ධ කර නොමැති නම්, දෝෂයක් නැවත පැමිණේ, errno -ENOSYS ලෙස සකසා ඇත, සහ පද්ධති ඇමතුම ක්‍රියාත්මක නොවේ.

- SECCOMP_RET_LOG - පද්ධති ඇමතුම විසඳා ලොග් වී ඇත.

- SECCOMP_RET_ALLOW - පද්ධති ඇමතුම සරලව අවසර දී ඇත.

ptrace යනු ට්‍රේසි නම් ක්‍රියාවලියක් තුළ ලුහුබැඳීමේ යාන්ත්‍රණයන් ක්‍රියාත්මක කිරීමට පද්ධති ඇමතුමකි, ක්‍රියාවලිය ක්‍රියාත්මක කිරීම නිරීක්ෂණය කිරීමට සහ පාලනය කිරීමට හැකියාව ඇත. ට්‍රේස් ක්‍රමලේඛය ක්‍රියාත්මක කිරීමට ඵලදායි ලෙස බලපෑම් කිරීමට සහ ට්‍රේසිගේ මතක ලේඛන වෙනස් කිරීමට හැකිය. Seccomp සන්දර්භය තුළ, SECCOMP_RET_TRACE තත්ත්‍ව කේතය මඟින් ක්‍රියාරම්භ කරන විට ptrace භාවිතා වේ, එබැවින් ලුහුබැඳීම මඟින් පද්ධති ඇමතුම ක්‍රියාත්මක වීම වළක්වා එහිම තර්කනය ක්‍රියාත්මක කළ හැක.

Seccomp දෝෂ

කලින් කලට, Seccomp සමඟ වැඩ කරන විට, ඔබට විවිධ දෝෂ හමු වනු ඇත, ඒවා SECCOMP_RET_ERRNO වර්ගයේ ප්‍රතිලාභ අගයකින් හඳුනා ගනී. දෝෂයක් වාර්තා කිරීමට, seccomp පද්ධති ඇමතුම 1 වෙනුවට -0 ලබා දෙනු ඇත.

පහත දෝෂ ඇතිවිය හැක:

- ප්‍රවේශය - ඇමතුම්කරුට පද්ධති ඇමතුමක් ගැනීමට අවසර නැත. මෙය සාමාන්‍යයෙන් සිදුවන්නේ එයට CAP_SYS_ADMIN වරප්‍රසාද නොමැති නිසා හෝ prctl භාවිතයෙන් no_new_privs සකසා නොමැති නිසා (අපි මේ ගැන පසුව කතා කරමු);

— EFAULT — සම්මත කරන ලද තර්කවලට (seccomp_data ව්‍යුහයේ ඇති args) වලංගු ලිපිනයක් නොමැත;

- EINVAL - මෙහි හේතු හතරක් තිබිය හැක:

-ඉල්ලන ලද මෙහෙයුම වත්මන් වින්‍යාසය තුළ කර්නලය විසින් නොදන්නා හෝ සහාය නොදක්වයි;

ඉල්ලූ මෙහෙයුම සඳහා නිශ්චිත කොඩි වලංගු නොවේ;

-මෙහෙයුමට BPF_ABS ඇතුළත් වේ, නමුත් seccomp_data ව්‍යුහයේ ප්‍රමාණය ඉක්මවිය හැකි නිශ්චිත ඕෆ්සෙට් සමඟ ගැටලු තිබේ;

-පෙරහන වෙත ලබා දුන් උපදෙස් ගණන උපරිමය ඉක්මවයි;

- ENOMEM - වැඩසටහන ක්‍රියාත්මක කිරීමට ප්‍රමාණවත් මතකයක් නොමැත;

- EOPNOTSUPP - මෙහෙයුම SECCOMP_GET_ACTION_AVAIL සමඟ ක්‍රියාව පවතින බව පෙන්නුම් කරයි, නමුත් කර්නලය තර්ක වල ප්‍රතිලාභ සඳහා සහය නොදක්වයි;

- ESRCH - වෙනත් ධාරාවක් සමමුහුර්ත කිරීමේදී ගැටළුවක් ඇති විය;

- ENOSYS - SECCOMP_RET_TRACE ක්‍රියාවට අනුරේඛනයක් නොමැත.

prctl යනු byte endianness, thread names, Security computation mode (Seccomp), privileges, Perf events යනාදී ක්‍රියාවලියක විශේෂිත අංගයන් හැසිරවීමට (සැකසීමට සහ ලබා ගැනීමට) පරිශීලක-අවකාශ වැඩසටහනකට ඉඩ සලසන පද්ධති ඇමතුමකි.

Seccomp ඔබට සෑන්ඩ්බොක්ස් තාක්ෂණයක් සේ පෙනෙන නමුත් එය එසේ නොවේ. Seccomp යනු සෑන්ඩ්බොක්ස් යාන්ත්‍රණයක් සංවර්ධනය කිරීමට පරිශීලකයින්ට ඉඩ සලසන උපයෝගීතාවයකි. දැන් අපි බලමු Seccomp පද්ධති ඇමතුම මගින් කෙලින්ම කියන ෆිල්ටරයක් ​​භාවිතයෙන් පරිශීලක අන්තර්ක්‍රියා වැඩසටහන් නිර්මාණය කරන්නේ කෙසේදැයි බලමු.

BPF Seccomp පෙරහන් උදාහරණය

මෙහිදී අපි කලින් සාකච්ඡා කළ ක්‍රියා දෙක ඒකාබද්ධ කරන්නේ කෙසේදැයි පෙන්වමු, එනම්:

- අපි Seccomp BPF වැඩසටහනක් ලියන්නෙමු, එය ගනු ලබන තීරණ අනුව විවිධ ප්‍රතිලාභ කේත සහිත පෙරනයක් ලෙස භාවිතා කරනු ඇත;

- prctl භාවිතයෙන් පෙරණය පූරණය කරන්න.

පළමුව ඔබට සම්මත පුස්තකාලයෙන් සහ ලිනක්ස් කර්නලයෙන් ශීර්ෂ අවශ්‍ය වේ:

#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_LD යන වචනයේ ස්වරූපයෙන් පද්ධතිය පූරණය වී එකතු වේ, පැකට් දත්ත BPF_ABS ස්ථාවර ඕෆ්සෙට් එකක පිහිටා ඇත.

- BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arch, 0, 3) - සමුච්චක නියත BPF_K හි ගෘහ නිර්මාණ අගය ආරුක්කුවට සමාන වේද යන්න BPF_JEQ භාවිතයෙන් පරීක්ෂා කරයි. එසේ නම්, ඕෆ්සෙට් 0 හිදී මීළඟ උපදෙස් වෙත පනින්න, එසේ නොමැතිනම් ඕෆ්සෙට් 3 (මෙම අවස්ථාවේදී) ආරුක්කුව නොගැලපෙන නිසා දෝෂයක් ඇති කිරීමට පනින්න.

- BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, nr))) - BPF_ABS හි ස්ථාවර ඕෆ්සෙට්හි අඩංගු පද්ධති ඇමතුම් අංකය වන BPF_LD යන වචනයේ 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 සමඟින් වැඩසටහන අවසන් කරන අතර එහි ප්‍රතිඵලයක් ලෙස වැරදි විචල්‍යයේ අංකය සමඟ SECCOMP_RET_ERRNO දෝෂයක් ඇති කරයි.

- BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW) - BPF_RET සමඟින් වැඩසටහන අවසන් කරන අතර SECCOMP_RET_ALLOW භාවිතයෙන් පද්ධති ඇමතුම ක්‍රියාත්මක කිරීමට ඉඩ සලසයි.

SECCOMP යනු CBPF ය
සම්පාදනය කරන ලද ELF වස්තුවක් හෝ JIT සම්පාදනය කළ C වැඩසටහනක් වෙනුවට උපදෙස් ලැයිස්තුවක් භාවිතා කරන්නේ මන්දැයි ඔබ කල්පනා කරනවා විය හැකිය.

මෙයට හේතු දෙකක් තිබේ.

• පළමුව, Seccomp cBPF (සම්භාව්‍ය BPF) භාවිතා කරන අතර eBPF නොවේ, එනම්: එයට රෙජිස්ටර් නොමැත, නමුත් උදාහරණයේ දැකිය හැකි පරිදි ගණනය කිරීමේ අවසාන ප්‍රතිඵලය ගබඩා කිරීම සඳහා ඇකියුමුලේටරයක් ​​පමණි.

• දෙවනුව, 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 ශ්‍රිතයේ කිරීමට ඉතිරිව ඇත්තේ එක දෙයයි - වැඩසටහනම පූරණය කරන්න! මෙය සිදු කිරීම සඳහා, අපි ආරක්ෂිත පරිගණක මාදිලියට ඇතුළු වීමට 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 ශ්‍රිතය භාවිතා කළ හැක, නමුත් ඊට පෙර අපි වත්මන් ක්‍රියාත්මක කිරීම සඳහා PR_SET_NO_NEW_PRIVS සැකසීමට prctl භාවිතා කිරීමට අවශ්‍ය වන අතර එමඟින් ළමා ක්‍රියාවලීන්ට ඔවුන්ගේ දෙමාපියන්ට වඩා වැඩි වරප්‍රසාද ලැබෙන තත්ත්වය මඟහරවා ගත යුතුය. මෙමගින්, අපට 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

පුදුමයි! මෙන්න අපගේ wrapper වැඩසටහන භාවිතා කරන ආකාරය: අපි සරලව අපට පරීක්ෂා කිරීමට අවශ්‍ය වැඩසටහන පළමු තර්කය ලෙස සමත් කරමු:

./filter-write "ls -la"

ක්රියාත්මක වන විට, මෙම වැඩසටහන සම්පූර්ණයෙන්ම හිස් ප්රතිදානය නිපදවයි. කෙසේ වෙතත්, අපට සිදුවන්නේ කුමක්ද යන්න බැලීමට strace භාවිතා කළ හැක:

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

කාර්යයේ ප්‍රති result ලය බොහෝ සෙයින් කෙටි වී ඇත, නමුත් එහි අනුරූප කොටස පෙන්නුම් කරන්නේ EPERM දෝෂය සමඟ වාර්තා අවහිර කර ඇති බවයි - අපි වින්‍යාස කළ එකම එක. මෙයින් අදහස් කරන්නේ එය ලිවීමේ පද්ධති ඇමතුමට ප්‍රවේශ විය නොහැකි නිසා වැඩසටහන කිසිවක් ප්‍රතිදානය නොකරන බවයි:

[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 වැඩසටහන් හා සම්බන්ධ කොකු හතක් ඇති අතර, SELinux යනු ඒවා ක්‍රියාත්මක කරන එකම ගොඩනඟන ලද LSM වේ.

උගුල් සඳහා මූලාශ්‍ර කේතය ගොනුවේ කර්නල් ගසෙහි ස්ථානගත කර ඇත ඇතුළත්/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 interceptors පිටුපස ඇති අදහස නම්, ඔවුන්ට සෑම eBPF වස්තුවකටම ආරක්ෂාව සැපයිය හැකි අතර, සුදුසු වරප්‍රසාද ඇති අයට පමණක් කාඩ්පත් සහ වැඩසටහන් වල මෙහෙයුම් සිදු කළ හැකි බව සහතික කිරීමයි.

සාරාංශය

ආරක්‍ෂාව යනු ඔබට ආරක්‍ෂා කිරීමට අවශ්‍ය සෑම දෙයකටම එක ප්‍රමාණයකට ගැලපෙන ආකාරයෙන් ක්‍රියාත්මක කළ හැකි දෙයක් නොවේ. විවිධ මට්ටම්වල සහ විවිධ ආකාරවලින් පද්ධති ආරක්ෂා කිරීමට හැකි වීම වැදගත් වේ. විශ්වාස කරන්න හෝ නොවන්න, පද්ධතියක් සුරක්ෂිත කිරීම සඳහා හොඳම ක්රමය වන්නේ විවිධ ස්ථානවල සිට විවිධ මට්ටමේ ආරක්ෂාවක් සංවිධානය කිරීමයි, එවිට එක් මට්ටමක ආරක්ෂාව අඩු කිරීම සමස්ත පද්ධතියට ප්රවේශ වීමට ඉඩ නොදේ. ප්‍රධාන සංවර්ධකයින් අපට විවිධ ස්ථර සහ ටච් පොයින්ට් කට්ටලයක් ලබා දීමට විශාල කාර්යයක් කර ඇත. ස්ථර මොනවාද සහ ඒවා සමඟ වැඩ කිරීමට BPF වැඩසටහන් භාවිතා කරන්නේ කෙසේද යන්න පිළිබඳව අපි ඔබට හොඳ අවබෝධයක් ලබා දී ඇතැයි අපි බලාපොරොත්තු වෙමු.

කතුවරුන් ගැන

ඩේවිඩ් කලවේරා Netliify හි CTO වේ. ඔහු ඩොකර් සහායක සේවය කළ අතර Runc, Go සහ BCC මෙවලම් මෙන්ම අනෙකුත් විවෘත මූලාශ්‍ර ව්‍යාපෘති සංවර්ධනය කිරීමට දායක විය. ඩොකර් ව්‍යාපෘති සහ ඩොකර් ප්ලගින පරිසර පද්ධතියේ සංවර්ධනය පිළිබඳ ඔහුගේ වැඩ සඳහා ප්‍රසිද්ධය. ඩේවිඩ් ගිනි ප්‍රස්ථාර කෙරෙහි දැඩි ඇල්මක් දක්වන අතර සෑම විටම කාර්ය සාධනය ප්‍රශස්ත කිරීමට බලාපොරොත්තු වේ.

ලොරෙන්සෝ ෆොන්ටානා Sysdig හි විවෘත මූලාශ්‍ර කණ්ඩායමෙහි ක්‍රියා කරයි, එහිදී ඔහු මූලික වශයෙන් අවධානය යොමු කර ඇත්තේ කර්නල් මොඩියුලයක් සහ eBPF හරහා බහාලුම් ධාවන කාල ආරක්ෂාව සහ විෂමතා හඳුනාගැනීම සපයන Cloud Native Computing Foundation ව්‍යාපෘතියක් වන Falco වෙතය. ඔහු බෙදා හරින ලද පද්ධති, මෘදුකාංග නිර්වචනය කළ ජාලකරණය, ලිනක්ස් කර්නලය සහ කාර්ය සාධන විශ්ලේෂණය කෙරෙහි දැඩි ඇල්මක් දක්වයි.

» පොත පිළිබඳ වැඩි විස්තර මෙතැනින් සොයාගත හැකිය ප්රකාශකයාගේ වෙබ් අඩවිය
» පටුන
» උපුටා ගැනීමකි

Khabrozhiteley සඳහා කූපනය භාවිතයෙන් 25% වට්ටමක් - ලිනක්ස්

පොතේ කඩදාසි පිටපත ගෙවීමෙන් පසු විද්‍යුත් පොතක් විද්‍යුත් තැපෑලෙන් එවනු ලැබේ.

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න