ಪುಸ್ತಕ "ಲಿನಕ್ಸ್ ಮಾನಿಟರಿಂಗ್ಗಾಗಿ ಬಿಪಿಎಫ್"

ಪುಸ್ತಕ "ಲಿನಕ್ಸ್ ಮಾನಿಟರಿಂಗ್ಗಾಗಿ ಬಿಪಿಎಫ್"ಹಲೋ, ಖಬ್ರೋ ನಿವಾಸಿಗಳು! BPF ವರ್ಚುವಲ್ ಯಂತ್ರವು Linux ಕರ್ನಲ್‌ನ ಪ್ರಮುಖ ಅಂಶಗಳಲ್ಲಿ ಒಂದಾಗಿದೆ. ಇದರ ಸರಿಯಾದ ಬಳಕೆಯು ಸಿಸ್ಟಮ್ ಇಂಜಿನಿಯರ್‌ಗಳಿಗೆ ದೋಷಗಳನ್ನು ಕಂಡುಹಿಡಿಯಲು ಮತ್ತು ಅತ್ಯಂತ ಸಂಕೀರ್ಣ ಸಮಸ್ಯೆಗಳನ್ನು ಪರಿಹರಿಸಲು ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ. ಕರ್ನಲ್‌ನ ನಡವಳಿಕೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡುವ ಮತ್ತು ಮಾರ್ಪಡಿಸುವ ಪ್ರೋಗ್ರಾಮ್‌ಗಳನ್ನು ಹೇಗೆ ಬರೆಯುವುದು, ಕರ್ನಲ್‌ನಲ್ಲಿನ ಈವೆಂಟ್‌ಗಳನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಲು ಕೋಡ್ ಅನ್ನು ಸುರಕ್ಷಿತವಾಗಿ ಕಾರ್ಯಗತಗೊಳಿಸುವುದು ಮತ್ತು ಇನ್ನೂ ಹೆಚ್ಚಿನದನ್ನು ನೀವು ಕಲಿಯುವಿರಿ. ಡೇವಿಡ್ ಕ್ಯಾಲವೆರಾ ಮತ್ತು ಲೊರೆಂಜೊ ಫಾಂಟಾನಾ BPF ನ ಶಕ್ತಿಯನ್ನು ಅನ್ಲಾಕ್ ಮಾಡಲು ನಿಮಗೆ ಸಹಾಯ ಮಾಡುತ್ತಾರೆ. ಕಾರ್ಯಕ್ಷಮತೆ ಆಪ್ಟಿಮೈಸೇಶನ್, ನೆಟ್‌ವರ್ಕಿಂಗ್, ಭದ್ರತೆಯ ಬಗ್ಗೆ ನಿಮ್ಮ ಜ್ಞಾನವನ್ನು ವಿಸ್ತರಿಸಿ. - Linux ಕರ್ನಲ್‌ನ ನಡವಳಿಕೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಲು ಮತ್ತು ಮಾರ್ಪಡಿಸಲು BPF ಅನ್ನು ಬಳಸಿ. - ಕರ್ನಲ್ ಅನ್ನು ಮರುಕಂಪೈಲ್ ಮಾಡದೆಯೇ ಅಥವಾ ಸಿಸ್ಟಮ್ ಅನ್ನು ರೀಬೂಟ್ ಮಾಡದೆಯೇ ಕರ್ನಲ್ ಈವೆಂಟ್‌ಗಳನ್ನು ಸುರಕ್ಷಿತವಾಗಿ ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಲು ಕೋಡ್ ಅನ್ನು ಇಂಜೆಕ್ಟ್ ಮಾಡಿ. - ಸಿ, ಗೋ ಅಥವಾ ಪೈಥಾನ್‌ನಲ್ಲಿ ಅನುಕೂಲಕರ ಕೋಡ್ ಉದಾಹರಣೆಗಳನ್ನು ಬಳಸಿ. - BPF ಪ್ರೋಗ್ರಾಂ ಜೀವನಚಕ್ರವನ್ನು ಹೊಂದುವ ಮೂಲಕ ನಿಯಂತ್ರಣವನ್ನು ತೆಗೆದುಕೊಳ್ಳಿ.

Linux ಕರ್ನಲ್ ಭದ್ರತೆ, ಅದರ ವೈಶಿಷ್ಟ್ಯಗಳು ಮತ್ತು Seccomp

BPF ಸ್ಥಿರತೆ, ಭದ್ರತೆ ಅಥವಾ ವೇಗವನ್ನು ತ್ಯಾಗ ಮಾಡದೆಯೇ ಕರ್ನಲ್ ಅನ್ನು ವಿಸ್ತರಿಸಲು ಪ್ರಬಲವಾದ ಮಾರ್ಗವನ್ನು ಒದಗಿಸುತ್ತದೆ. ಈ ಕಾರಣಕ್ಕಾಗಿ, ಕರ್ನಲ್ ಡೆವಲಪರ್‌ಗಳು BPF ಪ್ರೋಗ್ರಾಂಗಳಿಂದ ಬೆಂಬಲಿತವಾದ Seccomp ಫಿಲ್ಟರ್‌ಗಳನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸುವ ಮೂಲಕ Seccomp BPF ಎಂದೂ ಕರೆಯಲ್ಪಡುವ Seccomp ನಲ್ಲಿ ಪ್ರಕ್ರಿಯೆಯ ಪ್ರತ್ಯೇಕತೆಯನ್ನು ಸುಧಾರಿಸಲು ಅದರ ಬಹುಮುಖತೆಯನ್ನು ಬಳಸುವುದು ಒಳ್ಳೆಯದು ಎಂದು ಭಾವಿಸಿದ್ದಾರೆ. ಈ ಅಧ್ಯಾಯದಲ್ಲಿ ನಾವು Seccomp ಎಂದರೇನು ಮತ್ತು ಅದನ್ನು ಹೇಗೆ ಬಳಸಲಾಗುತ್ತದೆ ಎಂಬುದನ್ನು ವಿವರಿಸುತ್ತೇವೆ. ನಂತರ ನೀವು BPF ಪ್ರೋಗ್ರಾಂಗಳನ್ನು ಬಳಸಿಕೊಂಡು Seccomp ಫಿಲ್ಟರ್‌ಗಳನ್ನು ಹೇಗೆ ಬರೆಯಬೇಕೆಂದು ಕಲಿಯುವಿರಿ. ಅದರ ನಂತರ, ನಾವು Linux ಭದ್ರತಾ ಮಾಡ್ಯೂಲ್‌ಗಳಿಗಾಗಿ ಕರ್ನಲ್‌ನಲ್ಲಿ ಸೇರಿಸಲಾದ ಅಂತರ್ನಿರ್ಮಿತ BPF ಹುಕ್‌ಗಳನ್ನು ನೋಡುತ್ತೇವೆ.

