Unix-alapok
A Unix/Linux szerverek üzemeltetése wikiből
		A lap korábbi változatát látod, amilyen KornAndras  (vitalap | szerkesztései) 2008. szeptember 17., 01:23-kor történt szerkesztése után volt.
A Unix:
- Többfelhasználós (multiuser)
 - Többfeladatos (multitaszking)
 - Hálózati (network)
 
operációs rendszer (operating system). De ezt úgyis tudtuk.
Egy csomó minden mást is tudunk, úgyhogy koncentráljunk inkább olyasmire, amit talán nem, vagy nem annyira pontosan.
Tartalomjegyzék | 
1 Processz állapottere
- UID
 - GID
 - supplementary group memberships
 - effektív UID (pl. setuid bit miatt lehet más)
 - effektiv GID (pl. setgid bit miatt lehet más)
 - current working directory
 - filedeszkriptorok
 - környezeti változók
 -  PGID
- kill -SIGNAL -PGID az egész process groupnak elküldi a signalt
 
 - scheduler
 - niceness (Linuxon újabban külön ionice is)
 - resource limits
 - root directory (chroot esetén változhat)
 - umask
 - capability-k
 - újabban: namespace (külön fs-, hálózati-, processz-, esetleg IPC-)
 - stb.
 
2 Capability-k
-  A root jogosultságainak szétparticionálása kisebb jogosultság-csomagokra, amikkel egy-egy thread külön-külön is rendelkezhet. Pl:
- CAP_DAC_OVERRIDE: fájlrendszer-jogok figyelmen kívül hagyása;
 - CAP_KILL: nemcsak saját processznek küldhet signalt;
 - CAP_MKNOD: hozhat létre device node-ot a fájlrendszerben;
 - CAP_NET_BIND_SERVICE: bind()-olhat 1024 alatti portra;
 - CAP_SETUID: válthat user ID-t;
 - CAP_SYS_BOOT: újraindíthatja a gépet;
 - stb. (több tucat van)
 
 - Majd egyszercsak rendesen működni fog, és akkor jó lesz. :) Szerencsére talán már belátható időn belül.
 - A 2.6.24-es kernel óta elvileg a fájlrendszerben is adhatók capabilityk a programoknak, kb. mint a setuid bit. Mindössze kb. 10 évet késett ez a fícsör.
 
2.1 Capabilityk a processzekben/threadekben
-  Minden threadhez három capability-halmaz tartozik:
-  Permitted ("megengedett"): A thread által birtokolható, örökíthető capabilityk halmaza. Ami nincs benne, azt az adott thread sehogy sem tudja megszerezni (kivéve, ha új binárist tölt magára exec()-kel, és azon pl. setuid bit volt).
- 2.6.24 előtt a CAP_SETPCAP-pel rendelkező processz bármelyik másik processz permitted készletében állítgathatta azokat a capabilityket, amik a saját permitted készletében megvoltak.
 
 - Inheritable ("örökíthető"): Amit a thread ebbe rak a permittedből, az lesz az általa exec() hívással indított új folyamat permitted készlete.
 - Effective ("hatásos"): ezeket szeretnénk éppen használni. A kernel a jogosultságellenőrzések során ezt nézi.
 
 -  Permitted ("megengedett"): A thread által birtokolható, örökíthető capabilityk halmaza. Ami nincs benne, azt az adott thread sehogy sem tudja megszerezni (kivéve, ha új binárist tölt magára exec()-kel, és azon pl. setuid bit volt).
 - A processz a capset() hívással viszonylag szabadon állítgathatja a két utóbbi halmaz tartalmát (de csak a permitted készletben levő capabilitykkel gazdálkodhat).
 - fork() során az új processz a szülő capability-készleteit örökli.
 
2.2 Capabilityk a fájlrendszerben
- A filerendszerben egy bővített attribútumban tárolódik, hogy az adott binárishoz milyen capability-halmazokat rendeltünk.
 -  Szintén három halmaz van:
