Daemonul înregistrează o eroare de chroot, iar profilul pare deja generos, așa că remedierea tentantă este să lărgești o regulă de cale și să repornești. De obicei asta nu schimbă nimic, pentru că chroot este condiționat de un privilegiu pe care profilul nu l-a putut niciodată acorda. A decide ce strat să modifici cere trei verificări, și ele sunt ieftine: ce are voie procesul să dețină, ce permite politica și ce a eliminat lansatorul înainte ca vreuna dintre cele două să conteze.

Două porți separate, și doar una aparține de AppArmor

chroot are nevoie de CAP_SYS_CHROOT în spațiul de nume de utilizator în care rulează procesul. Acesta este privilegiul convențional din Linux, verificat de kernel înainte ca apelul să facă ceva cu căile. Separat, un profil AppArmor în modul enforcing poate refuza capabilitatea chiar și atunci când procesul o deține, pentru că politica obligatorie este consultată în plus față de credențiale, nu în locul lor. Distincția contează în practică: cele două straturi trăiesc în fișiere diferite și sunt de obicei întreținute de oameni diferiți.

Cele două porți eșuează cu același errno. Ambele produc EPERM și ambele apar ca o plângere generică de permisiune în jurnalul daemonului, motiv pentru care ghicirea conținutului profilului pierde atât de mult timp. Regula de cale pe care urma să o adaugi controlează accesul la fișiere după ce chroot reușește; ea nu are nicio legătură cu faptul dacă operațiunea este permisă.

O a treia poartă stă în amonte de ambele. Dacă managerul de servicii sau un wrapper a pornit procesul fără capabilitatea în setul său de limite, nicio modificare AppArmor nu o poate readuce, iar adăugarea de capabilități în profil doar documentează o intenție pe care kernelul nu o va onora.

Citește starea privilegiilor înainte de a edita politica

Începe de la procesul care rulează, nu de la configurația pe care crezi că este activă. Fișierul de stare expune cinci măști de capabilități și indicatorul no-new-privileges, iar ele răspund la întrebări diferite:

grep -E '^(CapInh|CapPrm|CapEff|CapBnd|CapAmb|NoNewPrivs):' /proc/$(pidof openvpn)/status
sudo aa-status | grep -i openvpn

CapEff este setul care contează pentru apel: o capabilitate prezentă în CapBnd dar absentă din CapEff este permisă de plafon și nu este deținută în acel moment. CapAmb contează atunci când binarul nu este privilegiat în sensul obișnuit de setuid, pentru că capabilitățile ambientale sunt felul în care un serviciu păstrează un privilegiu peste exec fără capabilități de fișier. CapInh ține biți care ar putea fi moșteniți peste exec, dar numai când setul moștenibil al fișierului executat permite asta, așa că un bit acolo nu acordă nimic de unul singur.

Apoi confirmă ce profil este cu adevărat atașat. Un proces poate fi confinat de un nume de profil la care nu te așteptai, mai ales când o distribuție livrează împreună propria unitate și propriul profil, iar citirea /proc/PID/attr/current lămurește asta într-o singură linie. Compararea fișierului tău editat cu profilul pe care kernelul îl raportează este diferența dintre a remedia cauza și a edita un fișier pe care nimeni nu îl încarcă.

Adaugă regula de capabilitate doar când traseul de audit spune asta

Înregistrările kernelului și ale auditului numesc stratul care refuză. Caută un refuz care are operațiunea capable și numele sys_chroot, împreună cu profilul care l-a produs. Dacă acea înregistrare există, procesul deținea deja capabilitatea și AppArmor a refuzat-o, iar schimbarea țintită este o regulă de capabilitate în profilul real:

capability sys_chroot,

Păstreaz-o ca fragment în profilul care este cu adevărat atașat și verifică cuvântul-cheie în referința de profil apparmor.d, în loc să copiezi o regulă dintr-un tutorial fără legătură. Dacă o pui într-un include partajat, o acorzi fiecărui program confinat care încarcă acel fișier, iar trecerea profilului în modul complain ascunde următorul refuz în loc să îl rezolve pe acesta. Regula din profil elimină un refuz de politică; ea nu fabrică privilegiu, așa că un proces care nu a avut niciodată CAP_SYS_CHROOT în setul său efectiv va eșua în continuare cu regula în vigoare.

Dacă înregistrarea de audit nu arată niciun refuz AppArmor, oprește editarea profilului. Te confrunți cu o problemă de credențiale, iar munca rămasă este în unitate sau în procesul părinte, nu în limbajul de politică.

Managerul de servicii își ține propriul plafon

systemd stabilește un set de limite de capabilități pentru fiecare serviciu, iar implicit acel set este îngust. Orice este exclus acolo devine indisponibil pentru proces, indiferent ce spune profilul, motiv pentru care unitățile întărite pot eșua la o operațiune care funcționa când daemonul era pornit manual. Directivele relevante sunt ușor de citit în unitate și ușor de trecut cu vederea când aplicația raportează eroarea. Drop-in-urile livrate de un pachet de distribuție sunt sursa obișnuită a unui plafon pe care nimeni nu își amintește că l-a configurat.

Ridicarea plafonului și acordarea capabilității sunt două schimbări, nu una. O intrare în setul de limite spune că procesul poate deține capabilitatea; ea nu o adaugă în setul efectiv, iar NoNewPrivs poate împiedica reușita unei elevări ulterioare chiar și când tot restul se aliniază. Adaugă doar ce are nevoie operațiunea, păstrează restul întăririi intact și rezistă tentației de a acorda toate capabilitățile pentru ca un singur apel să treacă.

Ordinea contează și aici. Schimbă mai întâi plafonul unității, verifică faptul că CapEff conține acum bitul și abia apoi decide dacă AppArmor mai refuză. A face ambele schimbări deodată te lasă din nou să ghicești dacă eșecul persistă.

După ce refuzul dispare, verifică închisoarea în sine

Un chroot reușit mută rădăcina, așa că fiecare cale pe care daemonul o atinge după aceea este rezolvată în interiorul arborelui nou. Configurație lipsă, un nod de dispozitiv absent sau un director de certificate care nu a fost copiat vor apărea acum ca eroare de fișier, iar acea eroare este o problemă de așezare, nu de capabilitate. Citește următorul eveniment în loc să adaugi o altă permisiune largă. Mutarea schimbă și sensul unei căi relative, motiv pentru care ghidurile de întărire insistă pe căi absolute în configurația daemonului.

Ajută și să reții ce nu face chroot. Este o graniță de cale, nu un sandbox: un proces care păstrează privilegiul poate ieși din ea, motiv pentru care capabilitatea este de obicei eliminată după apel și de ce confinarea ar trebui să rămână în jurul daemonului. Păstrarea împreună a profilului AppArmor, a setului de limite de capabilități și a restricțiilor de sistem de fișiere este scopul exercițiului, nu un rest de eliminat după ce serviciul pornește.

Regula de decizie este scurtă. Dacă înregistrarea de audit numește AppArmor, adaugă o regulă de capabilitate în profilul atașat. Dacă setul efectiv este gol, repară plafonul unității și ordinea de renunțare la privilegii. Dacă profilul nu este cel pe care l-ai editat, oprește editarea și găsește-l pe cel real.

Articole similare