ಲಿನಕ್ಸ್ ಸೆಕ್ಯುರಿಟಿ ಮಾಡ್ಯೂಲ್‌ಗಳು (ಎಲ್‌ಎಸ್‌ಎಂ) ಒಂದು ಚೌಕಟ್ಟಾಗಿದ್ದು, ಇದು ವಿವಿಧ ಭದ್ರತಾ ಮಾದರಿಗಳನ್ನು ಪ್ರಮಾಣಿತ ರೀತಿಯಲ್ಲಿ ಕಾರ್ಯಗತಗೊಳಿಸಲು ಬಳಸಬಹುದಾದ ಕಾರ್ಯಗಳ ಗುಂಪನ್ನು ಒದಗಿಸುತ್ತದೆ. LSM ಅನ್ನು ನೇರವಾಗಿ Apparmor, SELinux ಮತ್ತು Tomoyo ನಂತಹ ಕರ್ನಲ್ ಮೂಲ ಮರದಲ್ಲಿ ಬಳಸಬಹುದು.

Linux ನ ಸಾಮರ್ಥ್ಯಗಳನ್ನು ಚರ್ಚಿಸುವ ಮೂಲಕ ಪ್ರಾರಂಭಿಸೋಣ.

ವೈಶಿಷ್ಟ್ಯಗಳು

ಲಿನಕ್ಸ್‌ನ ಸಾಮರ್ಥ್ಯಗಳ ಸಾರವೆಂದರೆ ನೀವು ನಿರ್ದಿಷ್ಟ ಕಾರ್ಯವನ್ನು ನಿರ್ವಹಿಸಲು ಅನಪೇಕ್ಷಿತ ಪ್ರಕ್ರಿಯೆಯ ಅನುಮತಿಯನ್ನು ನೀಡಬೇಕಾಗುತ್ತದೆ, ಆದರೆ ಆ ಉದ್ದೇಶಕ್ಕಾಗಿ ಸೂಡ್ ಅನ್ನು ಬಳಸದೆಯೇ ಅಥವಾ ಪ್ರಕ್ರಿಯೆಯನ್ನು ಸವಲತ್ತು ಮಾಡಿ, ದಾಳಿಯ ಸಾಧ್ಯತೆಯನ್ನು ಕಡಿಮೆ ಮಾಡುತ್ತದೆ ಮತ್ತು ಪ್ರಕ್ರಿಯೆಯು ಕೆಲವು ಕಾರ್ಯಗಳನ್ನು ನಿರ್ವಹಿಸಲು ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ. ಉದಾಹರಣೆಗೆ, ನಿಮ್ಮ ಅಪ್ಲಿಕೇಶನ್ ಸವಲತ್ತು ಪಡೆದ ಪೋರ್ಟ್ ಅನ್ನು ತೆರೆಯಬೇಕಾದರೆ, ಪ್ರಕ್ರಿಯೆಯನ್ನು ರೂಟ್ ಆಗಿ ರನ್ ಮಾಡುವ ಬದಲು 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 --caps='cap_net_bind_service+eip cap_setpcap,cap_setuid,cap_setgid+ep' 
   --keep=1 --user="nobody" 
   --addamb=cap_net_bind_service -- -c "./capabilities"

