chroot не успева на OpenVPN-у: правило AppArmor или могућност?
Додавање путање у AppArmor профил никада не даје CAP_SYS_CHROOT, а одбијени chroot може доћи из три одвојена слоја. Откријте који од њих треба мењати.
Демон бележи неуспех chroot, а профил већ изгледа широкогрудо, па је примамљиво решење проширити правило путање и поново покренути. То обично ништа не мења, јер је chroot затворен привилегијом коју профил никада није могао да пренесе. Да бисте одлучили који слој треба дирати, потребне су три провере, и оне су јефтине: шта процес сме да држи, шта политика дозвољава и шта је покретач уклонио пре него што је било шта од тога постало важно.
Два одвојена врата, и само једна припадају AppArmor-у
chroot захтева CAP_SYS_CHROOT у корисничком простору имена у ком процес ради. То је уобичајена Linux привилегија, коју кернел проверава пре него што позив уради било шта са путањама. Одвојено од тога, AppArmor профил у режиму enforcing може да одбије могућност и када је процес држи, јер се обавезна политика разматра поред акредитива, а не уместо њих. Разлика је у пракси важна: два слоја живе у различитим датотекама и обично их одржавају различити људи.
Обе ове провере одбијају са истим errno. Обе дају EPERM, и обе се у дневнику демона појављују као општа жалба на дозволу, зато нагађање садржаја профила троши толико времена. Правило путање које сте хтели да додате контролише приступ датотекама тек после успешног chroot-а; на то да ли је операција уопште дозвољена оно нема никаквог утицаја.
Трећа врата стоје изнад обе. Ако је менаџер сервиса или омотач покренуо процес без те могућности у његовом граничном скупу, ниједна AppArmor измена је не може вратити, а додавање могућности у профил само документује намеру коју кернел неће испунити.
Прво прочитајте стање привилегија, па мењајте политику
Почните од процеса који ради, а не од конфигурације за коју мислите да је активна. Датотека стања показује пет маски могућности и заставицу no-new-privileges, и оне одговарају на различита питања:
grep -E '^(CapInh|CapPrm|CapEff|CapBnd|CapAmb|NoNewPrivs):' /proc/$(pidof openvpn)/status
sudo aa-status | grep -i openvpn
CapEff је скуп важан за позив: могућност присутна у CapBnd али одсутна из CapEff дозвољена је плафоном и тренутно се не држи. CapAmb је важна када бинарни фајл није привилегован у уобичајеном setuid смислу, јер су амбијенталне могућности начин на који сервис задржава привилегију кроз exec без датотечких могућности. CapInh држи битове који би могли да се наследе кроз exec, али само када наследни скуп извршне датотеке то дозвољава, па бит тамо сам по себи ништа не даје.
Затим потврдите који је профил стварно прикачен. Процес може бити ограничен профилом чије име нисте очекивали, нарочито када дистрибуција испоручује своју јединицу и свој профил заједно, а читање /proc/PID/attr/current то решава у једном реду. Поређење ваше измењене датотеке са профилом који кернел пријављује је разлика између исправљања узрока и мењања датотеке коју нико не учитава.
Додајте правило могућности само када то каже траг ревизије
Записи кернела и ревизије именују слој који је одбио. Потражите одбијање које носи операцију capable и име sys_chroot, заједно са профилом који га је произвео. Ако такав запис постоји, процес је већ имао могућност, а AppArmor га је одбио, и циљана измена је правило могућности унутар стварног профила:
capability sys_chroot,
Држите га као фрагмент у профилу који је заиста прикачен, и проверите кључну реч у референци apparmor.d профила уместо да копирате правило из неповезаног упутства. Стављање у заједнички include даје га сваком ограниченом програму који учита тај фајл, а пребацивање профила у режим complain сакрива следеће одбијање уместо да реши ово. Правило у профилу уклања одбијање политике; оно не ствара привилегију, па ће процес који никада није имао CAP_SYS_CHROOT у свом ефективном скупу и даље да падне, чак и са правилом на месту.
Ако запис ревизије не показује никакво AppArmor одбијање, престаните да мењате профил. Имате посла са проблемом акредитива, а преостали посао је у јединици или у родитељском процесу, не у језику политике.
Менаџер сервиса држи сопствени плафон
systemd поставља гранични скуп могућности за сваки сервис, и подразумевано је тај скуп узак. Све што је тамо искључено недоступно је процесу без обзира шта профил каже, зато ојачане јединице могу да падну на операцији која је радила када је демон покренут ручно. Релевантне директиве се лако читају у јединици и лако превиде када сама апликација пријави неуспех. Drop-in датотеке које испоручује пакет дистрибуције уобичајен су извор плафона за који се нико не сећа да га је подесио.
Подићи плафон и доделити могућност су две измене, не једна. Запис у граничном скупу каже да процес сме да држи могућност; он је не додаје у ефективни скуп, а NoNewPrivs може спречити касније уздизање да успе, чак и када се све остало поклопи. Додајте само оно што је операцији потребно, задржите остатак очвршћавања и одуприте се пречици да се доделе све могућности да би један позив прошао.
И редослед је овде важан. Прво измените плафон јединице, проверите да CapEff сада садржи тај бит, и тек онда одлучите да ли AppArmor још одбија. Ако оба урадите одједном, при неисправности која остаје поново ћете нагађати.
Када одбијање нестане, проверите саму тамницу
Успешан chroot помера корен, па се свака путања коју демон после дира реши унутар новог стабла. Недостајућа конфигурација, одсутни чвор уређаја или директоријум сертификата који није прекопљан сада ће се појавити као грешка датотеке, а та грешка је проблем распореда, не могућности. Читајте следећи догађај уместо да додате још једну широку дозволу. Померање мења и значење релативне путање, зато упутства за очвршћавање инсистирају на апсолутним путањама у конфигурацији демона.
Помаже и да запамтите шта chroot не ради. Он је граница путања, а не sandbox: процес који задржи привилегију може да побегне из њега, зато се могућност обично одбацује после позива и зато ограничење треба да остане око демона. Задржати заједно AppArmor профил, гранични скуп могућности и ограничења датотечног система јесте циљ вежбе, а не остатак који треба уклонити пошто се сервис покрене.
Правило одлуке је кратко. Ако запис ревизије именује AppArmor, додајте једно правило могућности у прикачени профил. Ако је ефективни скуп празан, исправите плафон јединице и редослед одбацивања привилегија. Ако профил није онај који сте мењали, престаните да мењате и пронађите прави.