Seccomp user notifications sunt una dintre acele funcții Linux care par făcute pentru cazuri foarte specifice, dar care devin importante imediat ce construiești containere, sandboxuri sau runtime-uri care trebuie să controleze apeluri de sistem sensibile. Ideea este simplă: în loc ca filtrul seccomp să spună doar „permite” sau „respinge”, el poate trimite o notificare către un proces userspace, numit de obicei broker sau supervisor. Acel proces decide cum tratează cererea.
Mecanismul este util, dar periculos dacă este înțeles greșit. Documentația Linux și pagina seccomp_unotify(2) insistă asupra unui punct esențial: user notifications nu sunt o politică completă de securitate. Sunt o unealtă pentru supraveghere și mediere, folosită împreună cu alte controale ale kernelului.
Arhitectura pornește de la procesul țintă. Acesta instalează un filtru seccomp cu SECCOMP_FILTER_FLAG_NEW_LISTENER, iar filtrul întoarce SECCOMP_RET_USER_NOTIF pentru syscall-urile care trebuie analizate. La instalare, kernelul returnează un file descriptor de ascultare. Când procesul țintă ajunge la un syscall marcat astfel, execuția lui este blocată temporar, iar brokerul primește o notificare prin SECCOMP_IOCTL_NOTIF_RECV.
Brokerul nu ar trebui să fie doar o bucată de cod care spune „da” sau „nu”. El trebuie tratat ca o componentă privilegiată, mică, auditată și izolată. În practică, brokerul citește notificarea, verifică identitatea și contextul procesului, evaluează syscall-ul cerut și răspunde prin SECCOMP_IOCTL_NOTIF_SEND. Pentru unele operațiuni, poate face el însuși acțiunea sigură și poate întoarce rezultatul către procesul țintă.
Un caz important este lucrul cu file descriptorii. Kernel documentation menționează SECCOMP_IOCTL_NOTIF_ADDFD, prin care brokerul poate introduce un file descriptor în procesul notificator. Varianta cu SECCOMP_ADDFD_FLAG_SEND permite adăugarea FD-ului și trimiterea răspunsului într-un pas atomic. Pentru design defensiv, această abordare este adesea mai sigură decât a lăsa procesul țintă să continue singur către resursa sensibilă.
Capcana majoră este TOCTOU: time-of-check, time-of-use. Dacă brokerul verifică argumentele unui syscall, iar apoi spune kernelului să continue apelul original, există o fereastră în care procesul țintă poate schimba ceea ce a fost verificat. Pagina seccomp_unotify(2) avertizează explicit că SECCOMP_USER_NOTIF_FLAG_CONTINUE trebuie folosit cu prudență. Nu este suficient să spui „am verificat calea” sau „am verificat pointerul”, pentru că argumentele indirecte pot fi modificate între verificare și folosire.
De aici vine regula practică: brokerul ar trebui să evite, pe cât posibil, continuarea syscall-ului original după ce a citit date din memoria procesului țintă. Mai sigur este ca brokerul să refuze cererea sau să execute el o variantă controlată a operațiunii, apoi să returneze rezultatul. Dacă se accesează informații prin /proc sau prin memoria procesului țintă, trebuie folosită validarea ID-ului notificării cu SECCOMP_IOCTL_NOTIF_ID_VALID, pentru a reduce riscul ca procesul să fi ieșit din syscall, să fi murit sau ca PID-ul să fi fost refolosit.
Un broker sănătos are câteva reguli de bază. Rulează cu privilegii minime, chiar dacă are mai multe drepturi decât ținta. Ține o listă foarte scurtă de syscall-uri mediate. Nu ia decizii pe baza unor șiruri citite o singură dată și apoi reutilizate orbește. Înregistrează deciziile relevante, dar fără a salva date sensibile inutil. Tratează semnalele, timeouturile și erorile ca scenarii normale, nu ca excepții rare.
La fel de important: seccomp trebuie combinat cu namespaces, capabilities reduse, AppArmor sau SELinux acolo unde există, politici clare de mount și acces la fișiere, plus actualizări regulate ale kernelului. Seccomp reduce suprafața de atac a kernelului, însă documentația oficială spune clar că nu este un sandbox complet.
Pentru echipele care construiesc runtime-uri, brokerul userspace este valoros tocmai pentru că aduce context acolo unde BPF-ul seccomp este limitat. Dar aceeași flexibilitate introduce curse, complexitate și riscuri de proiectare. Folosit corect, mecanismul poate media elegant syscall-uri sensibile. Folosit ca scurtătură pentru „securitate totală”, devine o zonă fragilă exact în locul în care ai nevoie de cea mai mare rigoare.

















