- Permitted: a bináris futtatásával létrejövő processz permitted-készlete kiegészül az itt felsorolt capabilitykkel.
 -  Inheritable: ez egy maszk, amit a kernel az exec() hívás során ÉS-kapcsolatba hoz a hívó processz inheritable halmazával; az így kapott halmazhoz adódik hozzá az iménti permitted halmaz.
- Ezzel korlátozható, hogy a bináris mit örökölhet a szülőjétől: pl. megoldható, hogy a /bin/sh ne örökölhessen CAP_DAC_OVERRIDE-ot és CAP_NET_BIND_SERIVCE-t. Ezzel egy csomó exploitot ki is heréltünk (persze ez csak látszatmegoldás lenne).
 - Jobban használható arra, hogy démonoktól eleve elvegyünk olyan capabilityket, amikre nincs szükségük: pl. a webszervernek nem kellhet CAP_MKNOD.
 
 -  Effective: ez itt nem halmaz, hanem egy jelzőbit. Ha 1, az új processz permitted-készletében szereplő összes capability azonnal megjelenik az effective készletben is. Ha 0, akkor nem. 
-  Buta programokhoz jó, amik nem tudják maguknak állítgatni az effective készletet akkor, amikor éppen kell.
- Ez a jelenlegi programok kb. 99,9999%-ára igaz.
 
 
 -  Buta programokhoz jó, amik nem tudják maguknak állítgatni az effective készletet akkor, amikor éppen kell.
 
 
2.3 capability bounding set
- Ez régebben egy olyan rendszerszintű maszk volt, ami korlátozta, milyen capabilityket rakhat egy thread a permittedből az inheritable készletébe (ha nem volt benne elve).
 -  A boot után a maszkban csak törölni lehetett a biteket, bebillenteni nem.
- Ez a mechanizmus kevés valódi rendszerben volt igazán hasznos.
 
 - Újabban a binárisok permitted-készletét is maszkolja (így a rendszerbe bárhogy bejuttatott CAP_DAC_OVERRIDE-os bináris sem juthat ehhez a capabilityhez, ha kivesszük a bounding setből).
 -  Még újabban (a 2.6.25 óta) már nem rendszer-, hanem szálszintű maszkról van szó.
- A szál, ha van CAP_SETPCAP capabilityje, törölhet biteket a maszkból.
 - A maszk fork() és exec() során is öröklődik a gyermekfolyamatra.
 
 - Vannak még ezzel kapcsolatos finomságok; l. man 7 capabilities
 
2.4 Capabilityk használhatósága
-  Egyelőre nem az igazi a sok kompatibilitási megoldás miatt, pl:
- sajnos a 0-ás UID-val futó processzek exec() után is teljes capability-halmazt kapnak.
 - Setuid root binárisok szintén.
 - Teljes root->nemroot uidváltás esetén a permitted és az effective halmaz törlődik.
 - root->nemroot EUID-váltás esetén a kernel törli az effective halmazt.
 -  nemroot->root EUID-váltás esetén a kernel a permitted halmazt az effective halmazra másolja.
- A 2.6.26-ban javítottak ezen, az okos programok (az összes program 0,0001%-a) már alighanem tudnák normálisan használni a capabilityket.
 
 
 
3 Signalok
-  Aszinkron jelzések processzek között.
- A címzett nem tudja, kitől kapja a signalt.
 
 -  Lehet hozzájuk handlereket regisztrálni
-  Handler nélkül öt alapakció egyikét eredményezik:
- Term (kilépés)
 - Ign (semmi)
 - Core (kilépés és coredump)
 - Stop (felfüggesztés)
 - Cont (folytatás, ha a processz fel volt függesztve)
 
 - Van alapértelmezés, hogy ezek közül melyiket, de a processz megváltoztathatja.
 - A signal disposition (hogy mi történjen egy adott signal hatására) a processz tulajdonsága, minden threadben ugyanaz.
 
 -  Handler nélkül öt alapakció egyikét eredményezik:
 -  Az érdektelenek kimaszkolhatók, blokkolhatók (kivéve KILL és STOP).