ಈ ತಂಡವನ್ನು ಸ್ವಲ್ಪ ಅರ್ಥಮಾಡಿಕೊಳ್ಳೋಣ.

  • ಕ್ಯಾಪ್ಶ್ - ಕ್ಯಾಪ್ಶ್ ಅನ್ನು ಶೆಲ್ ಆಗಿ ಬಳಸಿ.
  • —caps='cap_net_bind_service+eip cap_setpcap,cap_setuid,cap_setgid+ep' - ನಾವು ಬಳಕೆದಾರರನ್ನು ಬದಲಾಯಿಸಬೇಕಾಗಿರುವುದರಿಂದ (ನಾವು ರೂಟ್ ಆಗಿ ಚಲಾಯಿಸಲು ಬಯಸುವುದಿಲ್ಲ), ನಾವು cap_net_bind_service ಅನ್ನು ನಿರ್ದಿಷ್ಟಪಡಿಸುತ್ತೇವೆ ಮತ್ತು ಬಳಕೆದಾರ ID ಅನ್ನು ವಾಸ್ತವವಾಗಿ ಬದಲಾಯಿಸುವ ಸಾಮರ್ಥ್ಯವನ್ನು ಯಾರಿಗೂ ರೂಟ್ ಇಲ್ಲ, ಅವುಗಳೆಂದರೆ cap_setuid ಮತ್ತು cap_setgid.
  • —keep=1 — ನಾವು ರೂಟ್ ಖಾತೆಯಿಂದ ಬದಲಾಯಿಸುವಾಗ ಸ್ಥಾಪಿಸಲಾದ ಸಾಮರ್ಥ್ಯಗಳನ್ನು ಇರಿಸಿಕೊಳ್ಳಲು ಬಯಸುತ್ತೇವೆ.
  • —ಬಳಕೆದಾರ=“ಯಾರೂ ಇಲ್ಲ” — ಪ್ರೋಗ್ರಾಂ ಅನ್ನು ಚಾಲನೆ ಮಾಡುವ ಅಂತಿಮ ಬಳಕೆದಾರರು ಯಾರೂ ಆಗಿರುವುದಿಲ್ಲ.
  • —addamb=cap_net_bind_service — ರೂಟ್ ಮೋಡ್‌ನಿಂದ ಬದಲಾಯಿಸಿದ ನಂತರ ಸಂಬಂಧಿತ ಸಾಮರ್ಥ್ಯಗಳ ತೆರವುಗೊಳಿಸುವಿಕೆಯನ್ನು ಹೊಂದಿಸಿ.
  • - -c "./ಸಾಮರ್ಥ್ಯಗಳು" - ಕೇವಲ ಪ್ರೋಗ್ರಾಂ ಅನ್ನು ರನ್ ಮಾಡಿ.

ಲಿಂಕ್ ಮಾಡಲಾದ ಸಾಮರ್ಥ್ಯಗಳು ವಿಶೇಷ ರೀತಿಯ ಸಾಮರ್ಥ್ಯಗಳಾಗಿವೆ, ಅದು ಪ್ರಸ್ತುತ ಪ್ರೋಗ್ರಾಂ ಅವುಗಳನ್ನು execve() ಬಳಸಿಕೊಂಡು ಕಾರ್ಯಗತಗೊಳಿಸಿದಾಗ ಮಕ್ಕಳ ಕಾರ್ಯಕ್ರಮಗಳಿಂದ ಆನುವಂಶಿಕವಾಗಿ ಪಡೆಯಲಾಗುತ್ತದೆ. ಸಂಯೋಜಿತವಾಗಿರಲು ಅನುಮತಿಸಲಾದ ಸಾಮರ್ಥ್ಯಗಳು ಅಥವಾ ಬೇರೆ ರೀತಿಯಲ್ಲಿ ಹೇಳುವುದಾದರೆ, ಪರಿಸರ ಸಾಮರ್ಥ್ಯಗಳು ಮಾತ್ರ ಆನುವಂಶಿಕವಾಗಿ ಪಡೆಯಬಹುದು.

--caps ಆಯ್ಕೆಯಲ್ಲಿ ಸಾಮರ್ಥ್ಯವನ್ನು ನಿರ್ದಿಷ್ಟಪಡಿಸಿದ ನಂತರ +eip ಎಂದರೆ ಏನು ಎಂದು ನೀವು ಬಹುಶಃ ಆಶ್ಚರ್ಯ ಪಡುತ್ತೀರಿ. ಸಾಮರ್ಥ್ಯವನ್ನು ನಿರ್ಧರಿಸಲು ಈ ಧ್ವಜಗಳನ್ನು ಬಳಸಲಾಗುತ್ತದೆ:

-ಸಕ್ರಿಯಗೊಳಿಸಬೇಕು (p);

- ಬಳಕೆಗೆ ಲಭ್ಯವಿದೆ (ಇ);

ಮಕ್ಕಳ ಪ್ರಕ್ರಿಯೆಗಳಿಂದ ಆನುವಂಶಿಕವಾಗಿ ಪಡೆಯಬಹುದು (i).

ನಾವು cap_net_bind_service ಅನ್ನು ಬಳಸಲು ಬಯಸುವುದರಿಂದ, ನಾವು ಇದನ್ನು ಇ ಫ್ಲ್ಯಾಗ್‌ನೊಂದಿಗೆ ಮಾಡಬೇಕಾಗಿದೆ. ನಂತರ ನಾವು ಆಜ್ಞೆಯಲ್ಲಿ ಶೆಲ್ ಅನ್ನು ಪ್ರಾರಂಭಿಸುತ್ತೇವೆ. ಇದು ಸಾಮರ್ಥ್ಯಗಳ ಬೈನರಿಯನ್ನು ರನ್ ಮಾಡುತ್ತದೆ ಮತ್ತು ನಾವು ಅದನ್ನು i ಫ್ಲ್ಯಾಗ್‌ನೊಂದಿಗೆ ಗುರುತಿಸಬೇಕಾಗಿದೆ. ಅಂತಿಮವಾಗಿ, ನಾವು ವೈಶಿಷ್ಟ್ಯವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು ಬಯಸುತ್ತೇವೆ (ನಾವು UID ಅನ್ನು ಬದಲಾಯಿಸದೆಯೇ ಇದನ್ನು ಮಾಡಿದ್ದೇವೆ) p. ಇದು 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

ಈ ಉದಾಹರಣೆಯಲ್ಲಿ ನಾವು ಕ್ಯಾಪ್ಶ್ ಅನ್ನು ಬಳಸಿದ್ದೇವೆ, ಆದರೆ ನೀವು ಲಿಬ್‌ಕ್ಯಾಪ್ ಬಳಸಿ ಶೆಲ್ ಅನ್ನು ಬರೆಯಬಹುದು. ಹೆಚ್ಚಿನ ಮಾಹಿತಿಗಾಗಿ, ಮ್ಯಾನ್ 3 ಲಿಬ್‌ಕ್ಯಾಪ್ ಅನ್ನು ನೋಡಿ.

