io_uring a fost creat pentru performanță: mai puține syscall-uri repetitive, cozi partajate între user space și kernel și execuție asincronă pentru operații de I/O. Tocmai de aceea, într-un sandbox Linux, întrebarea grea nu este doar „permit sau blochez io_uring?”, ci „ce are voie să facă acest ring după ce l-am creat?”. Răspunsul practic nu stă într-un singur mecanism. seccomp rămâne util, dar pentru operațiile din interiorul ringului trebuie folosite restricțiile native io_uring și controale complementare.
De ce seccomp nu este suficient pentru io_uring
seccomp filtrează apeluri de sistem. Poate limita sau bloca io_uring_setup, io_uring_register și io_uring_enter, în funcție de politica procesului. Problema este că io_uring comprimă multe intenții de I/O în submission queue entries, iar aplicația poate pregăti operații care nu arată ca o succesiune clasică de syscall-uri separate.
Asta nu înseamnă că seccomp devine inutil. Înseamnă că el trebuie să fie primul strat, nu singurul. Dacă lucrezi la izolarea unui serviciu, articolul despre sandbox Linux cu namespaces, seccomp, chroot și filesystem read-only rămâne baza. Pentru io_uring, însă, politica trebuie coborâtă și la nivelul ringului.
Ce sunt, de fapt, „io_uring filters”
În documentația liburing și man-pages, mecanismul stabil este numit restrictions, nu „filters”. Ideea este simplă: creezi ringul în stare dezactivată, înregistrezi o listă de restricții, apoi activezi ringul. După activare, kernelul validează operațiile în raport cu acea politică.
Operația relevantă este IORING_REGISTER_RESTRICTIONS. Potrivit paginii io_uring_register(2), restricțiile funcționează ca allowlist: ce nu este înregistrat nu este permis. O intrare poate permite un opcode io_uring_register, poate specifica ce opcode-uri SQE sunt acceptate și ce flags sunt permise sau cerute pe submission queue entries.
Detaliul critic este ordinea. Ringul trebuie creat cu IORING_SETUP_R_DISABLED. În această stare, man page-ul io_uring_setup(2) spune că restricțiile pot fi înregistrate, dar submissions nu sunt permise. Apoi ringul se activează cu IORING_REGISTER_ENABLE_RINGS sau, prin liburing, cu io_uring_enable_rings(3). Dacă sari peste această etapă și lași ringul să accepte lucrări înainte de politică, ai pierdut punctul principal al mecanismului.
Model de politică defensivă
Pentru un serviciu care are nevoie doar de citire/scriere asincronă pe fișiere sau socketuri deja controlate, politica bună pornește invers: nu întrebi ce vrei să blochezi, ci ce trebuie să permiți minim. În io_uring restrictions, asta se potrivește natural cu allowlist-ul.
Un profil defensiv poate separa trei niveluri. Primul: seccomp permite doar syscall-urile necesare pentru inițializarea și folosirea ringului, plus restul minim al procesului. Al doilea: io_uring restrictions limitează operațiile din ring la SQE opcodes și flags strict necesare aplicației. Al treilea: sistemul de operare limitează resursele și accesul lateral prin cgroups, capabilities, namespaces, LSM și permisiuni de filesystem.
Pentru servicii care rulează fără root, merită corelată această politică cu eliminarea privilegiilor root folosind capabilities, seccomp și user namespaces. Iar dacă riscul principal este consumul necontrolat de resurse, cgroups v2 pentru limitarea CPU, memoriei și I/O completează partea pe care io_uring restrictions nu o rezolvă.
Ce nu rezolvă restricțiile io_uring
Restricțiile nu sunt un firewall de aplicație și nu înlocuiesc controlul accesului. Dacă un proces are deja descriptorii de fișier potriviți, politica ringului trebuie gândită împreună cu modul în care acei descriptori au fost obținuți. La fel, restricțiile nu transformă automat o aplicație nesigură într-una sigură; reduc suprafața disponibilă pentru operații asincrone neintenționate.
Mai există o limită practică: nu toate aplicațiile expun ușor configurația io_uring. Pentru software propriu, ai control direct asupra inițializării ringului. Pentru aplicații terțe, uneori soluția realistă este să dezactivezi io_uring dacă programul permite, să îl izolezi mai strict sau să îl rulezi într-un profil seccomp/LSM mai conservator.
Cum verifici designul fără să inventezi securitate
Un audit bun începe cu întrebări verificabile: unde se creează ringul, este folosit IORING_SETUP_R_DISABLED, sunt înregistrate toate restricțiile într-un singur pas înainte de activare, ce SQE opcodes sunt permise și ce se întâmplă când apare o operație nepermisă. io_uring_register(2) documentează eroarea EACCES pentru opcode nepermis de restricțiile înregistrate.
Pentru sisteme sensibile, seccomp poate fi dus mai departe cu un broker userspace, dar acesta trebuie proiectat atent; altfel apar curse de tip TOCTOU. Contextul este explicat separat în materialul despre Seccomp User Notifications în Linux. În practică, cea mai robustă abordare este stratificată: seccomp pentru syscall-uri, io_uring restrictions pentru ring, cgroups pentru resurse și LSM pentru politica de acces.
Întrebări frecvente
io_uring filters este numele oficial al mecanismului?
În documentația man-pages și liburing, mecanismul stabil este numit io_uring restrictions. „Filters” este o formulare descriptivă, dar termenul tehnic de urmărit este IORING_REGISTER_RESTRICTIONS.
Pot înlocui seccomp cu io_uring restrictions?
Nu. seccomp filtrează syscall-uri, iar io_uring restrictions limitează ce se poate face în ring. Cele două mecanisme acoperă niveluri diferite și trebuie combinate.
De ce trebuie creat ringul cu IORING_SETUP_R_DISABLED?
Pentru ca restricțiile să fie înregistrate înainte ca ringul să accepte submissions. După activare, operațiile sunt validate conform politicii înregistrate.
Ce se întâmplă cu o operație nepermisă?
io_uring_register(2) documentează EACCES atunci când opcode-ul nu este permis de restricțiile înregistrate. Într-un design defensiv, aplicația trebuie să trateze acest caz ca refuz de politică, nu ca eroare temporară.

















