- A blokkolt signalok sorbaállnak, amíg a processz vagy szál meg nem szünteti a blokkolásukat.
 - A processz lekérdezheti, milyen sorbanálló signaljai vannak (sigpending()).
 - Egyféle signalból csak egy állhat sorba.
 - A sorbanálló signalok kézbesítési sorrendje nem specifikált.
 
 -  Signal címzettje lehet processz vagy szál (thread).
- Ha többszálú processz kap signalt, a kernel az adott signalt éppen nem blokkoló szálak közül véletlenszerűen választja ki azt, amelyik megkapja.
 
 - Kézbesítésük amúgy sem feltétlenül azonnali (pl. D állapotú processz nem kapja meg, l. később)
 -  A signal megkapásakor a program futása megszakad, és a vezérlés a handlerre kerül.
- Signal handlert óvatosan kell írni, mert a program tetszőlegesen inkonzisztens állapotban lehet a handler indulásakor.
 - A POSIX szabvány specifikál néhány tucat könyvtári függvényt, amiket elvileg gond nélkül hívhatunk.
 - Signal érkezése rendszerhívást is megszakíthat; a hívás ebben az esetben EINTR hibakóddal tér vissza, de a processz kérheti, hogy ilyenkor a legutóbbi rendszerhívás automatikusan hívódjon újra a signal handler kilépése után (ennél igazából bonyolultabb, függ a hívás jellegétől is, itt nem megyünk bele, l. man 7 signal).
 
 -  Signal küldése
- kill paranccsal
 - kill() rendszerhívással
 - sigqueue() rendszerhívással (l. a real-time signaloknál)
 
 -  Néhány gyakori signal:
-  HUP (HangUp)
- Ha eltűnik a terminál (pl. a user bezárja az ablakot)
 - Daemonoknál gyakran: olvasd újra a configot
 
 -  INT (Interrupt)
- CTRL-C
 
 -  QUIT 
- CTRL-\
 
 -  ILL (Illegal instruction)
- CPU-kivétel
 - súlyos program- vagy hardverhibára utal
 
 -  KILL
- Kilépteti a processzt, nem maszkolható
 
 -  USR1
- Nincs előre definiált jelentése, szabadon felhasználható
 
 -  SEGV (Segmentation Violation)
- "A program érvénytelen műveletet hajtott végre"
 -  Tipikus okok:
- Pointer rossz helyre mutat (pl. túlcímeztünk egy tömböt)
 - Valamit kértünk, nem sikerült, mégis használjuk (pl. nemlétező file-t próbáltunk megnyitni, és annak ellenére, hogy az open() hibát adott vissza, az érvénytelen filedescriptorból olvasni próbálunk)
 
 - Vagyis: programhiba
 - Lehet hardverhiba is
 
 -  USR2
- l. mint fent
 
 -  PIPE ("broken pipe")
- A pipe-unkat olvasó processz kilépett
 
 -  ALRM (Alarm)
- Időzítő lejárt
 
 -  TERM (Terminate)
- Default "lépj ki" signal
 
 -  CHLD (Child exited)
- Véget ért egy gyermekfolyamatunk
 
 -  CONT (Continue)
- Folytatódhat a végrehajtás STOP vagy TSTP után
 
 -  STOP
- Felfüggesztés, nem maszkolható
 
 -  TSTP (Terminal stop)
- Felfüggesztés CTRL-Z hatására
 
 -  XCPU (CPU time exceeded)
- Lejárt a megengedett CPU-idő
 
 -  WINCH (Window changed)
- Megváltozott a terminál mérete
 
 
 -  HUP (HangUp)
 -  Létezik "real-time signal" is; a Linux 32 különbözőt támogat.
- Nincs előre definiált jelentésük, arra használjuk, amire akarjuk.
 -  Különlegességek:
- Ugyanabból a real-time signalból egynél több is állhat sorba egyszerre.
 - A sigqueue() rendszerhívással adat is küldhető a signal mellé; a címzett ki tudja olvasni.
 - Ha sigqueue()-t használunk, a címzett megnézheti, milyen UID-val és PID-val futott a küldő-processz.
 - A kézbesítés sorrendje garantált. Először a signalok sorszáma szerinti növekvő sorrendben, és ha ez nem egyértelmű, akkor a sorbaállítás ideje szerinti növekvő sorrendben kézbesülnek.
 -  A 2.6.8-as kernel óta userenkénti rlimit szabályozza, hány signal állhat sorba.
- Az rlimit a processz állapotteréhez tartozik; több azonos UID-val futó processz limitje különbözhet. Az ellenőrzés a sigqueue() meghívásakor történik, és a kernel a hívó processz limitjét hasonlítja össze az adott user által már sorbaállított signalok számával.
 
 
 
 
4 Processzek állapotai
Pl. a ps(1) outputjában látszanak:
% ps axu USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND [...] korn 1842 0.0 0.1 4932 2592 ? Ds Sep07 0:23 SCREEN -D korn 17670 0.0 0.0 4896 948 pts/0 R+ 20:55 0:00 ps axu [...]
- D: I/O-ra vár (itt alighanem épp a read() vagy a write() rendszerhívásban)
 - R: fut vagy futásra kész
 - S: vár (ilyenkor kaphat signalt)
 - T: fel van függesztve
 - Z: "zombie" - véget ért, de a szülője még nem olvasta ki a visszatérési értékét a wait() vagy a waitpid() rendszerhívással
 
Egyéb flagek:
- <: negatív nice (több processzoridőt kap)
 - N: pozitív nice (kevesebb processzoridőt kap)
 - s: session leader (igazából nincs jelentősége)
 - l: többszálú
 - +: előtérben van
 
5 Ajánlott irodalom
Ezeket részben hallgatók írták egy másik tárgy óráin elhangzottak alapján, úgyhogy lehetnek bennük tévedések:
- 2004. őszi "alapozólabor" első gyakorlatának óravázlata
 - 2005. tavaszi "alapozólabor" első gyakorlatának óravázlata
 - 2005. őszi "alapozólabor" első gyakorlatának óravázlata
 - 2006. tavaszi "alapozólabor" első gyakorlatának óravázlata
 
Ezek megbízhatóbbak, de csak a signalokról van szó bennük:
- man 7 signal (különösen a realtime signalokról szóló rész tanulságos)
 - man 2 kill (magyarul)
 - man 1 kill (magyarul)
 
A processzek lehetséges állapotairól:
A process groupokról:
- http://en.wikipedia.org/wiki/Process_group
 - Job Control (Ez kicsit részletesebb.)
 
6 Potenciális zh-kérdések
-  Soroljon fel legalább tíz olyan állapotváltozót (az állapottér elemét), amelyet egy unixos gyermekfolyamat örököl a szülőjétől!
- current working directory
 - UID
 - GID
 - effektív UID (pl. setuid bit miatt lehet más)
 - effektiv GID (pl. setgid bit miatt lehet más)
 - PGID
 - filedeszkriptorok
 - környezeti változók
 - umask
 - root directory (chroot esetén változhat)
 
 -  Mi a process group?
- Több processz összerendelése egy csoportba. Hasznos, ha futás közben forkol a processz. Nem szükséges figyelni, hogy indult-e újabb, mert a PGID segítségével a csoport összes folyamata megkapja a nekik szánt signal-t.
 
 -  Mi a supplementary group?
- A felhasználó több csoportnak is a tagja, a /etc/group-ban több grouphoz is be van jegyezve.
 
 -  A processzek szempontjából mit jelent az, hogy egy felhasználó tagja egy csoportnak?
- Szigorúan véve nem a felhasználóknak, hanem a futó folyamatoknak vannak csoporttagságaik, ezért a változtatások csak az újonnan induló processzekre lesznek érvényesek, ha a felhasználót hozzáadjuk egy újabb csoporthoz.
 - Még szigorúbban véve az adott buroktól öröklik a jogokat az újonnan induló folyamatok is, ezért aztán újra be kell lépni. Vagy legalábbis újra beolvastatni a burokkal a csoporttagságokat.