ಕಾರ್ಯಕ್ರಮಗಳನ್ನು ಬರೆಯುವಾಗ, ಸಾಕಷ್ಟು ಬಾರಿ ಡೆವಲಪರ್ ರನ್ ಸಮಯದಲ್ಲಿ ಪ್ರೋಗ್ರಾಂಗೆ ಅಗತ್ಯವಿರುವ ಎಲ್ಲಾ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಮುಂಚಿತವಾಗಿ ತಿಳಿದಿರುವುದಿಲ್ಲ; ಇದಲ್ಲದೆ, ಈ ವೈಶಿಷ್ಟ್ಯಗಳು ಹೊಸ ಆವೃತ್ತಿಗಳಲ್ಲಿ ಬದಲಾಗಬಹುದು.

ನಮ್ಮ ಪ್ರೋಗ್ರಾಂನ ಸಾಮರ್ಥ್ಯಗಳನ್ನು ಚೆನ್ನಾಗಿ ಅರ್ಥಮಾಡಿಕೊಳ್ಳಲು, ನಾವು BCC ಸಾಮರ್ಥ್ಯದ ಉಪಕರಣವನ್ನು ತೆಗೆದುಕೊಳ್ಳಬಹುದು, ಇದು cap_capable ಕರ್ನಲ್ ಕಾರ್ಯಕ್ಕಾಗಿ kprobe ಅನ್ನು ಹೊಂದಿಸುತ್ತದೆ:

/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 ಆಗಿದೆ, ಇದನ್ನು ಫೈಲ್‌ನಲ್ಲಿನ ಕರ್ನಲ್ ಮೂಲ ಕೋಡ್‌ನಲ್ಲಿ ಸ್ಥಿರ ಎಂದು ವ್ಯಾಖ್ಯಾನಿಸಲಾಗಿದೆ/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">

ರನ್‌ಸಿ ಅಥವಾ ಡಾಕರ್‌ನಂತಹ ಕಂಟೇನರ್‌ಗಳಿಗೆ ಅವಕಾಶವಿಲ್ಲದ ಮೋಡ್‌ನಲ್ಲಿ ರನ್ ಮಾಡಲು ಅವಕಾಶ ಮಾಡಿಕೊಡಲು ರನ್‌ಟೈಮ್‌ನಲ್ಲಿ ಸಾಮರ್ಥ್ಯಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾಗುತ್ತದೆ, ಆದರೆ ಹೆಚ್ಚಿನ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಚಲಾಯಿಸಲು ಅಗತ್ಯವಿರುವ ಸಾಮರ್ಥ್ಯಗಳನ್ನು ಮಾತ್ರ ಅನುಮತಿಸಲಾಗುತ್ತದೆ. ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ನಿರ್ದಿಷ್ಟ ಸಾಮರ್ಥ್ಯಗಳ ಅಗತ್ಯವಿದ್ದಾಗ, ಡಾಕರ್ ಅವುಗಳನ್ನು --cap-add ಬಳಸಿಕೊಂಡು ಒದಗಿಸಬಹುದು:

docker run -it --rm --cap-add=NET_ADMIN ubuntu ip link add dummy0 type dummy

ಈ ಆಜ್ಞೆಯು ಕಂಟೇನರ್‌ಗೆ CAP_NET_ADMIN ಸಾಮರ್ಥ್ಯವನ್ನು ನೀಡುತ್ತದೆ, ಇದು dummy0 ಇಂಟರ್ಫೇಸ್ ಅನ್ನು ಸೇರಿಸಲು ನೆಟ್‌ವರ್ಕ್ ಲಿಂಕ್ ಅನ್ನು ಕಾನ್ಫಿಗರ್ ಮಾಡಲು ಅನುಮತಿಸುತ್ತದೆ.

ಮುಂದಿನ ವಿಭಾಗವು ಫಿಲ್ಟರಿಂಗ್‌ನಂತಹ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಹೇಗೆ ಬಳಸುವುದು ಎಂಬುದನ್ನು ತೋರಿಸುತ್ತದೆ, ಆದರೆ ನಮ್ಮ ಸ್ವಂತ ಫಿಲ್ಟರ್‌ಗಳನ್ನು ಪ್ರೋಗ್ರಾಮಿಕ್ ಆಗಿ ಕಾರ್ಯಗತಗೊಳಿಸಲು ನಮಗೆ ಅನುಮತಿಸುವ ವಿಭಿನ್ನ ತಂತ್ರವನ್ನು ಬಳಸುವುದು.

ಸೆಕಾಂಪ್

Seccomp ಎಂದರೆ ಸೆಕ್ಯೂರ್ ಕಂಪ್ಯೂಟಿಂಗ್ ಮತ್ತು ಇದು ಲಿನಕ್ಸ್ ಕರ್ನಲ್‌ನಲ್ಲಿ ಅಳವಡಿಸಲಾಗಿರುವ ಭದ್ರತಾ ಪದರವಾಗಿದ್ದು, ಡೆವಲಪರ್‌ಗಳಿಗೆ ನಿರ್ದಿಷ್ಟ ಸಿಸ್ಟಮ್ ಕರೆಗಳನ್ನು ಫಿಲ್ಟರ್ ಮಾಡಲು ಅನುಮತಿಸುತ್ತದೆ. Seccomp ಸಾಮರ್ಥ್ಯಗಳಲ್ಲಿ Linux ಗೆ ಹೋಲಿಸಬಹುದಾದರೂ, ಕೆಲವು ಸಿಸ್ಟಮ್ ಕರೆಗಳನ್ನು ನಿರ್ವಹಿಸುವ ಅದರ ಸಾಮರ್ಥ್ಯವು ಅವುಗಳಿಗೆ ಹೋಲಿಸಿದರೆ ಅದನ್ನು ಹೆಚ್ಚು ಹೊಂದಿಕೊಳ್ಳುವಂತೆ ಮಾಡುತ್ತದೆ.

