Quando leggete un disco fisso su Unix vedete un albero di nomi di file e directory. Normalmente non avrete bisogno di andare oltre, ma può essere utile avere maggiori dettagli se vi capita un crash del disco e dovete cercare di salvare dei file. Sfortunatamente non c'è un buon modo per descrivere l'organizzazione del disco dal livello dei file in giù, quindi dovrò partire dall'hardware e risalire.
La superficie del vostro disco, dove vengono immagazzinati i dati, si divide in una sorta di bersaglio per il tiro a freccette: in tracce circolari che sono poi `affettate' in settori. Dal momento che le tracce vicino al bordo esterno hanno area maggiore di quelle vicino al centro, le tracce esterne hanno più settori rispetto a quelle interne. Ogni settore (o blocco disco) ha la stessa dimensione, che sui moderni Unix è generalmente pari a 1K binario (1024 parole da 8 bit). Ogni blocco è individuato da un indirizzo univoco, il numero di blocco disco.
Unix divide il disco in partizioni disco. Ogni partizione è formata da una serie continua di blocchi che vengono usati separatamente da quelli delle altre partizioni, come file system oppure come spazio swap. La partizione con numero più basso viene spesso trattata in modo speciale, come partizione di avvio dove si può mettere un kernel da far partire.
Ogni partizione è alternativamente uno spazio swap, usato per implementare memoria virtuale, oppure un file system, usato per contenere i file. Le partizioni swap sono trattate proprio come una sequenza lineare di blocchi. I file system, invece, hanno bisogno di un modo per associare i nomi dei file alle sequenze di blocchi disco. Dal momento che la dimensione dei file aumenta, diminuisce, si modifica nel tempo, i blocchi dati di un file non saranno una sequenza lineare ma potranno essere disseminati su tutta la sua partizione (dipende da dove il sistema operativo riesce a trovare un blocco libero quando gliene serve uno).
All'interno di ciascun file system la corrispondenza tra i nomi e i blocchi viene assicurata da una struttura chiamata inode. C'è un gruppo di questi elementi vicino al ``fondo'' (i blocchi a numerazione più bassa) di ciascun file system (quelli più bassi in assoluto sono usati a fini di manutenzione e di etichettatura, non ne parleremo qui). Ogni inode individua un file. I blocchi dati dei file si trovano sotto gli inode.
Ciascun inode contiene una lista dei numeri di blocco disco relativi al file che individua. (Questa è una mezza verità, corretta solo per i file piccoli, ma il resto dei dettagli non è importante qui.) Notate che l'inode non contiene il nome del file.
I nomi dei file si trovano nelle strutture delle directory. Una struttura della directory associa i nomi ai numeri inode. Ecco perché, su Unix, un file può avere più nomi reali (o hard link); sono soltanto diverse voci di directory che puntano allo stesso inode.
Nel caso più semplice, tutto il vostro file system Unix si trova su di una sola partizione disco. Anche se questa situazione si ritrova in qualche piccolo sistema Unix personale, è inusuale. Più tipicamente esso è suddiviso tra più partizioni disco, magari su diversi dischi fisici. Così, per esempio, il vostro sistema può avere una piccola partizione dove alloggia il kernel, una un po' più grande dove si trovano i programmi di utilità del SO ed una molto più grande dove ci sono le directory personali degli utenti.
La sola partizione alla quale avrete accesso subito dopo l'avvio del sistema è la partizione root, che è (quasi sempre) quella dalla quale avete fatto il boot. Essa contiene la root directory del file system, il nodo superiore dal quale dipende tutto il resto.
Le altre partizioni del sistema devono collegarsi a questa root affinché tutto il vostro file system multipartizione sia accessibile. Circa a metà del processo di avvio, il vostro Unix renderà accessibili queste partizioni non root. Dovrà montare ciascuna di esse su una directory della partizione root.
Per esempio, se avete una directory chiamata `/usr', si tratta probabilmente di un mount point per una partizione che contiene molti programmi che fanno parte della distribuzione standard del vostro Unix ma che non sono necessari durante l'avvio iniziale.
Ora possiamo guardare al file system dall'alto al basso. Ecco cosa succede quando aprite un file (quale, ad esempio, /home/esr/WWW/ldp/fundamentals.sgml):
Il kernel parte dalla radice del vostro file system Unix (dalla partizione root). Cerca una directory chiamata `home'. Di solito `home' è un mount point per una grande partizione utente da qualche altra parte, così va di là. Nella struttura della directory di livello più alto di quella partizione utente cerca poi una voce chiamata `esr' e ne estrae un numero di inode. Va a quell'inode, vede che si tratta di una struttura di directory e cerca `WWW'. Estraendo quell'inode, va alla corrispondente sottodirectory e cerca `ldp'. Questo lo porta ad un altro inode di directory ancora. Aprendolo, trova il numero inode di `fundamentals.sgml'. Questo inode non è una directory, ma contiene piuttosto la lista dei blocchi disco associati al file.
Per evitare che i programmi, in modo accidentale o malizioso, accedano a dati cui non dovrebbero accedere, Unix usa la caratteristica dei permessi. Questi furono originariamente ideati per gestire il timesharing proteggendo gli utenti multipli su uno stesso computer gli uni dagli altri, ancora ai tempi in cui Unix girava principalmente su costosi minicomputer condivisi.
Per capire i permessi dei file, dovete richiamare alla mente la nostra descrizione degli utenti e dei gruppi dalla sezione Cosa succede al login?. Ogni file è di proprietà di un utente e di un gruppo. Questi sono inizialmente quelli del creatore del file; possono essere cambiati con i programmi chown(1) e chgrp(1).
I permessi di base che possono essere associati con un file sono `lettura' (permesso di leggere i dati in esso contenuti), `scrittura' (permesso di modificarlo) e `esecuzione' (permesso di lanciarlo come programma). Ogni file ha tre serie di permessi: uno per l'utente che ne è proprietario, uno per qualunque utente del suo gruppo proprietario e uno per tutti gli altri. I `privilegi' che avete quando fate il login sono solo la possibilità di leggere, scrivere ed eseguire quei file per i quali i bit di permesso corrispondono al vostro user ID o uno dei gruppi cui appartenete.
Per vedere come questi possono interagire e come lo Unix li mostra, guardiamo un listato di file di un ipotetico sistema Unix. Eccone uno:
snark:~$ ls -l notes
-rw-r--r-- 1 esr users 2993 Jun 17 11:00 notes
Si tratta di un ordinario file di dati. Il listato ci dice che è posseduto dall'utente `esr' ed è stato creato di proprietà del gruppo `users'. Probabilmente il computer pone tutti gli utenti ordinari in questo gruppo in modo predefinito; altri gruppi usati di frequente su macchine condivise sono `staff', `admin' o `wheel' (per ovvie ragioni, i gruppi non sono molto importanti sulle workstation per utente singolo o sui PC). Il vostro Unix potrebbe usare un diverso gruppo predefinito, magari uno con lo stesso nome del vostro user ID.
La stringa `-rw-r--r--' rappresenta i bit di permesso per il file. Il primissimo trattino è la posizione del bit di directory; mostrerebbe `d' se il file fosse una directory. Dopo di questo, i primi tre posti sono i permessi utente, i secondi tre i permessi di gruppo e i terzi i permessi per gli altri (spesso chiamati `mondo' o `world'). Per questo file, l'utente proprietario `esr' può leggere o scrivere il file, le altre persone nel gruppo `users' possono leggerlo e tutti gli altri al mondo possono leggerlo. Si tratta di un insieme di permessi tipico per un ordinario file di dati.
Ora diamo un'occhiata ad un file con permessi differenti. Questo file è GCC, il compilatore C GNU.
snark:~$ ls -l /usr/bin/gcc
-rwxr-xr-x 3 root bin 64796 Mar 21 16:41 /usr/bin/gcc
Questo file appartiene ad un utente chiamato `root' e ad un gruppo chiamato `bin'; può essere scritto (modificato) solo da root, ma letto od eseguito da chiunque. Si tratta di proprietà e insieme di permessi tipici per un comando pre-installato. Il gruppo `bin' esiste in alcuni Unix per raggruppare i comandi di sistema (il nome è un residuo storico, abbreviazione di `binari'). Il vostro Unix potrebbe invece usare un gruppo `root' (che non è proprio la stessa cosa dell'utente `root'!).
L'utente `root' è il nome convenzionale per lo user ID di numero 0, uno speciale, privilegiato account che può disporre di tutti i privilegi. Accedere come root è utile ma pericoloso: un errore di digitazione può cancellare fondamentali file di sistema che lo stesso comando digitato da un utente ordinario non riuscirebbe ad intaccare.
Dal momento che l'account root è così potente, il suo accesso dovrebbe essere custodito con molta cura. La vostra password di root è l'informazione di sicurezza più critica e fondamentale del vostro sistema ed è ciò che qualunque cracker e intruso che vi dia la caccia mira ad ottenere.
(Riguardo alle password: non scrivetele -- e non scegliete una password che possa essere facilmente indovinata, come il nome della vostra ragazza/o. Questa è una cattiva prassi incredibilmente comune che aiuta moltissimo i cracker...)
Ora vediamo un terzo caso:
snark:~$ ls -ld ~
drwxr-xr-x 89 esr users 9216 Jun 27 11:29 /home2/esr
snark:~$
Questo file è una directory (notate la `d' nella prima casella dei permessi). Vediamo che può essere scritto solo da esr, ma letto ed eseguito da chiunque altro. I permessi vengono interpretati in maniera speciale quando riguardano una directory: regolano l'accesso ai file contenuti nella directory.
Il permesso di lettura di una directory è semplice: significa soltanto che potete attraversare la directory per aprire i file e le directory in essa contenuti. Il permesso di scrittura attribuisce la capacità di creare e rimuovere file nella directory. Il permesso di esecuzione vi dà la possibilità di cercare nella directory -- cioè di listarla e vedere i nomi dei file e delle directory che contiene. A volte vedrete directory che sono leggibili da chiunque ma non eseguibili da chiunque: significa che un utente qualsiasi può raggiungere i file e le directory in essa contenuti, ma solo conoscendo esattamente i loro nomi.
Per finire, vediamo quali sono i permessi dello programma login stesso.
snark:~$ ls -l /bin/login
-rwsr-xr-x 1 root bin 20164 Apr 17 12:57 /bin/login
Ha i permessi che ci aspettiamo per un comando di sistema -- eccetto quella `s' dove ci dovrebbe essere il permesso di esecuzione per il proprietario. Questa è la visualizzazione di uno speciale permesso chiamato `set-user-id' o setuid bit.
Il setuid bit è di solito associato a programmi che hanno bisogno di dare agli utenti ordinari i privilegi di root, ma in modo controllato. Quando è impostato su un programma eseguibile, vi sono consentiti i privilegi del possessore di quel file di programma mentre il programma sta funzionando per conto vostro.
Come lo stesso account di root, i programmi setuid sono utili ma pericolosi. Chiunque riesca sovvertire o modificare un programma setuid di proprietà di root può usarlo per lanciare una shell con privilegi di root. Per questa ragione, aprire un file in scrittura disattiva automaticamente il setuid bit sulla maggior parte degli Unix. Molti attacchi alla sicurezza di Unix cercano di sfruttare bachi nei programmi setuid per sovvertirli. Gli amministratori di sistema consci dei problemi di sicurezza sono quindi estremamente cauti con questi programmi e riluttanti ad installarne di nuovi.
Ci sono un paio di dettagli importanti che abbiamo trascurato parlando
dei permessi. In particolare, come il gruppo proprietario e i permessi
vengono assegnati quando un file viene creato per la prima volta. Il
gruppo è un problema perché gli utenti possono far parte di più
gruppi, ma solo uno di questi (specificato nella voce dell'utente in
/etc/passwd
) è il gruppo predefinito
dell'utente e avrà normalmente la proprietà dei file creati
dall'utente.
La storia dei bit di permesso iniziali è un po' più complicata. Un programma che crea un file di solito specifica i permessi di partenza. Ma questi verranno modificati da una variabile d'ambiente dell'utente chiamata umask. La umask specifica quali bit di permesso disattivare al momento della creazione di un file. Il valore più comune, predefinito nella maggior parte dei sistemi, è -------w- o 002, che disattiva il bit di scrittura per il mondo intero. Rifatevi alla documentazione del comando umask nella pagina di manuale della vostra shell per maggiori dettagli.
Prima accennavamo al fatto che i file system possono essere delicati. Ora sappiamo che per raggiungere un file dobbiamo fare il gioco della campana attraverso quella che può essere una catena arbitrariamente lunga di riferimenti inode e directory. Supponiamo ora che sul vostro disco fisso si formi un punto danneggiato.
Se siete fortunati ciò vi farà perdere solo qualche file di dati. Se invece siete sfortunati, si potrebbe danneggiare una struttura di directory o un numero inode e un intero sottoalbero del vostro sistema potrebbe rimanere pendente nel limbo. Oppure, peggio ancora, si potrebbe originare una struttura rovinata che punta in più modi allo stesso blocco disco o inode. Un danneggiamento di questo tipo si può propagare a partire da una normale operazione sui file, facendo perdere tutti i dati collegati al punto danneggiato di origine.
Fortunatamente questo tipo di eventualità è divenuto abbastanza infrequente perché l'hardware dei dischi è più affidabile. Tuttavia, questo comporta che il vostro Unix voglia controllare periodicamente l'integrità del file system per assicurarsi che non ci sia nulla fuori posto. Gli Unix moderni compiono un rapido controllo dell'integrità di ciascuna partizione nella fase di avvio, giusto prima di montarle. Ogni tot riavvii fanno un controllo molto più approfondito che impiega qualche minuto in più.
Se tutto questo può far sembrare che Unix sia terribilmente complesso e incline a malfunzionamenti, può essere rassicurante sapere che questi controlli nella fase d'avvio tipicamente intercettano e correggono i problemi normali prima che diventino veramente disastrosi. Altri sistemi operativi non hanno questi strumenti, cosa che velocizza un po' l'avvio ma può mettervi molto di più nei pasticci quando cercate di fare un salvataggio a mano (e sempre assumendo che abbiate una copia delle Norton Utilities o simili, tanto per cominciare...).