Seccomp

seccomp (lyhennetty englanninkielisestä  suojatusta laskentatilasta ) on yksi Linux-ytimen suojausmekanismeista , joka tarjoaa mahdollisuuden rajoittaa sovellusten käytettävissä olevien järjestelmäkutsujen määrää ja käyttää myös BPF-mekanismia ( Berkeley Packet Filter ) monimutkaisten suodatusten suorittamiseen. puheluista ja niiden argumenteista. Ilmestyi ensimmäisen kerran ytimen versiossa 2.6.12 vuonna 2005 [1] [2] .

Jos haluat työskennellä epäluotettavien tai vahvistamattomien ja siten mahdollisesti vaarallisten ohjelmien kanssa, on suositeltavaa käyttää erityisiä ympäristöjä, joista on mahdotonta vahingoittaa koko järjestelmän suorituskykyä. Tällaisissa ympäristöissä (hiekkalaatikot, säiliöt) monet järjestelmän ominaisuudet ovat rajoitettuja ohjelmien suorittamiseen, kuten verkkoon pääsy, I/O-laitteet ja vuorovaikutus käyttöjärjestelmän kanssa. seccomp-mekanismi määrittää prosessin sallitut järjestelmäkutsut ja estää ne, joita ei ole aiemmin ilmoitettu. Sitä käytetään tällä hetkellä useissa selaimissa , Linuxin kaltaisissa käyttöjärjestelmissä ja joissakin virtualisointijärjestelmissä .

Historia

seccomp-mekanismin kehitti Andrea Arcangeli ( italialainen  Andrea Arcangeli ) osana kaupallista CPUShare-projektia, jonka pääajatuksena oli määrittää valmiudet ja kehittää ratkaisuja laskentaresurssien tarjoamiseen tietokoneille, erityisesti Linux-käyttöjärjestelmällä. suorittaa kolmannen osapuolen koodia. Ilmestyi ensimmäisen kerran Linux-ytimessä maaliskuussa 2005 (versio 2.6.12). Ensimmäisessä versiossa seccompin ottamiseksi käyttöön prosessin piti kirjoittaa "1" tiedostoon /proc/PID/seccomp. Sen jälkeen vieraskoodiin oli saatavilla vain neljä järjestelmäkutsua: read(), write(), exit()ja sigreturn()[3] . Vuonna 2007 versio 2.6.23 lisäsi mahdollisuuden ottaa seccomp käyttöön järjestelmäkutsulla prctl()käyttämällä PR_SET_SECCOMP-toimintoa, ja /proc-liitäntä poistettiin [4] .

Huolimatta siitä, että CPUShare-projektia, jota varten seccomp kehitettiin, ei kehitetty ja suljettu, se jäi Linux-ytimeen [3] . Helmikuussa 2009 seccomp-koodista löydettiin haavoittuvuus. Se johtui siitä, että Linuxin 32- ja 64-bittisissä versioissa eri järjestelmäkutsut vastasivat samoja numeroita. Esimerkiksi sallittu puhelu read()64-bittisestä versiosta vastasi kiellettyä puhelua restart_syscall()32-bittisestä versiosta. Sen jälkeen heräsi kysymys seccompin poistamisesta Linuxista, ja Linus Torvalds ehdotti, ettei kukaan käyttänyt seccompia [5] .

Koska seccomp oli tarpeeksi yksinkertainen käyttää, Google Chromen kehittäjät saivat idean toteuttaa työkalun siihen perustuvien kolmannen osapuolen laajennuksien suorittamiseen . Tämän tavoitteen saavuttamiseksi pelkkä kaikkien paitsi neljän sallitun järjestelmäkutsun estäminen ei kuitenkaan riittänyt. Tämän seurauksena vuonna 2012 BPF (Berkeley Packet Filter) -mekanismi integroitiin seccompiin (versioon 3.5 lisättiin toinen toimintatapa - SECCOMP_MODE_FILTER), mikä laajensi merkittävästi mekanismin ominaisuuksia - innovaation jälkeen vieras prosessi voisi joustavammin valita sallittujen ja kiellettyjen järjestelmäkutsujen joukon liittämällä sopivan BPF-ohjelman. Vuonna 2012 ilmestyi myös libseccomp-kirjasto, joka tarjoaa yksinkertaisen ja kätevän API :n järjestelmäkutsujen suodattamiseen [4] .