Seccomp ಮತ್ತು Linux ವೈಶಿಷ್ಟ್ಯಗಳು ಪರಸ್ಪರ ಪ್ರತ್ಯೇಕವಾಗಿರುವುದಿಲ್ಲ ಮತ್ತು ಎರಡೂ ವಿಧಾನಗಳಿಂದ ಪ್ರಯೋಜನ ಪಡೆಯಲು ಒಟ್ಟಿಗೆ ಬಳಸಲಾಗುತ್ತದೆ. ಉದಾಹರಣೆಗೆ, ನೀವು ಪ್ರಕ್ರಿಯೆಗೆ CAP_NET_ADMIN ಸಾಮರ್ಥ್ಯವನ್ನು ನೀಡಲು ಬಯಸಬಹುದು ಆದರೆ ಸಾಕೆಟ್ ಸಂಪರ್ಕಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ಅನುಮತಿಸುವುದಿಲ್ಲ, ಸ್ವೀಕರಿಸಲು ಮತ್ತು ಸ್ವೀಕರಿಸಲು4 ಸಿಸ್ಟಮ್ ಕರೆಗಳನ್ನು ನಿರ್ಬಂಧಿಸುತ್ತದೆ.

Seccomp ಫಿಲ್ಟರಿಂಗ್ ವಿಧಾನವು SECCOMP_MODE_FILTER ಮೋಡ್‌ನಲ್ಲಿ ಕಾರ್ಯನಿರ್ವಹಿಸುವ BPF ಫಿಲ್ಟರ್‌ಗಳನ್ನು ಆಧರಿಸಿದೆ ಮತ್ತು ಪ್ಯಾಕೆಟ್‌ಗಳಂತೆಯೇ ಸಿಸ್ಟಮ್ ಕರೆ ಫಿಲ್ಟರಿಂಗ್ ಅನ್ನು ನಿರ್ವಹಿಸಲಾಗುತ್ತದೆ.

PR_SET_SECCOMP ಕಾರ್ಯಾಚರಣೆಯ ಮೂಲಕ prctl ಅನ್ನು ಬಳಸಿಕೊಂಡು Seccomp ಫಿಲ್ಟರ್‌ಗಳನ್ನು ಲೋಡ್ ಮಾಡಲಾಗುತ್ತದೆ. ಈ ಫಿಲ್ಟರ್‌ಗಳು BPF ಪ್ರೋಗ್ರಾಮ್‌ನ ರೂಪವನ್ನು ತೆಗೆದುಕೊಳ್ಳುತ್ತವೆ, ಇದನ್ನು seccomp_data ರಚನೆಯಿಂದ ಪ್ರತಿನಿಧಿಸುವ ಪ್ರತಿ Seccomp ಪ್ಯಾಕೆಟ್‌ಗೆ ಕಾರ್ಯಗತಗೊಳಿಸಲಾಗುತ್ತದೆ. ಈ ರಚನೆಯು ಉಲ್ಲೇಖ ಆರ್ಕಿಟೆಕ್ಚರ್ ಅನ್ನು ಒಳಗೊಂಡಿದೆ, ಸಿಸ್ಟಮ್ ಕರೆ ಸಮಯದಲ್ಲಿ ಪ್ರೊಸೆಸರ್ ಸೂಚನೆಗಳಿಗೆ ಪಾಯಿಂಟರ್ ಮತ್ತು ಗರಿಷ್ಠ ಆರು ಸಿಸ್ಟಮ್ ಕರೆ ಆರ್ಗ್ಯುಮೆಂಟ್‌ಗಳನ್ನು 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 (ಕೆಟ್ಟ ಸಿಸ್ಟಂ ಕರೆ) ಸಂಕೇತವನ್ನು ಕರೆ ಮಾಡುವ ಕಾರ್ಯಕ್ಕೆ ಕಳುಹಿಸಲಾಗುತ್ತದೆ.

- SECCOMP_RET_ERRNO - ಸಿಸ್ಟಂ ಕರೆಯನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸಲಾಗಿಲ್ಲ ಮತ್ತು SECCOMP_RET_DATA ಫಿಲ್ಟರ್ ರಿಟರ್ನ್ ಮೌಲ್ಯದ ಭಾಗವನ್ನು ಬಳಕೆದಾರರ ಜಾಗಕ್ಕೆ ದೋಷ ಮೌಲ್ಯವಾಗಿ ರವಾನಿಸಲಾಗುತ್ತದೆ. ದೋಷದ ಕಾರಣವನ್ನು ಅವಲಂಬಿಸಿ, ವಿಭಿನ್ನ ದೋಷ ಮೌಲ್ಯಗಳನ್ನು ಹಿಂತಿರುಗಿಸಲಾಗುತ್ತದೆ. ದೋಷ ಸಂಖ್ಯೆಗಳ ಪಟ್ಟಿಯನ್ನು ಮುಂದಿನ ವಿಭಾಗದಲ್ಲಿ ನೀಡಲಾಗಿದೆ.