Seccompin käytön yksinkertaistamiseksi vuonna 2013 versio 3.8 lisäsi "Seccomp"-kentän kohtaan /proc/PID/status, jonka avulla voit selvittää seccompin tilan (kun sisällytys poistettiin tiedostosta /proc, ei ollut mahdollista selvittää, oliko jo käytössä oleva seccomp käynnissä keskeyttämättä prosessia). Vuonna 2014 versio 3.17 lisäsi erityisen järjestelmäkutsun - seccomp(), joka osittain toistaa toiminnallisuuden prctl()[4] .

Marraskuussa 2017, kun glibc - kirjaston versio 2.26 julkaistiin, ilmaantui uusi ongelma: koska C -ohjelmissa järjestelmäkutsuja ei tehdä suoraan, vaan vakiokirjaston kääreiden kautta, joiden nimet eivät välttämättä vastaa järjestelmäkutsujen nimiä, puhelun esto voi yllättäen vaikuttaa ohjelmaan. Esimerkiksi glibc-standardin kirjastoversion 2.26 funktio toteutetaan järjestelmäkutsun kautta , joka ei ole sama kuin kutsu ja suodattimen tekijä voi virheellisesti estää sen [6] . open()openat()open()

Kuvaus

Voit käyttää seccomp()tai järjestelmäkutsua ottaaksesi seccompin käyttöön ohjelmassasi prctl(). Tällä hetkellä seccompilla on kaksi toimintatilaa: SECCOMP_MODE_STRICT ja SECCOMP_MODE_FILTER. Voit selvittää, onko seccomp käytössä ja missä tilassa /proc/[pid]/status-tiedoston "Seccomp"-kentästä. Kenttä saa arvot 0, 1 tai 2: 0 — seccomp ei ole käytössä prosessissa, 1 — seccomp SECCOMP_MODE_STRICT-tilassa, 2 — SECCOMP_MODE_FILTER-tilassa [4] . Et voi ottaa seccompia käyttöön muille prosesseille [7] .

SECCOMP_MODE_STRICT-tila

Se oli ainoa toimintatapa ennen Linux 3.5:ää. Käyttääksesi sitä, ydin on määritettävä avaimella CONFIG_SECCOMP=y [2] .

Päästäksesi tähän tilaan, sinun on soitettava puhelu prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT)tai vastaavasti seccomp(SECCOMP_SET_MODE_STRICT, 0, NULL). Nyt prosessi voi käyttää vain neljää järjestelmäkutsua: read(), write(), _exit()ja sigreturn()[3] . Muut järjestelmäkutsut johtavat prosessin päättämiseen SIGKILL-signaalilla. Koska järjestelmäkutsu open()on poistettu käytöstä, jos seccomp on tarkistettava, procfs-tilatiedosto on avattava lukuoikeuksilla ennen kuin seccomp otetaan käyttöön prosessissa [4] .

SECCOMP_MODE_FILTER-tila

Toimintatapa, joka esiteltiin Linux-ytimen versiossa 3.5 [8] . Käytettävissä, jos CONFIG_SECCOMP_FILTER=y-lippu asetettiin ytimen luomisen yhteydessä.

Ennen tähän tilaan siirtymistä on soitettava puhelu prctl(PR_SET_NO_NEW_PRIVS, 1)ja siten no_new_privs-bitti on asetettava prosessille. Syynä tähän vaatimukseen on se, että muutoin etuoikeutettu prosessi voisi suorittaa etuoikeutetun ohjelman execve(). Jos tätä ei tehdä, siirtyminen SECCOMP_MODE_FILTER-tilaan epäonnistuu [4] .

No_new_privs-bitin asettamisen jälkeen, jotta voit liittää suodattimen prosessiin, sinun on kutsuttava prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, args)tai seccomp(SECCOMP_SET_MODE_FILTER, 0, args), jossa args on osoitin rakenteeseen sock_fprog, joka koostuu BPF-käskyjen joukosta ja sen pituudesta. Suodatin suoritetaan aina, kun prosessi tekee järjestelmäkutsun. Kun suodatin käynnistetään, se vastaanottaa syötteenä rakenteen, joka sisältää tiedot järjestelmän kutsunumerosta, arkkitehtuurista, ohjelmalaskurin nykyisestä tilasta ja kutsuargumenteista [7] [8] . Suodattimen tulee palauttaa 32-bittinen arvo, jossa ylemmät 16 bittiä sisältävät suoritettavan toiminnon koodin ja alemmat 16 bittiä dataa. Jos suodatinalgoritmi ei vahingossa anna palautusarvoa, se ei läpäise staattista analyysiä eikä tällaista suodatinta liitetä [9] .