- SECCOMP_RET_TRACE - PTRACE_O_TRACESECCOMP ಅನ್ನು ಬಳಸಿಕೊಂಡು ptrace ಟ್ರೇಸರ್ ಅನ್ನು ಸೂಚಿಸಲು ಬಳಸಲಾಗುತ್ತದೆ - ಆ ಪ್ರಕ್ರಿಯೆಯನ್ನು ನೋಡಲು ಮತ್ತು ನಿಯಂತ್ರಿಸಲು ಸಿಸ್ಟಮ್ ಕರೆಯನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸಿದಾಗ ಪ್ರತಿಬಂಧಿಸಲು. ಟ್ರೇಸರ್ ಅನ್ನು ಸಂಪರ್ಕಿಸದಿದ್ದರೆ, ದೋಷವನ್ನು ಹಿಂತಿರುಗಿಸಲಾಗುತ್ತದೆ, ದೋಷವನ್ನು -ENOSYS ಗೆ ಹೊಂದಿಸಲಾಗಿದೆ ಮತ್ತು ಸಿಸ್ಟಮ್ ಕರೆಯನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸಲಾಗುವುದಿಲ್ಲ.

- SECCOMP_RET_LOG - ಸಿಸ್ಟಮ್ ಕರೆಯನ್ನು ಪರಿಹರಿಸಲಾಗಿದೆ ಮತ್ತು ಲಾಗ್ ಮಾಡಲಾಗಿದೆ.

- SECCOMP_RET_ALLOW - ಸಿಸ್ಟಂ ಕರೆಯನ್ನು ಸರಳವಾಗಿ ಅನುಮತಿಸಲಾಗಿದೆ.

ptrace ಎನ್ನುವುದು ಪ್ರಕ್ರಿಯೆಯ ಕಾರ್ಯಗತಗೊಳಿಸುವಿಕೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡುವ ಮತ್ತು ನಿಯಂತ್ರಿಸುವ ಸಾಮರ್ಥ್ಯದೊಂದಿಗೆ ಟ್ರೇಸೀ ಎಂಬ ಪ್ರಕ್ರಿಯೆಯಲ್ಲಿ ಟ್ರೇಸಿಂಗ್ ಕಾರ್ಯವಿಧಾನಗಳನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸಲು ಸಿಸ್ಟಮ್ ಕರೆಯಾಗಿದೆ. ಟ್ರೇಸ್ ಪ್ರೋಗ್ರಾಂ ಕಾರ್ಯಗತಗೊಳಿಸುವಿಕೆಯ ಮೇಲೆ ಪರಿಣಾಮಕಾರಿಯಾಗಿ ಪ್ರಭಾವ ಬೀರುತ್ತದೆ ಮತ್ತು ಟ್ರೇಸಿಯ ಮೆಮೊರಿ ರೆಜಿಸ್ಟರ್‌ಗಳನ್ನು ಮಾರ್ಪಡಿಸುತ್ತದೆ. Seccomp ಸನ್ನಿವೇಶದಲ್ಲಿ, SECCOMP_RET_TRACE ಸ್ಥಿತಿ ಕೋಡ್‌ನಿಂದ ಪ್ರಚೋದಿಸಿದಾಗ ptrace ಅನ್ನು ಬಳಸಲಾಗುತ್ತದೆ, ಆದ್ದರಿಂದ ಟ್ರೇಸರ್ ಸಿಸ್ಟಮ್ ಕರೆಯನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸುವುದನ್ನು ತಡೆಯಬಹುದು ಮತ್ತು ತನ್ನದೇ ಆದ ತರ್ಕವನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸಬಹುದು.

ಸೆಕಾಂಪ್ ದೋಷಗಳು

ಕಾಲಕಾಲಕ್ಕೆ, Seccomp ನೊಂದಿಗೆ ಕೆಲಸ ಮಾಡುವಾಗ, ನೀವು SECCOMP_RET_ERRNO ಪ್ರಕಾರದ ರಿಟರ್ನ್ ಮೌಲ್ಯದಿಂದ ಗುರುತಿಸಲಾದ ವಿವಿಧ ದೋಷಗಳನ್ನು ಎದುರಿಸುತ್ತೀರಿ. ದೋಷವನ್ನು ವರದಿ ಮಾಡಲು, seccomp ಸಿಸ್ಟಮ್ ಕರೆ 1 ಬದಲಿಗೆ -0 ಅನ್ನು ಹಿಂತಿರುಗಿಸುತ್ತದೆ.

ಕೆಳಗಿನ ದೋಷಗಳು ಸಾಧ್ಯ:

- ಪ್ರವೇಶ - ಕಾಲರ್ ಸಿಸ್ಟಂ ಕರೆ ಮಾಡಲು ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ. ಇದು ಸಾಮಾನ್ಯವಾಗಿ ಸಂಭವಿಸುತ್ತದೆ ಏಕೆಂದರೆ ಇದು 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), ಸವಲತ್ತುಗಳು, ಪರ್ಫ್ ಈವೆಂಟ್‌ಗಳು ಇತ್ಯಾದಿಗಳಂತಹ ಪ್ರಕ್ರಿಯೆಯ ನಿರ್ದಿಷ್ಟ ಅಂಶಗಳನ್ನು ಕುಶಲತೆಯಿಂದ (ಸೆಟ್ ಮಾಡಲು ಮತ್ತು ಪಡೆಯಲು) ಬಳಕೆದಾರ-ಸ್ಪೇಸ್ ಪ್ರೋಗ್ರಾಂ ಅನ್ನು ಅನುಮತಿಸುತ್ತದೆ.

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 (ಆಫ್ಸೆಟ್‌ಆಫ್(ಸ್ಟ್ರಕ್ಟ್ ಸೆಕಾಂಪ್_ಡೇಟಾ, ಆರ್ಚ್))) - BPF_LD ಪದದ ರೂಪದಲ್ಲಿ BPF_LD ನಿಂದ ಸಿಸ್ಟಮ್ ಲೋಡ್ ಆಗುತ್ತದೆ ಮತ್ತು ಸಂಗ್ರಹಗೊಳ್ಳುತ್ತದೆ, ಪ್ಯಾಕೆಟ್ ಡೇಟಾ BPF_ABS ಸ್ಥಿರ ಆಫ್‌ಸೆಟ್‌ನಲ್ಲಿದೆ.

- BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ಕಮಾನು, 0, 3) - BPF_JEQ ಅನ್ನು ಬಳಸಿಕೊಂಡು ಸಂಚಯಕ ಸ್ಥಿರ BPF_K ನಲ್ಲಿನ ಆರ್ಕಿಟೆಕ್ಚರ್ ಮೌಲ್ಯವು ಕಮಾನಿಗೆ ಸಮಾನವಾಗಿದೆಯೇ ಎಂದು ಪರಿಶೀಲಿಸುತ್ತದೆ. ಹಾಗಿದ್ದಲ್ಲಿ, ಕಮಾನು ಹೊಂದಿಕೆಯಾಗದ ಕಾರಣ ದೋಷವನ್ನು ಎಸೆಯಲು ಆಫ್‌ಸೆಟ್ 0 ಅನ್ನು ಮುಂದಿನ ಸೂಚನೆಗೆ, ಇಲ್ಲದಿದ್ದರೆ ಆಫ್‌ಸೆಟ್ 3 (ಈ ಸಂದರ್ಭದಲ್ಲಿ) ಜಂಪ್ ಮಾಡುತ್ತದೆ.

- BPF_STMT(BPF_LD + BPF_W + BPF_ABS (ಆಫ್ಸೆಟ್‌ಆಫ್(ಸ್ಟ್ರಕ್ಟ್ ಸೆಕಾಂಪ್_ಡೇಟಾ, ಎನ್ಆರ್))) - BPF_LD ನಿಂದ BPF_W ಪದದ ರೂಪದಲ್ಲಿ ಲೋಡ್ ಆಗುತ್ತದೆ ಮತ್ತು ಸಂಗ್ರಹಗೊಳ್ಳುತ್ತದೆ, ಇದು BPF_ABS ನ ಸ್ಥಿರ ಆಫ್‌ಸೆಟ್‌ನಲ್ಲಿರುವ ಸಿಸ್ಟಮ್ ಕರೆ ಸಂಖ್ಯೆಯಾಗಿದೆ.

— 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;

ಸಾಕೆಟ್_ಫಿಲ್ಟರ್ ರಚನೆಯಲ್ಲಿ ಫಿಲ್ಟರ್ ಕೋಡ್ ಅನ್ನು ವ್ಯಾಖ್ಯಾನಿಸಿದ ನಂತರ, ನೀವು ಕೋಡ್ ಮತ್ತು ಫಿಲ್ಟರ್‌ನ ಲೆಕ್ಕಾಚಾರದ ಉದ್ದವನ್ನು ಹೊಂದಿರುವ sock_fprog ಅನ್ನು ವ್ಯಾಖ್ಯಾನಿಸಬೇಕಾಗಿದೆ. ಈ ಡೇಟಾ ರಚನೆಯು ಪ್ರಕ್ರಿಯೆಯನ್ನು ನಂತರ ಚಲಾಯಿಸಲು ಘೋಷಿಸಲು ವಾದವಾಗಿ ಅಗತ್ಯವಿದೆ:

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

ಇನ್ಸ್ಟಾಲ್_ಫಿಲ್ಟರ್ ಕಾರ್ಯದಲ್ಲಿ ಮಾಡಲು ಕೇವಲ ಒಂದು ವಿಷಯ ಮಾತ್ರ ಉಳಿದಿದೆ - ಪ್ರೋಗ್ರಾಂ ಅನ್ನು ಸ್ವತಃ ಲೋಡ್ ಮಾಡಿ! ಇದನ್ನು ಮಾಡಲು, ನಾವು prctl ಅನ್ನು ಬಳಸುತ್ತೇವೆ, ಸುರಕ್ಷಿತ ಕಂಪ್ಯೂಟಿಂಗ್ ಮೋಡ್ ಅನ್ನು ಪ್ರವೇಶಿಸಲು PR_SET_SECCOMP ಅನ್ನು ಆಯ್ಕೆಯಾಗಿ ತೆಗೆದುಕೊಳ್ಳುತ್ತೇವೆ. ನಂತರ ನಾವು SECCOMP_MODE_FILTER ಅನ್ನು ಬಳಸಿಕೊಂಡು ಫಿಲ್ಟರ್ ಅನ್ನು ಲೋಡ್ ಮಾಡಲು ಮೋಡ್‌ಗೆ ಹೇಳುತ್ತೇವೆ, ಇದು sock_fprog ಪ್ರಕಾರದ ಪ್ರೊಗ್ ವೇರಿಯೇಬಲ್‌ನಲ್ಲಿದೆ:

  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 ಅನ್ನು ಬಳಸಬೇಕಾಗುತ್ತದೆ ಮತ್ತು ಆ ಮೂಲಕ ಮಕ್ಕಳ ಪ್ರಕ್ರಿಯೆಗಳು ಅವರ ಪೋಷಕರಿಗಿಂತ ಹೆಚ್ಚಿನ ಸವಲತ್ತುಗಳನ್ನು ಪಡೆಯುವ ಪರಿಸ್ಥಿತಿಯನ್ನು ತಪ್ಪಿಸಬೇಕು. ಇದರೊಂದಿಗೆ, ನಾವು ಮೂಲ ಹಕ್ಕುಗಳಿಲ್ಲದೆಯೇ 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]);
 }