Jos prosessiin on liitetty useita suodattimia, ne linkitetään yksittäin ja suoritetaan päinvastaisessa järjestyksessä kuin ne lisättiin, vaikka yksi suodattimista lopettaisi prosessin [7] . Tällöin järjestelmäkutsun palautusarvo määräytyy ensimmäisen (suodattimien suoritusjärjestyksessä) korkeimman prioriteetin palautusarvon mukaan taulukon mukaan (laskevassa prioriteettijärjestyksessä) [10] :

Toiminta Tulos
SECCOMP_RET_KILL Järjestelmäkutsu epäonnistuu, prosessi lopetetaan signaalilla SIGSYS [4]
SECCOMP_RET_TRAP Järjestelmäkutsu epäonnistuu, prosessi vastaanottaa SIGSYS-signaalin, signaalinkäsittelijällä on pääsy tietoihin järjestelmäkutsusta, joka tuotti tämän tuloksen
SECCOMP_RET_ERRNO Järjestelmäkutsua ei suoriteta, errnosuodattimen paluuarvo on muuttujassa
SECCOMP_RET_TRACE Jos ptrace()prosessille määritetään jäljitin avun avulla, se saa ilmoituksen kutsusta. Jos sitä ei ole määritetty, järjestelmäkutsua ei suoriteta.
SECCOMP_RET_ALLOW Järjestelmäpuhelu käynnissä

Käyttöesimerkkejä

Otetaan käyttöön SECCOMP_MODE_STRICT [4]

# sisältää <stdio.h> # sisältää <unistd.h> # sisältää <linux/seccomp.h> # sisältää <sys/prctl.h> # sisältää <fcntl.h> int main () { int fd ; prctl ( PR_SET_SECCOMP , SECCOMP_MODE_STRICT ); fprintf ( stderr , "yritä avata \n " ); fd = avoin ( "testitiedosto" , O_CREAT ); fprintf ( stderr , "fd = %d" , fd ); paluu 0 ; }

Työn tulos:

$ gcc test_seccomp.c -o test_seccomp $ ./test_seccomp yritä avata Tapettu

Yllä olevassa esimerkissä prctl()prosessi jatkuu puhelun jälkeen täsmälleen siihen hetkeen asti, kun se yrittää soittaa numeroon open().

Esimerkkejä ohjelmistojen käytöstä

Muistiinpanot

  1. 1 2 3 Imamjafar Borate, Chavan RK, 2016 .
  2. 12 Kroah – Hartman, 2007 .
  3. 1 2 3 Kurt Dietrich, Johannes Winter, 2011 .
  4. 1 2 3 4 5 6 7 8 Jake Edge, Michael Kerrisk, 2015 .
  5. Jonathan Corbet. Seccomp ja hiekkalaatikko  // LWN.net. - 2009. - 13. toukokuuta. Arkistoitu alkuperäisestä 12. marraskuuta 2017.
  6. Jonathan Corbet. seccomp()  // LWN.net:n luontainen hauraus. - 2017 - 1. marraskuuta. Arkistoitu alkuperäisestä 9. joulukuuta 2017.
  7. 1 2 3 Lingguang Lei, Jianhua Sun, Kun Sun, Chris Shenefiel, Rui Ma, Yuewu Wang, Qi Li, 2017 .
  8. 1 2 Taesoo Kim, Nickolai Zeldovich, 2013 .
  9. Steven McCanne, Van Jacobson, 1993 .
  10. Turvallinen tietojenkäsittely suodattimilla . Linux-ytimen arkistot . Linux-ytimen organisaatio. Haettu 3. maaliskuuta 2018. Arkistoitu alkuperäisestä 13. lokakuuta 2017.
  11. Anto.Y, 2012 .
  12. Adrian Mouat, 2015 .
  13. Senthil Kumaran S., 2017 .

Kirjallisuus

Linkit