ನಾವೀಗ ಆರಂಭಿಸೋಣ. ನಮ್ಮ ಪ್ರೋಗ್ರಾಂ ಅನ್ನು ಕಂಪೈಲ್ ಮಾಡಲು ನಾವು ಕ್ಲಾಂಗ್ ಅಥವಾ ಜಿಸಿಸಿ ಅನ್ನು ಬಳಸಬಹುದು, ಯಾವುದೇ ರೀತಿಯಲ್ಲಿ ಅದು ವಿಶೇಷ ಆಯ್ಕೆಗಳಿಲ್ಲದೆ 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 -f ./filter-write "ls -la"

ಕೆಲಸದ ಫಲಿತಾಂಶವು ಬಹಳ ಕಡಿಮೆಯಾಗಿದೆ, ಆದರೆ ಅದರ ಅನುಗುಣವಾದ ಭಾಗವು 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 ಆಗಿದೆ.

ಬಲೆಗಳ ಮೂಲ ಕೋಡ್ ಫೈಲ್‌ನಲ್ಲಿ ಕರ್ನಲ್ ಟ್ರೀನಲ್ಲಿದೆ, 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 ಆಗಿದೆ. ಅವರು ಡಾಕರ್ ಬೆಂಬಲದಲ್ಲಿ ಕೆಲಸ ಮಾಡಿದರು ಮತ್ತು ರನ್ಕ್, ಗೋ ಮತ್ತು ಬಿಸಿಸಿ ಪರಿಕರಗಳ ಅಭಿವೃದ್ಧಿಗೆ ಕೊಡುಗೆ ನೀಡಿದರು, ಹಾಗೆಯೇ ಇತರ ತೆರೆದ ಮೂಲ ಯೋಜನೆಗಳು. ಡಾಕರ್ ಯೋಜನೆಗಳು ಮತ್ತು ಡಾಕರ್ ಪ್ಲಗಿನ್ ಪರಿಸರ ವ್ಯವಸ್ಥೆಯ ಅಭಿವೃದ್ಧಿಯಲ್ಲಿ ಅವರ ಕೆಲಸಕ್ಕಾಗಿ ಹೆಸರುವಾಸಿಯಾಗಿದ್ದಾರೆ. ಡೇವಿಡ್ ಜ್ವಾಲೆಯ ಗ್ರಾಫ್‌ಗಳ ಬಗ್ಗೆ ತುಂಬಾ ಉತ್ಸುಕರಾಗಿದ್ದಾರೆ ಮತ್ತು ಯಾವಾಗಲೂ ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಅತ್ಯುತ್ತಮವಾಗಿಸಲು ನೋಡುತ್ತಿದ್ದಾರೆ.

ಲೊರೆಂಜೊ ಫಾಂಟಾನಾ Sysdig ನಲ್ಲಿ ಓಪನ್ ಸೋರ್ಸ್ ತಂಡದಲ್ಲಿ ಕೆಲಸ ಮಾಡುತ್ತಾರೆ, ಅಲ್ಲಿ ಅವರು ಪ್ರಾಥಮಿಕವಾಗಿ Falco ಮೇಲೆ ಕೇಂದ್ರೀಕರಿಸಿದ್ದಾರೆ, ಇದು ಕ್ಲೌಡ್ ನೇಟಿವ್ ಕಂಪ್ಯೂಟಿಂಗ್ ಫೌಂಡೇಶನ್ ಯೋಜನೆಯಾಗಿದ್ದು ಅದು ಕಂಟೇನರ್ ರನ್ಟೈಮ್ ಭದ್ರತೆ ಮತ್ತು ಕರ್ನಲ್ ಮಾಡ್ಯೂಲ್ ಮತ್ತು eBPF ಮೂಲಕ ಅಸಂಗತತೆಯನ್ನು ಪತ್ತೆಹಚ್ಚುತ್ತದೆ. ಅವರು ವಿತರಿಸಿದ ವ್ಯವಸ್ಥೆಗಳು, ಸಾಫ್ಟ್‌ವೇರ್ ಡಿಫೈನ್ಡ್ ನೆಟ್‌ವರ್ಕಿಂಗ್, ಲಿನಕ್ಸ್ ಕರ್ನಲ್ ಮತ್ತು ಕಾರ್ಯಕ್ಷಮತೆಯ ವಿಶ್ಲೇಷಣೆಯ ಬಗ್ಗೆ ಉತ್ಸುಕರಾಗಿದ್ದಾರೆ.

» ಪುಸ್ತಕದ ಕುರಿತು ಹೆಚ್ಚಿನ ವಿವರಗಳನ್ನು ಇಲ್ಲಿ ಕಾಣಬಹುದು ಪ್ರಕಾಶಕರ ವೆಬ್‌ಸೈಟ್
» ಪರಿವಿಡಿ
» ಆಯ್ದ ಭಾಗ

ಖಬ್ರೋಝೈಟೆಲಿಗಾಗಿ ಕೂಪನ್ ಬಳಸಿ 25% ರಿಯಾಯಿತಿ - ಲಿನಕ್ಸ್

ಪುಸ್ತಕದ ಕಾಗದದ ಆವೃತ್ತಿಯನ್ನು ಪಾವತಿಸಿದ ನಂತರ, ಇ-ಮೇಲ್ ಮೂಲಕ ಎಲೆಕ್ಟ್ರಾನಿಕ್ ಪುಸ್ತಕವನ್ನು ಕಳುಹಿಸಲಾಗುತ್ತದೆ.

ಮೂಲ: www.habr.com

ಕಾಮೆಂಟ್ ಅನ್ನು ಸೇರಿಸಿ