X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=filedir.tex;h=6d02656f05f4374eae593600db1d25f8c74db156;hp=814f6d44431004940c46cfdaa22a929d2a1bb477;hb=922de35645e21550b70e2e5fe5ced103a0d2e0b4;hpb=9fd07acb47a0dddaff1769bdec46ffd760c7f0fb diff --git a/filedir.tex b/filedir.tex index 814f6d4..6d02656 100644 --- a/filedir.tex +++ b/filedir.tex @@ -16,10 +16,11 @@ In questo capitolo tratteremo in dettaglio le modalità con cui si gestiscono file e directory, iniziando dalle funzioni di libreria che si usano per copiarli, spostarli e cambiarne i nomi. Esamineremo poi l'interfaccia che permette la manipolazione dei vari attributi di file e directory ed alla fine -faremo una trattazione dettagliata su come è strutturato il sistema base di -protezioni e controllo dell'accesso ai file e sulle funzioni che ne permettono -la gestione. Tutto quello che riguarda invece la manipolazione del contenuto -dei file è lasciato ai capitoli successivi. +prenderemo in esame la struttura di base del sistema delle protezioni e del +controllo dell'accesso ai file e le successive estensioni (\textit{Extended + Attributes}, ACL, quote disco, \textit{capabilities}). Tutto quello che +riguarda invece la manipolazione del contenuto dei file è lasciato ai capitoli +successivi. @@ -41,8 +42,8 @@ riguarda il comportamento e gli effetti delle varie funzioni. \label{sec:file_link} Una caratteristica comune a diversi sistemi operativi è quella di poter creare -dei nomi fittizi (come gli alias del MacOS o i collegamenti di Windows o i -nomi logici del VMS) che permettono di fare riferimento allo stesso file +dei nomi fittizi (come gli alias del vecchio MacOS o i collegamenti di Windows +o i nomi logici del VMS) che permettono di fare riferimento allo stesso file chiamandolo con nomi diversi o accedendovi da directory diverse. Questo è possibile anche in ambiente Unix, dove tali collegamenti sono @@ -721,9 +722,9 @@ serie 2.4 alla serie 2.6 è stata aumentata a 32 bit la dimensione del tipo \type{dev\_t}, con delle dimensioni passate a 12 bit per il \itindex{major~number} \textit{major number} e 20 bit per il \itindex{minor~number} \textit{minor number}. La transizione però ha anche -comportato il passaggio di \type{dev\_t} a tipo opaco, e la necessità di -specificare il numero tramite delle opportune macro, così da non avere -problemi di compatibilità con eventuali ulteriori estensioni. +comportato il passaggio di \type{dev\_t} a \index{tipo!opaco} tipo opaco, e la +necessità di specificare il numero tramite delle opportune macro, così da non +avere problemi di compatibilità con eventuali ulteriori estensioni. Le macro sono definite nel file \file{sys/sysmacros.h}, che viene automaticamente incluso quando si include \file{sys/types.h}; si possono @@ -917,7 +918,7 @@ esaurite tutte le voci in essa presenti. \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{15cm} + \begin{minipage}[c]{\textwidth} \includestruct{listati/dirent.c} \end{minipage} \normalsize @@ -1155,9 +1156,9 @@ estensione\footnote{le glibc, a partire dalla versione 2.1, effettuano anche ordina i nomi tenendo conto del numero di versione (cioè qualcosa per cui \texttt{file10} viene comunque dopo \texttt{file4}.) -\begin{figure}[!htb] +\begin{figure}[!htbp] \footnotesize \centering - \begin{minipage}[c]{15.6cm} + \begin{minipage}[c]{\codesamplewidth} \includecodesample{listati/my_ls.c} \end{minipage} \caption{Esempio di codice per eseguire la lista dei file contenuti in una @@ -1194,9 +1195,9 @@ voce presente questo è sufficiente a stampare la lista completa dei file e delle relative dimensioni. Si noti infine come si restituisca sempre 0 come valore di ritorno per indicare una esecuzione senza errori. -\begin{figure}[!htb] +\begin{figure}[!htbp] \footnotesize \centering - \begin{minipage}[c]{15.6cm} + \begin{minipage}[c]{\codesamplewidth} \includecodesample{listati/DirScan.c} \end{minipage} \caption{Codice della funzione di scansione di una directory contenuta nel @@ -1381,31 +1382,36 @@ controllo e la creazione si ha giusto lo spazio per una possibile sez.~\ref{sec:proc_race_cond}). Le \acr{glibc} provvedono varie funzioni per generare nomi di file temporanei, -di cui si abbia certezza di unicità (al momento della generazione); la prima -di queste funzioni è \funcd{tmpnam} il cui prototipo è: +di cui si abbia certezza di unicità al momento della generazione; storicamente +la prima di queste funzioni create a questo scopo era +\funcd{tmpnam},\footnote{la funzione è stata deprecata nella revisione + POSIX.1-2008 dello standard POSIX.} il cui prototipo è: \begin{prototype}{stdio.h}{char *tmpnam(char *string)} - Restituisce il puntatore ad una stringa contente un nome di file valido e - non esistente al momento dell'invocazione. - + Genera un nome univoco per un file temporaneo. + \bodydesc{La funzione ritorna il puntatore alla stringa con il nome o \val{NULL} in caso di fallimento. Non sono definiti errori.} \end{prototype} -\noindent se si è passato un puntatore \param{string} non nullo questo deve -essere di dimensione \const{L\_tmpnam} (costante definita in \file{stdio.h}, -come \const{P\_tmpdir} e \const{TMP\_MAX}) ed il nome generato vi verrà -copiato automaticamente; altrimenti il nome sarà generato in un buffer statico -interno che verrà sovrascritto ad una chiamata successiva. Successive + +La funzione restituisce il puntatore ad una stringa contente un nome di file +valido e non esistente al momento dell'invocazione; se si è passato come +argomento \param{string} un puntatore non nullo ad un buffer di caratteri +questo deve essere di dimensione \const{L\_tmpnam} ed il nome generato vi +verrà copiato automaticamente; altrimenti il nome sarà generato in un buffer +statico interno che verrà sovrascritto ad una chiamata successiva. Successive invocazioni della funzione continueranno a restituire nomi unici fino ad un -massimo di \const{TMP\_MAX} volte. Al nome viene automaticamente aggiunto come -prefisso la directory specificata da \const{P\_tmpdir}. +massimo di \const{TMP\_MAX} volte, limite oltre il quale il comportamento è +indefinito. Al nome viene automaticamente aggiunto come prefisso la directory +specificata dalla costante \const{P\_tmpdir}.\footnote{le costanti + \const{L\_tmpnam}, \const{P\_tmpdir} e \const{TMP\_MAX} sono definite in + \file{stdio.h}.} Di questa funzione esiste una versione \index{funzioni!rientranti} rientrante, \func{tmpnam\_r}, che non fa nulla quando si passa \val{NULL} come argomento. Una funzione simile, \funcd{tempnam}, permette di specificare un prefisso per il file esplicitamente, il suo prototipo è: \begin{prototype}{stdio.h}{char *tempnam(const char *dir, const char *pfx)} - Restituisce il puntatore ad una stringa contente un nome di file valido e - non esistente al momento dell'invocazione. + Genera un nome univoco per un file temporaneo. \bodydesc{La funzione ritorna il puntatore alla stringa con il nome o \val{NULL} in caso di fallimento, \var{errno} viene impostata a @@ -1416,16 +1422,16 @@ La funzione alloca con \code{malloc} la stringa in cui restituisce il nome, per cui è sempre \index{funzioni!rientranti} rientrante, occorre però ricordarsi di disallocare con \code{free} il puntatore che restituisce. L'argomento \param{pfx} specifica un prefisso di massimo 5 caratteri per il -nome provvisorio. La funzione assegna come directory per il file temporaneo -(verificando che esista e sia accessibili), la prima valida delle seguenti: -\begin{itemize} +nome provvisorio. La funzione assegna come directory per il file temporaneo, +verificando che esista e sia accessibile, la prima valida fra le seguenti: +\begin{itemize*} \item La variabile di ambiente \const{TMPDIR} (non ha effetto se non è definita o se il programma chiamante è \itindex{suid~bit} \acr{suid} o \itindex{sgid~bit} \acr{sgid}, vedi sez.~\ref{sec:file_special_perm}). \item il valore dell'argomento \param{dir} (se diverso da \val{NULL}). \item Il valore della costante \const{P\_tmpdir}. \item la directory \file{/tmp}. -\end{itemize} +\end{itemize*} In ogni caso, anche se la generazione del nome è casuale, ed è molto difficile ottenere un nome duplicato, nulla assicura che un altro processo non possa @@ -1439,7 +1445,7 @@ esistente. Per evitare di dovere effettuare a mano tutti questi controlli, lo standard POSIX definisce la funzione \funcd{tmpfile}, che permette di ottenere in maniera sicura l'accesso ad un file temporaneo, il suo prototipo è: -\begin{prototype}{stdio.h}{FILE *tmpfile (void)} +\begin{prototype}{stdio.h}{FILE *tmpfile(void)} Restituisce un file temporaneo aperto in lettura/scrittura. \bodydesc{La funzione ritorna il puntatore allo stream associato al file @@ -1468,8 +1474,7 @@ conclusa da 6 caratteri \code{X} che verranno sostituiti da un codice unico. La prima delle due è analoga a \func{tmpnam} e genera un nome casuale, il suo prototipo è: \begin{prototype}{stlib.h}{char *mktemp(char *template)} - Genera un filename univoco sostituendo le \code{XXXXXX} finali di - \param{template}. + Genera un nome univoco per un file temporaneo. \bodydesc{La funzione ritorna il puntatore \param{template} in caso di successo e \val{NULL} in caso di errore, nel qual caso \var{errno} @@ -1478,7 +1483,9 @@ il suo prototipo è: \item[\errcode{EINVAL}] \param{template} non termina con \code{XXXXXX}. \end{errlist}} \end{prototype} -\noindent dato che \param{template} deve poter essere modificata dalla + +La funzionane genera un nome univoco sostituendo le \code{XXXXXX} finali di +\param{template}; dato che \param{template} deve poter essere modificata dalla funzione non si può usare una stringa costante. Tutte le avvertenze riguardo alle possibili \itindex{race~condition} \textit{race condition} date per \func{tmpnam} continuano a valere; inoltre in alcune vecchie implementazioni @@ -1489,13 +1496,12 @@ Per tutti questi motivi la funzione è deprecata e non dovrebbe mai essere usata. La seconda funzione, \funcd{mkstemp} è sostanzialmente equivalente a -\func{tmpfile}, ma restituisce un file descriptor invece di uno stream; il suo +\func{tmpfile}, ma restituisce un file descriptor invece di un nome; il suo prototipo è: \begin{prototype}{stlib.h}{int mkstemp(char *template)} - Genera un file temporaneo con un nome ottenuto sostituendo le \code{XXXXXX} - finali di \param{template}. + Genera un file temporaneo. - \bodydesc{La funzione ritorna il file descriptor in caso successo e + \bodydesc{La funzione ritorna il file descriptor in caso di successo e -1 in caso di errore, nel qual caso \var{errno} assumerà i valori: \begin{errlist} \item[\errcode{EINVAL}] \param{template} non termina con \code{XXXXXX}. @@ -1503,22 +1509,38 @@ prototipo è: contenuto di \param{template} è indefinito. \end{errlist}} \end{prototype} -\noindent come per \func{mktemp} anche in questo caso \param{template} non può -essere una stringa costante. La funzione apre un file in lettura/scrittura con -la funzione \func{open}, usando l'opzione \const{O\_EXCL} (si veda + +Come per \func{mktemp} anche in questo caso \param{template} non può essere +una stringa costante. La funzione apre un file in lettura/scrittura con la +funzione \func{open}, usando l'opzione \const{O\_EXCL} (si veda sez.~\ref{sec:file_open}), in questo modo al ritorno della funzione si ha la -certezza di essere i soli utenti del file. I permessi sono impostati al valore -\code{0600}\footnote{questo è vero a partire dalle \acr{glibc} 2.0.7, le - versioni precedenti delle \acr{glibc} e le vecchie \acr{libc5} e \acr{libc4} - usavano il valore \code{0666} che permetteva a chiunque di leggere i - contenuti del file.} (si veda sez.~\ref{sec:file_perm_overview}). - -In OpenBSD è stata introdotta un'altra funzione\footnote{introdotta anche in - Linux a partire dalle \acr{glibc} 2.1.91.} simile alle precedenti, -\funcd{mkdtemp}, che crea una directory temporanea; il suo prototipo è: +certezza di essere stati i creatori del file, i cui permessi (si veda +sez.~\ref{sec:file_perm_overview}) sono impostati al valore \code{0600} +(lettura e scrittura solo per il proprietario).\footnote{questo è vero a + partire dalle \acr{glibc} 2.0.7, le versioni precedenti delle \acr{glibc} e + le vecchie \acr{libc5} e \acr{libc4} usavano il valore \code{0666} che + permetteva a chiunque di leggere e scrivere i contenuti del file.} Di +questa funzione esiste una variante \funcd{mkostemp}, introdotta +specificamente dalla \acr{glibc},\footnote{la funzione è stata introdotta + nella versione 2.7 delle librerie e richiede che sia definita la macro + \const{\_GNU\_SOURCE}.} il cui prototipo è: +\begin{prototype}{stlib.h}{int mkostemp(char *template, int flags)} + Genera un file temporaneo. + + \bodydesc{La funzione ritorna il file descriptor in caso di successo e + -1 in caso di errore, con gli stessi errori di \func{mkstemp}.} +\end{prototype} +\noindent la cui sola differenza è la presenza dell'ulteriore argomento +\var{flags} che consente di specificare i flag da passare ad \func{open} +nell'apertura del file. + + +In OpenBSD è stata introdotta un'altra funzione simile alle precedenti, +\funcd{mkdtemp}, che crea invece una directory temporanea;\footnote{la + funzione è stata introdotta nelle \acr{glibc} a partire dalla versione + 2.1.91 ed inserita nello standard POSIX.1-2008.} il suo prototipo è: \begin{prototype}{stlib.h}{char *mkdtemp(char *template)} - Genera una directory temporaneo il cui nome è ottenuto sostituendo le - \code{XXXXXX} finali di \param{template}. + Genera una directory temporanea. \bodydesc{La funzione ritorna il puntatore al nome della directory in caso successo e \val{NULL} in caso di errore, nel qual caso \var{errno} @@ -1528,9 +1550,11 @@ In OpenBSD è stata introdotta un'altra funzione\footnote{introdotta anche in \end{errlist} più gli altri eventuali codici di errore di \func{mkdir}.} \end{prototype} -\noindent la directory è creata con permessi \code{0700} (al solito si veda -cap.~\ref{cha:file_unix_interface} per i dettagli); dato che la creazione -della directory è sempre esclusiva i precedenti problemi di + +La funzione genera una directory il cui nome è ottenuto sostituendo le +\code{XXXXXX} finali di \param{template} con permessi \code{0700} (al solito +si veda cap.~\ref{cha:file_unix_interface} per i dettagli); dato che la +creazione della directory è sempre esclusiva i precedenti problemi di \itindex{race~condition} \textit{race condition} non si pongono. @@ -1554,34 +1578,32 @@ sez.~\ref{sec:file_access_control}). \label{sec:file_stat} La lettura delle informazioni relative ai file è fatta attraverso la famiglia -delle funzioni \func{stat} (\funcd{stat}, \funcd{fstat} e \funcd{lstat}); -questa è la funzione che ad esempio usa il comando \cmd{ls} per poter ottenere -e mostrare tutti i dati relativi ad un file. I prototipi di queste funzioni -sono i seguenti: +delle funzioni \func{stat} che sono quelle che usa il comando \cmd{ls} per +poter ottenere e mostrare tutti i dati relativi ad un file; ne fanno parte le +funzioni \funcd{stat}, \funcd{fstat} e \funcd{lstat}, i cui prototipi sono: \begin{functions} \headdecl{sys/types.h} \headdecl{sys/stat.h} \headdecl{unistd.h} - \funcdecl{int stat(const char *file\_name, struct stat *buf)} Legge le - informazione del file specificato da \param{file\_name} e le inserisce in - \param{buf}. - - \funcdecl{int lstat(const char *file\_name, struct stat *buf)} Identica a - \func{stat} eccetto che se il \param{file\_name} è un link simbolico vengono - lette le informazioni relative ad esso e non al file a cui fa riferimento. - - \funcdecl{int fstat(int filedes, struct stat *buf)} Identica a \func{stat} - eccetto che si usa con un file aperto, specificato tramite il suo file - descriptor \param{filedes}. - + \funcdecl{int stat(const char *file\_name, struct stat *buf)} + \funcdecl{int lstat(const char *file\_name, struct stat *buf)} + \funcdecl{int fstat(int filedes, struct stat *buf)} + Legge le informazioni di un file. + \bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 per un errore, nel qual caso \var{errno} assumerà uno dei valori: \errval{EBADF}, \errval{ENOENT}, \errval{ENOTDIR}, \errval{ELOOP}, \errval{EFAULT}, \errval{EACCES}, \errval{ENOMEM}, \errval{ENAMETOOLONG}.} \end{functions} -\noindent il loro comportamento è identico, solo che operano rispettivamente -su un file, su un link simbolico e su un file descriptor. + +La funzione \func{stat} legge le informazioni del file il cui pathname è +specificato dalla stringa puntata da \param{file\_name} e le inserisce nel +buffer puntato dall'argomento \param{buf}; la funzione \func{lstat} è identica +a \func{stat} eccetto che se \param{file\_name} è un link simbolico vengono +lette le informazioni relative ad esso e non al file a cui fa +riferimento. Infine \func{fstat} esegue la stessa operazione su un file già +aperto, specificato tramite il suo file descriptor \param{filedes}. La struttura \struct{stat} usata da queste funzioni è definita nell'header \file{sys/stat.h} e in generale dipende dall'implementazione; la versione @@ -1594,7 +1616,7 @@ sez.~\ref{sec:file_file_times}), o per il padding dei campi. \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{15cm} + \begin{minipage}[c]{\textwidth} \includestruct{listati/stat.h} \end{minipage} \normalsize @@ -1723,9 +1745,9 @@ Si tenga conto che la lunghezza del file riportata in \var{st\_size} non è detto che corrisponda all'occupazione dello spazio su disco per via della possibile esistenza dei cosiddetti \index{file!\textit{hole}} \textit{holes} (letteralmente \textsl{buchi}) che si formano tutte le volte che si va a -scrivere su un \itindex{sparse~file} file dopo aver eseguito una \func{lseek} -(tratteremo in dettaglio l'argomento in sez.~\ref{sec:file_lseek}) oltre la -sua fine. +scrivere su un \itindex{sparse~file} file dopo aver eseguito uno spostamento +oltre la sua fine (tratteremo in dettaglio l'argomento in +sez.~\ref{sec:file_lseek}). In questo caso si avranno risultati differenti a seconda del modo in cui si calcola la lunghezza del file, ad esempio il comando \cmd{du}, (che riporta il @@ -1744,14 +1766,14 @@ Un file può sempre essere troncato a zero aprendolo con il flag dimensione si possono usare le due funzioni \funcd{truncate} e \funcd{ftruncate}, i cui prototipi sono: \begin{functions} - \headdecl{unistd.h} \funcdecl{int truncate(const char *file\_name, off\_t - length)} Fa si che la dimensione del file \param{file\_name} sia troncata - ad un valore massimo specificato da \param{length}. - - \funcdecl{int ftruncate(int fd, off\_t length))} Identica a \func{truncate} - eccetto che si usa con un file aperto, specificato tramite il suo file - descriptor \param{fd}. - + \headdecl{unistd.h} + + \funcdecl{int truncate(const char *file\_name, off\_t length)} + + \funcdecl{int ftruncate(int fd, off\_t length))} + + Troncano un file alla lunghezza \param{length}. + \bodydesc{Le funzioni restituiscono zero in caso di successo e -1 per un errore, nel qual caso \var{errno} viene impostata opportunamente; per \func{ftruncate} si hanno i valori: @@ -1771,20 +1793,28 @@ dimensione si possono usare le due funzioni \funcd{truncate} e \errval{EROFS}, \errval{EIO}, \errval{EFAULT}, \errval{ELOOP}.} \end{functions} -Se il file è più lungo della lunghezza specificata i dati in eccesso saranno -perduti; il comportamento in caso di lunghezza inferiore non è specificato e -dipende dall'implementazione: il file può essere lasciato invariato o esteso -fino alla lunghezza scelta; nel caso di Linux viene esteso con la creazione di -un \index{file!\textit{hole}} \textsl{buco} nel \itindex{sparse~file} file e -ad una lettura si otterranno degli zeri. +Entrambe le funzioni fan sì che la dimensione del file sia troncata ad un +valore massimo specificato da \param{length}, e si distinguono solo per il +fatto che il file viene indicato con il pathname \param{file\_name} per +\func{truncate} e con il file descriptor \param{fd} per \funcd{ftruncate}; se +il file è più lungo della lunghezza specificata i dati in eccesso saranno +perduti. + +Il comportamento in caso di lunghezza inferiore non è specificato e dipende +dall'implementazione: il file può essere lasciato invariato o esteso fino alla +lunghezza scelta; nel caso di Linux viene esteso con la creazione di un +\index{file!\textit{hole}} \textsl{buco} nel \itindex{sparse~file} file e ad +una lettura si otterranno degli zeri; si tenga presente però che questo +comportamento è supportato solo per filesystem nativi, ad esempio su un +filesystem non nativo come il VFAT di Windows questo non è possibile. \subsection{I tempi dei file} \label{sec:file_file_times} -Il sistema mantiene per ciascun file tre tempi. Questi sono registrati +Il sistema mantiene per ciascun file tre tempi, questi sono registrati \itindex{inode} nell'\textit{inode} insieme agli altri attributi del file e possono essere letti tramite la funzione \func{stat}, che li restituisce -attraverso tre campi della struttura \struct{stat} di +attraverso tre specifici campi della struttura \struct{stat} di fig.~\ref{fig:file_stat_struct}. Il significato di detti tempi e dei relativi campi è riportato nello schema in tab.~\ref{tab:file_file_times}, dove è anche riportato un esempio delle funzioni che effettuano cambiamenti su di essi. Il @@ -1813,14 +1843,14 @@ valore è espresso nel cosiddetto \itindex{calendar~time} \textit{calendar \end{table} Il primo punto da tenere presente è la differenza fra il cosiddetto tempo di -modifica (il \textit{modification time}, \var{st\_mtime}) e il tempo di -cambiamento di stato (il \textit{change time}, \var{st\_ctime}). Il primo -infatti fa riferimento ad una modifica del contenuto di un file, mentre il -secondo ad una modifica \itindex{inode} dell'\textit{inode}; siccome esistono -molte operazioni (come la funzione \func{link} e molte altre che vedremo in -seguito) che modificano solo le informazioni contenute \itindex{inode} +ultima modifica (il \textit{modification time}, \var{st\_mtime}) e il tempo di +ultimo cambiamento di stato (il \textit{change time}, \var{st\_ctime}). Il +primo infatti fa riferimento ad una modifica del contenuto di un file, mentre +il secondo ad una modifica \itindex{inode} dell'\textit{inode}. Dato che +esistono molte operazioni, come la funzione \func{link} e altre che vedremo in +seguito, che modificano solo le informazioni contenute \itindex{inode} nell'\textit{inode} senza toccare il contenuto del file, diventa necessario -l'utilizzo di un altro tempo. +l'utilizzo di questo secondo tempo. Il tempo di ultima modifica viene usato ad esempio da programmi come \cmd{make} per decidere quali file necessitano di essere ricompilati o @@ -1859,14 +1889,6 @@ kernel 2.6.30, è diventata il comportamento di default e non deve più essere specificata esplicitamente.\footnote{si può comunque riottenere il vecchio comportamento usando la opzione di montaggio \texttt{strictatime}.} -L'effetto delle varie funzioni di manipolazione dei file sui relativi tempi è -illustrato in tab.~\ref{tab:file_times_effects}, facendo riferimento al -comportamento classico per quanto riguarda \var{st\_atime}. Si sono riportati -gli effetti sia per il file a cui si fa riferimento, sia per la directory che -lo contiene; questi ultimi possono essere capiti se si tiene conto di quanto -già detto, e cioè che anche le directory sono file (che contengono una lista -di nomi) che il sistema tratta in maniera del tutto analoga a tutti gli altri. - \begin{table}[htb] \centering \footnotesize @@ -1947,12 +1969,22 @@ di nomi) che il sistema tratta in maniera del tutto analoga a tutti gli altri. \label{tab:file_times_effects} \end{table} + +L'effetto delle varie funzioni di manipolazione dei file sui relativi tempi è +illustrato in tab.~\ref{tab:file_times_effects}, facendo riferimento al +comportamento classico per quanto riguarda \var{st\_atime}. Si sono riportati +gli effetti sia per il file a cui si fa riferimento, sia per la directory che +lo contiene; questi ultimi possono essere capiti se si tiene conto di quanto +già detto, e cioè che anche le directory sono anch'esse file che contengono +una lista di nomi, che il sistema tratta in maniera del tutto analoga a tutti +gli altri. + Per questo motivo tutte le volte che compiremo un'operazione su un file che comporta una modifica del nome contenuto nella directory, andremo anche a scrivere sulla directory che lo contiene cambiandone il tempo di modifica. Un -esempio di questo può essere la cancellazione di un file, invece leggere o -scrivere o cambiare i permessi di un file ha effetti solo sui tempi di -quest'ultimo. +esempio di questo tipo di operazione può essere la cancellazione di un file, +invece leggere o scrivere o cambiare i permessi di un file ha effetti solo sui +tempi di quest'ultimo. Si noti infine come \var{st\_ctime} non abbia nulla a che fare con il tempo di creazione del file, usato in molti altri sistemi operativi, ma che in Unix non @@ -1964,11 +1996,7 @@ I tempi di ultimo accesso e modifica possono essere modificati esplicitamente usando la funzione \funcd{utime}, il cui prototipo è: \begin{prototype}{utime.h} {int utime(const char *filename, struct utimbuf *times)} - - Cambia i tempi di ultimo accesso e modifica \itindex{inode} - dell'\textit{inode} specificato da \param{filename} secondo i valori dei - campi \var{actime} e \var{modtime} di \param{times}. Se questa è \val{NULL} - allora viene usato il tempo corrente. + Modifica i tempi di ultimo accesso e modifica di un file. \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: @@ -1979,14 +2007,16 @@ usando la funzione \funcd{utime}, il cui prototipo è: ed inoltre \errval{EROFS} e \errval{ENOENT}.} \end{prototype} -La funzione prende come argomento \param{times} una struttura -\struct{utimbuf}, la cui definizione è riportata in -fig.~\ref{fig:struct_utimebuf}, con la quale si possono specificare i nuovi -valori che si vogliono impostare per tempi. +La funzione cambia i tempi di ultimo accesso e modifica del file specificato +dall'argomento \param{filename}, e richiede come secondo argomento il +puntatore ad una struttura \struct{utimbuf}, la cui definizione è riportata in +fig.~\ref{fig:struct_utimebuf}, con i nuovi valori di detti tempi +(rispettivamente nei campi \var{actime} e \var{modtime}). Se si passa un +puntatore nullo verrà impostato il tempo corrente. \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{15cm} + \begin{minipage}[c]{\textwidth} \includestruct{listati/utimbuf.h} \end{minipage} \normalsize @@ -1999,17 +2029,17 @@ L'effetto della funzione e i privilegi necessari per eseguirla dipendono da cosa è l'argomento \param{times}; se è \val{NULL} la funzione imposta il tempo corrente ed è sufficiente avere accesso in scrittura al file; se invece si è specificato un valore la funzione avrà successo solo se si è proprietari -del file (o si hanno i privilegi di amministratore). +del file o si hanno i privilegi di amministratore. Si tenga presente che non è comunque possibile specificare il tempo di -cambiamento di stato del file, che viene comunque cambiato dal kernel tutte le -volte che si modifica \itindex{inode} l'\textit{inode} (quindi anche alla -chiamata di \func{utime}). Questo serve anche come misura di sicurezza per -evitare che si possa modificare un file nascondendo completamente le proprie -tracce. In realtà la cosa resta possibile, se si è in grado di accedere al -\index{file!di~dispositivo} file di dispositivo, scrivendo direttamente sul +cambiamento di stato del file, che viene aggiornato direttamente dal kernel +tutte le volte che si modifica \itindex{inode} l'\textit{inode} (quindi anche +alla chiamata di \func{utime}). Questo serve anche come misura di sicurezza +per evitare che si possa modificare un file nascondendo completamente le +proprie tracce. In realtà la cosa resta possibile se si è in grado di accedere +al \index{file!di~dispositivo} file di dispositivo, scrivendo direttamente sul disco senza passare attraverso il filesystem, ma ovviamente in questo modo la -cosa è molto più complicata da realizzare. +cosa è più complicata da realizzare. A partire dal kernel 2.6 la risoluzione dei tempi dei file, che nei campi di tab.~\ref{tab:file_file_times} è espressa in secondi, è stata portata ai @@ -2028,11 +2058,7 @@ precisione; il suo prototipo è: \begin{prototype} {sys/time.h} {int utimes(const char *filename, struct timeval times[2])} - - Cambia i tempi di ultimo accesso e modifica \itindex{inode} - dell'\textit{inode} specificato da \param{filename} secondo i valori - specificati da \param{times}. Se questo è \val{NULL} allora viene usato il - tempo corrente. + Modifica i tempi di ultimo accesso e modifica di un file. \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: @@ -2044,15 +2070,16 @@ precisione; il suo prototipo è: \end{prototype} La funzione è del tutto analoga alla precedente \func{utime} ma usa come -argomento \param{times}, un vettore di due strutture \struct{timeval}, la cui +secondo argomento un vettore di due strutture \struct{timeval}, la cui definizione è riportata in fig.~\ref{fig:sys_timeval_struct}, che consentono di indicare i tempi con una precisione del microsecondo. Il primo elemento di \param{times} indica il valore per il tempo di ultimo accesso, il secondo -quello per il tempo di ultima modifica. +quello per il tempo di ultima modifica. Se si indica come secondo argomento un +puntatore nullo di nuovo verrà utilizzato il tempo corrente. \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{15cm} + \begin{minipage}[c]{\textwidth} \includestruct{listati/timeval.h} \end{minipage} \normalsize @@ -2089,10 +2116,9 @@ prototipi sono: Le due funzioni anno lo stesso comportamento di \texttt{utimes} e richiedono gli stessi privilegi per poter operare, la differenza è che con \func{futimes} si può indicare il file su cui operare facendo riferimento al relativo file -descriptor (tratteremo in dettaglio l'argomento in -sez.~\ref{cha:file_unix_interface}) mentre con \func{lutimes} nel caso in -cui \param{filename} sia un link simbolico saranno modificati i suoi tempi -invece di quelli del file a cui esso punta. +descriptor mentre con \func{lutimes} nel caso in cui \param{filename} sia un +link simbolico saranno modificati i suoi tempi invece di quelli del file a cui +esso punta. Nonostante il kernel, come accennato, supporti risoluzioni dei tempi dei file fino al nanosecondo, le funzioni fin qui esaminate non consentono di impostare @@ -2125,7 +2151,7 @@ definizione è riportata in fig.~\ref{fig:sys_timespec_struct}. \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{15cm} + \begin{minipage}[c]{\textwidth} \includestruct{listati/timespec.h} \end{minipage} \normalsize @@ -2136,7 +2162,7 @@ definizione è riportata in fig.~\ref{fig:sys_timespec_struct}. Come per le precedenti funzioni il primo elemento di \param{times} indica il tempo di ultimo accesso ed il secondo quello di ultima modifica, e se si usa -il valore \const{NULL} verrà impostato il tempo corrente sia per l'ultimo +il valore \val{NULL} verrà impostato il tempo corrente sia per l'ultimo accesso che per l'ultima modifica. Nei singoli elementi di \param{times} si possono inoltre utilizzare due valori speciali per il campo \var{tv\_nsec}: con \const{UTIME\_NOW} si richiede l'uso del tempo corrente, mentre con @@ -2156,13 +2182,13 @@ kernel 2.6.22, e supportate dalle \acr{glibc} a partire dalla versione sostanzialmente una estensione di \func{futimes} che consente di specificare i tempi con precisione maggiore, la seconda supporta invece, rispetto ad \func{utimes}, una sintassi più complessa che, come vedremo in -sez.~\ref{sec:file_openat},\footnote{si rimanda pertanto la spiegazione del - significato degli argomenti aggiuntivi alla trattazione generica delle varie - funzioni che usano la stessa sintassi, effettuata in - sez.~\ref{sec:file_openat}.} consente una indicazione sicura dei +sez.~\ref{sec:file_openat} consente una indicazione sicura dei \textit{pathname relativi} specificando la directory da usare come riferimento in \param{dirfd} e la possibilità di usare \param{flags} per indicare alla -funzione di dereferenziare o meno i link simbolici. +funzione di dereferenziare o meno i link simbolici; si rimanda pertanto la +spiegazione del significato degli argomenti aggiuntivi alla trattazione +generica delle varie funzioni che usano la stessa sintassi, effettuata in +sez.~\ref{sec:file_openat}. \section{Il controllo di accesso ai file} @@ -2683,16 +2709,16 @@ in particolare accade che: \end{enumerate} Per alcuni filesystem\footnote{i filesystem più comuni (\textsl{ext2}, - \textsl{ext3}, \textsl{reiserfs}) supportano questa caratteristica, che è - mutuata da BSD.} è inoltre prevista un'ulteriore misura di sicurezza, volta -a scongiurare l'abuso dei \itindex{suid~bit} bit \acr{suid} e \acr{sgid}; essa -consiste nel cancellare automaticamente questi bit dai permessi di un file -qualora un processo che non appartenga all'amministratore\footnote{per la - precisione un processo che non dispone della \itindex{capabilities} capacità - \const{CAP\_FSETID}, vedi sez.~\ref{sec:proc_capabilities}.} effettui una -scrittura. In questo modo anche se un utente malizioso scopre un file -\acr{suid} su cui può scrivere, un'eventuale modifica comporterà la perdita di -questo privilegio. + \textsl{ext3}, \textsl{ext4}, \textsl{ReiserFS}) supportano questa + caratteristica, che è mutuata da BSD.} è inoltre prevista un'ulteriore +misura di sicurezza, volta a scongiurare l'abuso dei \itindex{suid~bit} bit +\acr{suid} e \acr{sgid}; essa consiste nel cancellare automaticamente questi +bit dai permessi di un file qualora un processo che non appartenga +all'amministratore\footnote{per la precisione un processo che non dispone + della \itindex{capabilities} capacità \const{CAP\_FSETID}, vedi + sez.~\ref{sec:proc_capabilities}.} effettui una scrittura. In questo modo +anche se un utente malizioso scopre un file \acr{suid} su cui può scrivere, +un'eventuale modifica comporterà la perdita di questo privilegio. Le funzioni \func{chmod} e \func{fchmod} ci permettono di modificare i permessi di un file, resta però il problema di quali sono i permessi assegnati @@ -2951,1224 +2977,931 @@ dell'interfaccia classica dei sistemi unix-like, principalmente utilizzate a scopi di sicurezza, che sono state introdotte nelle versioni più recenti di Linux. +\subsection{Gli attributi estesi} +\label{sec:file_xattr} -\subsection{La gestione delle \textit{capabilities}} -\label{sec:proc_capabilities} - -\itindbeg{capabilities} - -Come accennato in sez.~\ref{sec:proc_access_id} l'architettura classica della -gestione dei privilegi in un sistema unix-like ha il sostanziale problema di -fornire all'amministratore dei poteri troppo ampi, questo comporta che anche -quando si siano predisposte delle misure di protezione per in essere in grado -di difendersi dagli effetti di una eventuale compromissione del -sistema,\footnote{come montare un filesystem in sola lettura per impedirne - modifiche, o marcare un file come immutabile.} una volta che questa sia -stata effettuata e si siano ottenuti i privilegi di amministratore, queste -potranno essere comunque rimosse.\footnote{nei casi elencati nella precedente - nota si potrà sempre rimontare il sistema in lettura-scrittura, o togliere - la marcatura di immutabilità.} - -Il problema consiste nel fatto che nell'architettura tradizionale di un -sistema unix-like i controlli di accesso sono basati su un solo livello di -separazione: per i processi normali essi sono posti in atto, mentre per i -processi con i privilegi di amministratore essi non vengono neppure eseguiti; -per questo motivo non era previsto alcun modo per evitare che un processo con -diritti di amministratore non potesse eseguire certe operazioni, o per cedere -definitivamente alcuni privilegi da un certo momento in poi. - -Per ovviare a tutto ciò, a partire dai kernel della serie 2.2, è stato -introdotto un meccanismo, detto \textit{capabilities}, che consentisse di -suddividere i vari privilegi tradizionalmente associati all'amministratore in -un insieme di \textsl{capacità} distinte. L'idea era che queste capacità -potessero essere abilitate e disabilitate in maniera indipendente per ciascun -processo con privilegi di amministratore, permettendo così una granularità -molto più fine nella distribuzione degli stessi che evitasse la originaria -situazione di ``\textsl{tutto o nulla}''. - -Il meccanismo completo delle \textit{capabilities}\footnote{l'implementazione - si rifà ad una bozza di quello che doveva diventare lo standard POSIX.1e, - poi abbandonato.} prevede inoltre la possibilità di associare le stesse ai -singoli file eseguibili, in modo da poter stabilire quali capacità possono -essere utilizzate quando viene messo in esecuzione uno specifico programma; ma -il supporto per questa funzionalità è stato introdotto soltanto a partire dal -kernel 2.6.24; fino ad allora doveva essere il programma stesso ad eseguire -una riduzione esplicita delle sue capacità, cosa che ha reso l'uso di questa -funzionalità poco diffuso, vista la presenza di meccanismi alternativi come -\index{SELinux} SELinux. - -Per gestire questo meccanismo ciascun processo porta con sé tre distinti -insiemi di \textit{capabilities}, che vengono denominati rispettivamente -\textit{effective}, \textit{permitted} ed \textit{inherited}. Questi insiemi -vengono mantenuti in forma di tre diverse maschere binarie,\footnote{il kernel - li mantiene, come i vari identificatori di sez.~\ref{sec:proc_setuid}, - all'interno della \struct{task\_struct} di ciascun processo (vedi - fig.~\ref{fig:proc_task_struct}), nei tre campi \texttt{cap\_effective}, - \texttt{cap\_inheritable}, \texttt{cap\_permitted} del tipo - \texttt{kernel\_cap\_t}; questo è attualmente definito come intero a 32 bit, - il che comporta un massimo di 32 \textit{capabilities} distinte.} in cui -ciascun bit corrisponde ad una capacità diversa. - -L'utilizzo di tre distinti insiemi serve a fornire una interfaccia flessibile -per l'uso delle \textit{capabilities}, con scopi analoghi a quelli per cui -sono mantenuti i diversi insiemi di identificatori di -sez.~\ref{sec:proc_setuid}; il loro significato è il seguente: -\begin{basedescript}{\desclabelwidth{2.0cm}\desclabelstyle{\nextlinelabel}} -\item[\textit{effective}] l'insieme delle \textit{capabilities} - ``\textsl{effettive}'', cioè di quelle che vengono effettivamente usate dal - kernel quando deve eseguire il controllo di accesso per le varie operazioni - compiute dal processo. -\item[\textit{permitted}] l'insieme delle \textit{capabilities} - ``\textsl{permesse}'', cioè l'insieme di quelle capacità che un processo - \textsl{può} impostare come \textsl{effettive}. Se un processo cancella una - capacità da questo insieme non potrà più riassumerla (almeno che non esegua - un programma che è \acr{suid} di root). -\item[\textit{inherited}] l'insieme delle \textit{capabilities} - ``\textsl{ereditabili}'', cioè quelle che vengono trasmesse ad un nuovo - programma eseguito attraverso una chiamata ad \func{exec} (con l'eccezione - del caso che questo sia \acr{suid} di root). -\label{sec:capabilities_set} -\end{basedescript} +\itindbeg{Extended~Attributes} -Oltre a questi tre insiemi, che sono relativi al singolo processo, il kernel -mantiene un insieme generale valido per tutto il sistema, chiamato -\itindex{capabilities~bounding~set} \textit{capabilities bounding set}. Ogni -volta che un programma viene posto in esecuzione con \func{exec} il contenuto -degli insiemi \textit{effective} e \textit{permitted} vengono mascherati con -un \textsl{AND} binario del contenuto corrente del \textit{capabilities - bounding set}, così che il nuovo processo potrà disporre soltanto delle -capacità in esso elencate. - -Il \textit{capabilities bounding set} è un parametro di sistema, accessibile -attraverso il contenuto del file \procfile{/proc/sys/kernel/cap-bound}, che per -questa sua caratteristica consente di impostare un limite generale alle -capacità che possono essere accordate ai vari processi. Questo valore può -essere impostato ad un valore arbitrario esclusivamente dal primo processo -eseguito nel sistema (di norma cioè da \texttt{/sbin/init}), ogni processo -eseguito successivamente (cioè con \textsl{pid} diverso da 1) anche se -eseguito con privilegi di amministratore potrà soltanto rimuovere uno dei bit -già presenti dell'insieme: questo significa che una volta rimossa una -\textit{capability} dal \textit{capabilities bounding set} essa non sarà più -disponibile, neanche per l'amministratore, a meno di un riavvio. - -Quando un programma viene messo in esecuzione\footnote{cioè quando viene - eseguita la \func{execve} con cui lo si lancia; in corrispondenza di una - \func{fork} le \textit{capabilities} non vengono modificate.} esso eredita -(nel senso che assume negli insiemi \textit{effective} e \textit{permitted}) -le \textit{capabilities} mantenute nell'insieme \textit{inherited}, a meno che -non sia eseguito un programma \acr{suid} di root o la \func{exec} sia stata -eseguita da un programma con \textsl{uid} reale zero; in tal caso il programma -ottiene tutte le \textit{capabilities} presenti nel \textit{capabilities - bounding set}. In questo modo si può far si che ad un processo eseguito in -un secondo tempo possano essere trasmesse solo un insieme limitato di -capacità, impedendogli di recuperare quelle assenti nell'insieme -\textit{inherited}. Si tenga presente invece che attraverso una \func{fork} -vengono mantenute le stesse capacità del processo padre. +Nelle sezioni precedenti abbiamo trattato in dettaglio le varie informazioni +che il sistema mantiene negli \itindex{inode} \textit{inode}, e le varie +funzioni che permettono di modificarle. Si sarà notato come in realtà queste +informazioni siano estremamente ridotte. Questo è dovuto al fatto che Unix +origina negli anni '70, quando le risorse di calcolo e di spazio disco erano +minime. Con il venir meno di queste restrizioni è incominciata ad emergere +l'esigenza di poter associare ai file delle ulteriori informazioni astratte +(quelli che vengono chiamati i \textsl{meta-dati}) che però non potevano +trovare spazio nei dati classici mantenuti negli \itindex{inode} +\textit{inode}. +Per risolvere questo problema alcuni sistemi unix-like (e fra questi anche +Linux) hanno introdotto un meccanismo generico, detto \textit{Extended + Attributes} che consenta di associare delle informazioni ai singoli +file.\footnote{l'uso più comune è quello della ACL, che tratteremo nella + prossima sezione.} Gli \textsl{attributi estesi} non sono altro che delle +coppie nome/valore che sono associate permanentemente ad un oggetto sul +filesystem, analoghi di quello che sono le variabili di ambiente (vedi +sez.~\ref{sec:proc_environ}) per un processo. -% TODO verificare per process capability bounding set, vedi: -% http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=3b7391de67da515c91f48aa371de77cb6cc5c07e +Altri sistemi (come Solaris, MacOS e Windows) hanno adottato un meccanismo +diverso in cui ad un file sono associati diversi flussi di dati, su cui +possono essere mantenute ulteriori informazioni, che possono essere accedute +con le normali operazioni di lettura e scrittura. Questi non vanno confusi con +gli \textit{Extended Attributes} (anche se su Solaris hanno lo stesso nome), +che sono un meccanismo molto più semplice, che pur essendo limitato (potendo +contenere solo una quantità limitata di informazione) hanno il grande +vantaggio di essere molto più semplici da realizzare, più +efficienti,\footnote{cosa molto importante, specie per le applicazioni che + richiedono una gran numero di accessi, come le ACL.} e di garantire +l'atomicità di tutte le operazioni. -% TODO capire cosa cambia con i patch vari, vedi -% http://lwn.net/Articles/280279/ -% http://lwn.net/Articles/256519/ -% http://lwn.net/Articles/211883/ +In Linux gli attributi estesi sono sempre associati al singolo \itindex{inode} +\textit{inode} e l'accesso viene sempre eseguito in forma atomica, in lettura +il valore corrente viene scritto su un buffer in memoria, mentre la scrittura +prevede che ogni valore precedente sia sovrascritto. +Si tenga presente che non tutti i filesystem supportano gli \textit{Extended + Attributes}; al momento della scrittura di queste dispense essi sono +presenti solo sui vari \textsl{extN}, \textsl{ReiserFS}, \textsl{JFS}, +\textsl{XFS} e \textsl{Btrfs}.\footnote{l'elenco è aggiornato a Luglio 2011.} +Inoltre a seconda della implementazione ci possono essere dei limiti sulla +quantità di attributi che si possono utilizzare.\footnote{ad esempio nel caso + di \textsl{ext2} ed \textsl{ext3} è richiesto che essi siano contenuti + all'interno di un singolo blocco (pertanto con dimensioni massime pari a + 1024, 2048 o 4096 byte a seconda delle dimensioni di quest'ultimo impostate + in fase di creazione del filesystem), mentre con \textsl{XFS} non ci sono + limiti ed i dati vengono memorizzati in maniera diversa (nell'\textit{inode} + stesso, in un blocco a parte, o in una struttura ad albero dedicata) per + mantenerne la scalabilità.} Infine lo spazio utilizzato per mantenere gli +attributi estesi viene tenuto in conto per il calcolo delle quote di utente e +gruppo proprietari del file. -Un elenco delle delle \textit{capabilities} disponibili su Linux, con una -breve descrizione ed il nome delle costanti che le identificano, è riportato -in tab.~\ref{tab:proc_capabilities};\footnote{l'elenco presentato questa - tabella, ripreso dalla pagina di manuale (accessibile con \texttt{man - capabilities}) e dalle definizioni in \texttt{linux/capabilities.h}, è - aggiornato al kernel 2.6.26.} la tabella è divisa in due parti, la prima -riporta le \textit{capabilities} previste anche nella bozza dello standard -POSIX1.e, la seconda quelle specifiche di Linux. Come si può notare dalla -tabella alcune \textit{capabilities} attengono a singole funzionalità e sono -molto specializzate, mentre altre hanno un campo di applicazione molto vasto, -che è opportuno dettagliare maggiormente. +Come meccanismo per mantenere informazioni aggiuntive associate al singolo +file, gli \textit{Extended Attributes} possono avere usi anche molto diversi +fra loro. Per poterli distinguere allora sono stati suddivisi in +\textsl{classi}, a cui poter applicare requisiti diversi per l'accesso e la +gestione. Per questo motivo il nome di un attributo deve essere sempre +specificato nella forma \texttt{namespace.attribute}, dove \texttt{namespace} +fa riferimento alla classe a cui l'attributo appartiene, mentre +\texttt{attribute} è il nome ad esso assegnato. In tale forma il nome di un +attributo esteso deve essere univoco. Al momento\footnote{della scrittura di + questa sezione, kernel 2.6.23, ottobre 2007.} sono state definite le quattro +classi di attributi riportate in tab.~\ref{tab:extended_attribute_class}. -\begin{table}[!h!bt] +\begin{table}[htb] \centering \footnotesize \begin{tabular}{|l|p{12cm}|} \hline - \textbf{Capacità}&\textbf{Descrizione}\\ + \textbf{Nome} & \textbf{Descrizione} \\ \hline \hline -% -% POSIX-draft defined capabilities. -% - \const{CAP\_AUDIT\_WRITE}&La capacità di scrivere dati nel giornale di - auditing del kernel (dal kernel 2.6.11).\\ - \const{CAP\_AUDIT\_CONTROL}& La capacità di abilitare e disabilitare il - controllo dell'auditing (dal kernel 2.6.11).\\ - % TODO verificare questa roba dell'auditing - \const{CAP\_CHOWN} & La capacità di cambiare proprietario e gruppo - proprietario di un file (vedi - sez.~\ref{sec:file_ownership_management}).\\ - \const{CAP\_DAC\_OVERRIDE}& La capacità di evitare il controllo dei - permessi di lettura, scrittura ed esecuzione dei - file,\footnotemark (vedi - sez.~\ref{sec:file_access_control}).\\ - \const{CAP\_DAC\_READ\_SEARCH}& La capacità di evitare il controllo dei - permessi di lettura ed esecuzione per - le directory (vedi - sez.~\ref{sec:file_access_control}).\\ - \const{CAP\_FOWNER} & La capacità di evitare il controllo della - proprietà di un file per tutte - le operazioni privilegiate non coperte dalle - precedenti \const{CAP\_DAC\_OVERRIDE} e - \const{CAP\_DAC\_READ\_SEARCH}.\\ - \const{CAP\_FSETID} & La capacità di evitare la cancellazione - automatica dei bit \itindex{suid~bit} \acr{suid} - e \itindex{sgid~bit} \acr{sgid} quando un file - per i quali sono impostati viene modificato da - un processo senza questa capacità e la capacità - di impostare il bit \acr{sgid} su un file anche - quando questo è relativo ad un gruppo cui non si - appartiene (vedi - sez.~\ref{sec:file_perm_management}).\\ - \const{CAP\_SETFCAP} & La capacità di impostare le - \textit{capabilities} di un file (dal kernel - 2.6.24).\\ - \const{CAP\_KILL} & La capacità di mandare segnali a qualunque - processo (vedi sez.~\ref{sec:sig_kill_raise}).\\ - \const{CAP\_SETGID} & La capacità di manipolare i group ID dei - processi, sia il principale che i supplementari, - (vedi sez.~\ref{sec:proc_setgroups}) che quelli - trasmessi tramite i socket \textit{unix domain} - (vedi sez.~\ref{sec:unix_socket}).\\ - \const{CAP\_SETUID} & La capacità di manipolare gli user ID del - processo (vedi sez.~\ref{sec:proc_setuid}) e di - trasmettere un user ID arbitrario nel passaggio - delle credenziali coi socket \textit{unix - domain} (vedi sez.~\ref{sec:unix_socket}).\\ -% -% Linux specific capabilities -% -\hline - \const{CAP\_IPC\_LOCK} & La capacità di effettuare il \textit{memory - locking} \itindex{memory~locking} con le - funzioni \func{mlock}, \func{mlockall}, - \func{shmctl}, \func{mmap} (vedi - sez.~\ref{sec:proc_mem_lock} e - sez.~\ref{sec:file_memory_map}). \\ - \const{CAP\_IPC\_OWNER} & La capacità di evitare il controllo dei permessi - per le operazioni sugli oggetti di - intercomunicazione fra processi (vedi - sez.~\ref{sec:ipc_sysv}).\\ - \const{CAP\_LEASE} & La capacità di creare dei \textit{file lease} - \index{file!lease} (vedi - sez.~\ref{sec:file_asyncronous_lease}) - pur non essendo proprietari del file (dal kernel - 2.4).\\ - \const{CAP\_LINUX\_IMMUTABLE}& La capacità di impostare sui file gli - attributi \textit{immutable} e - \itindex{append~mode} \textit{append only} (se - supportati).\\ - \const{CAP\_MKNOD} & La capacità di creare - \index{file!di~dispositivo} file di dispositivo - con \func{mknod} (vedi - sez.~\ref{sec:file_mknod}) (dal kernel 2.4).\\ - \const{CAP\_NET\_ADMIN} & La capacità di eseguire alcune operazioni - privilegiate sulla rete.\\ - \const{CAP\_NET\_BIND\_SERVICE}& La capacità di porsi in ascolto - su porte riservate (vedi - sez.~\ref{sec:TCP_func_bind}).\\ - \const{CAP\_NET\_BROADCAST}& La capacità di consentire l'uso di socket in - \itindex{broadcast} \textit{broadcast} e - \itindex{multicast} \textit{multicast}.\\ - \const{CAP\_NET\_RAW} & La capacità di usare socket \texttt{RAW} e - \texttt{PACKET} (vedi sez.~\ref{sec:sock_type}).\\ - \const{CAP\_SETPCAP} & La capacità di impostare o rimuovere una - capacità.\\ - % TODO cambiata nel 2.4.24 rc1 ? - \const{CAP\_SYS\_ADMIN} & La capacità di eseguire una serie di compiti - amministrativi. \\ - \const{CAP\_SYS\_BOOT} & La capacità di fare eseguire un riavvio del - sistema.\\ -% TODO trattare reboot e kexec - \const{CAP\_SYS\_CHROOT}& La capacità di eseguire la funzione - \func{chroot} (vedi - sez.~\ref{sec:file_chroot}).\\ - \const{CAP\_MAC\_ADMIN} & La capacità amministrare il MAC di Smack (dal - kernel 2.6.25).\\ - \const{CAP\_MAC\_OVERRIDE}& La capacità evitare il MAC di Smack (dal - kernel 2.6.25).\\ - \const{CAP\_SYS\_MODULE}& La capacità di caricare e rimuovere moduli del - kernel. \\ - \const{CAP\_SYS\_NICE} & La capacità di modificare le priorità dei - processi. \\ - \const{CAP\_SYS\_PACCT} & La capacità di usare le funzioni di - \textit{accounting} dei processi (vedi - sez.~\ref{sec:sys_bsd_accounting}).\\ - \const{CAP\_SYS\_PTRACE}& La capacità di tracciare qualunque processo con - \func{ptrace} (vedi - sez.~\ref{sec:xxx_ptrace}).\\ - \const{CAP\_SYS\_RAWIO} & La capacità di eseguire operazioni sulle porte - di I/O con \func{ioperm} e \func{iopl} (vedi - sez.~\ref{sec:file_io_port}).\\ - \const{CAP\_SYS\_RESOURCE}& La capacità di superare le limitazioni sulle - risorse.\\ - \const{CAP\_SYS\_TIME} & La capacità di modificare il tempo di sistema - (vedi sez.~\ref{sec:sys_time}).\\ - \const{CAP\_SYS\_TTY\_CONFIG}& La capacità di simulare un \textit{hangup} - della console, con la funzione - \func{vhangup}.\\ + \texttt{security}&Gli \textit{extended security attributes}: vengono + utilizzati dalle estensioni di sicurezza del kernel (i + \itindex{Linux~Security~Modules} \textit{Linux + Security Modules}), per le realizzazione di meccanismi + evoluti di controllo di accesso come \index{SELinux} + SELinux o le \textit{capabilities} dei file di + sez.~\ref{sec:proc_capabilities}.\\ + \texttt{system} & Gli \textit{extended security attributes}: sono usati + dal kernel per memorizzare dati di sistema associati ai + file come le \itindex{Access~Control~List~(ACL)} ACL (vedi + sez.~\ref{sec:file_ACL}) o le \itindex{capabilities} + \textit{capabilities} (vedi + sez.~\ref{sec:proc_capabilities}).\\ + \texttt{trusted}& I \textit{trusted extended attributes}: vengono + utilizzati per poter realizzare in user space + meccanismi che consentano di mantenere delle + informazioni sui file che non devono essere accessibili + ai processi ordinari.\\ + \texttt{user} & Gli \textit{extended user attributes}: utilizzati per + mantenere informazioni aggiuntive sui file (come il + \textit{mime-type}, la codifica dei caratteri o del + file) accessibili dagli utenti.\\ \hline \end{tabular} - \caption{Le costanti che identificano le \textit{capabilities} presenti nel - kernel.} -\label{tab:proc_capabilities} + \caption{I nomi utilizzati valore di \texttt{namespace} per distinguere le + varie classi di \textit{Extended Attributes}.} + \label{tab:extended_attribute_class} \end{table} -\footnotetext{vale a dire i permessi caratteristici del modello classico del - controllo di accesso chiamato \itindex{Discrectionary~Access~Control~(DAC)} - \textit{Discrectionary Access Control} (da cui il nome DAC).} - -% TODO aggiungere CAP_SYSLOG, citata in http://lwn.net/Articles/429595/ -La prima di queste capacità ``\textsl{ampie}'' è \const{CAP\_FOWNER}, che -rimuove le restrizioni poste ad un processo che non ha la proprietà di un file -in un vasto campo di operazioni;\footnote{vale a dire la richiesta che - l'user-ID effettivo del processo (o meglio il \textit{filesystem user-ID}, - vedi sez.~\ref{sec:proc_setuid}) coincida con quello del proprietario.} -queste comprendono i cambiamenti dei permessi e dei tempi del file (vedi -sez.~\ref{sec:file_perm_management} e sez.~\ref{sec:file_file_times}), le -impostazioni degli attributi estesi e delle ACL (vedi -sez.~\ref{sec:file_xattr} e \ref{sec:file_ACL}), poter ignorare lo -\itindex{sticky~bit} \textit{sticky bit} nella cancellazione dei file (vedi -sez.~\ref{sec:file_special_perm}), la possibilità di impostare il flag di -\const{O\_NOATIME} con \func{open} e \func{fcntl} (vedi -sez.~\ref{sec:file_open} e sez.~\ref{sec:file_fcntl}) senza restrizioni. +Dato che uno degli usi degli \textit{Extended Attributes} è quello che li +impiega per realizzare delle estensioni (come le +\itindex{Access~Control~List~(ACL)} ACL, \index{SELinux} SELinux, ecc.) al +tradizionale meccanismo dei controlli di accesso di Unix, l'accesso ai loro +valori viene regolato in maniera diversa a seconda sia della loro classe sia +di quali, fra le estensioni che li utilizzano, sono poste in uso. In +particolare, per ciascuna delle classi riportate in +tab.~\ref{tab:extended_attribute_class}, si hanno i seguenti casi: +\begin{basedescript}{\desclabelwidth{1.7cm}\desclabelstyle{\nextlinelabel}} +\item[\texttt{security}] L'accesso agli \textit{extended security attributes} + dipende dalle politiche di sicurezza stabilite da loro stessi tramite + l'utilizzo di un sistema di controllo basato sui + \itindex{Linux~Security~Modules} \textit{Linux Security Modules} (ad esempio + \index{SELinux} SELinux). Pertanto l'accesso in lettura o scrittura dipende + dalle politiche di sicurezza implementate all'interno dal modulo di + sicurezza che si sta utilizzando al momento (ciascuno avrà le sue). Se non è + stato caricato nessun modulo di sicurezza l'accesso in lettura sarà + consentito a tutti i processi, mentre quello in scrittura solo ai processi + con privilegi amministrativi dotati della \index{capabilities} + \textit{capability} \const{CAP\_SYS\_ADMIN}. -Una seconda capacità che copre diverse operazioni, in questo caso riguardanti -la rete, è \const{CAP\_NET\_ADMIN}, che consente di impostare le opzioni -privilegiate dei socket (vedi sez.~\ref{sec:sock_generic_options}), abilitare -il \itindex{multicast} \textit{multicasting}, eseguire la configurazione delle -interfacce di rete (vedi sez.~\ref{sec:sock_ioctl_netdevice}) ed impostare la -tabella di instradamento. +\item[\texttt{system}] Anche l'accesso agli \textit{extended system + attributes} dipende dalle politiche di accesso che il kernel realizza + anche utilizzando gli stessi valori in essi contenuti. Ad esempio nel caso + delle \itindex{Access~Control~List~(ACL)} ACL l'accesso è consentito in + lettura ai processi che hanno la capacità di eseguire una ricerca sul file + (cioè hanno il permesso di lettura sulla directory che contiene il file) ed + in scrittura al proprietario del file o ai processi dotati della + \textit{capability} \index{capabilities} \const{CAP\_FOWNER}.\footnote{vale + a dire una politica di accesso analoga a quella impiegata per gli ordinari + permessi dei file.} -Una terza \textit{capability} con vasto campo di applicazione è -\const{CAP\_SYS\_ADMIN}, che copre una serie di operazioni amministrative, -come impostare le quote disco (vedi sez.\ref{sec:disk_quota}), attivare e -disattivare la swap, montare, rimontare e smontare filesystem (vedi -sez.~\ref{sec:sys_file_config}), effettuare operazioni di controllo sugli -oggetti dell'IPC di SysV (vedi sez.~\ref{sec:ipc_sysv}), operare sugli -attributi estesi di classe \texttt{security} o \texttt{trusted} (vedi -sez.~\ref{sec:file_xattr}), specificare un user-ID arbitrario nella -trasmissione delle credenziali dei socket (vedi sez.~\ref{sec:socket_xxx}), -assegnare classi privilegiate per lo scheduling dell'I/O (vedi -sez.~\ref{sec:io_priority}), superare il limite di sistema sul numero massimo -di file aperti,\footnote{quello indicato da \procfile{/proc/sys/fs/file-max}.} -effettuare operazioni privilegiate sulle chiavi mantenute dal kernel (vedi -sez.~\ref{sec:io_priority}), usare la funzione \func{lookup\_dcookie} (vedi -sez.~\ref{sec:xxx_profiling}), usare \const{CLONE\_NEWNS} con \func{unshare}, -(vedi sez.~\ref{sec:process_clone}). +\item[\texttt{trusted}] L'accesso ai \textit{trusted extended attributes}, sia + per la lettura che per la scrittura, è consentito soltanto ai processi con + privilegi amministrativi dotati della \index{capabilities} + \textit{capability} \const{CAP\_SYS\_ADMIN}. In questo modo si possono + utilizzare questi attributi per realizzare in user space dei meccanismi di + controllo che accedono ad informazioni non disponibili ai processi ordinari. -Originariamente \const{CAP\_SYS\_NICE} riguardava soltanto la capacità di -aumentare le priorità di esecuzione dei processi, come la diminuzione del -valore di \textit{nice} (vedi sez.~\ref{sec:proc_sched_stand}), l'uso delle -priorità \textit{real-time} (vedi sez.~\ref{sec:proc_real_time}), o -l'impostazione delle affinità di processore (vedi -sez.~\ref{sec:proc_sched_multiprocess}); ma con l'introduzione di priorità -anche riguardo le operazioni di accesso al disco, e, nel caso di sistemi NUMA, -alla memoria, essa viene a coprire anche la possibilità di assegnare priorità -arbitrarie nell'accesso a disco (vedi sez.~\ref{sec:io_priority}) e nelle -politiche di allocazione delle pagine di memoria ai nodi di un sistema NUMA. +\item[\texttt{user}] L'accesso agli \textit{extended user attributes} è + regolato dai normali permessi dei file: occorre avere il permesso di lettura + per leggerli e quello di scrittura per scriverli o modificarli. Dato l'uso + di questi attributi si è scelto di applicare al loro accesso gli stessi + criteri che si usano per l'accesso al contenuto dei file (o delle directory) + cui essi fanno riferimento. Questa scelta vale però soltanto per i file e le + directory ordinarie, se valesse in generale infatti si avrebbe un serio + problema di sicurezza dato che esistono diversi oggetti sul filesystem per i + quali è normale avere avere il permesso di scrittura consentito a tutti gli + utenti, come i link simbolici, o alcuni \index{file!di~dispositivo} file di + dispositivo come \texttt{/dev/null}. Se fosse possibile usare su di essi gli + \textit{extended user attributes} un utente qualunque potrebbe inserirvi + dati a piacere.\footnote{la cosa è stata notata su XFS, dove questo + comportamento permetteva, non essendovi limiti sullo spazio occupabile + dagli \textit{Extended Attributes}, di bloccare il sistema riempiendo il + disco.} -Infine la \textit{capability} \const{CAP\_SYS\_RESOURCE} attiene alla -possibilità di superare i limiti imposti sulle risorse di sistema, come usare -lo spazio disco riservato all'amministratore sui filesystem che lo supportano, -usare la funzione \func{ioctl} per controllare il \textit{journaling} sul -filesystem \acr{ext3}, non subire le quote disco, aumentare i limiti sulle -risorse (vedi sez.~\ref{sec:sys_resource_limit}) e sulle dimensioni dei -messaggi delle code del SysV IPC (vedi sez.~\ref{sec:ipc_sysv_mq}). + La semantica del controllo di accesso indicata inoltre non avrebbe alcun + senso al di fuori di file e directory: i permessi di lettura e scrittura per + un \index{file!di~dispositivo} file di dispositivo attengono alle capacità + di accesso al dispositivo sottostante,\footnote{motivo per cui si può + formattare un disco anche se \texttt{/dev} è su un filesystem in sola + lettura.} mentre per i link simbolici questi vengono semplicemente + ignorati: in nessuno dei due casi hanno a che fare con il contenuto del + file, e nella discussione relativa all'uso degli \textit{extended user + attributes} nessuno è mai stato capace di indicare una qualche forma + sensata di utilizzo degli stessi per link simbolici o + \index{file!di~dispositivo} file di dispositivo, e neanche per le fifo o i + socket. Per questo motivo essi sono stati completamente disabilitati per + tutto ciò che non sia un file regolare o una directory.\footnote{si può + verificare la semantica adottata consultando il file \texttt{fs/xattr.c} + dei sorgenti del kernel.} Inoltre per le directory è stata introdotta una + ulteriore restrizione, dovuta di nuovo alla presenza ordinaria di permessi + di scrittura completi su directory come \texttt{/tmp}. Per questo motivo, + per evitare eventuali abusi, se una directory ha lo \itindex{sticky~bit} + \textit{sticky bit} attivo sarà consentito scrivere i suoi \textit{extended + user attributes} soltanto se si è proprietari della stessa, o si hanno i + privilegi amministrativi della capability \index{capabilities} + \const{CAP\_FOWNER}. +\end{basedescript} +Le funzioni per la gestione degli attributi estesi, come altre funzioni di +gestione avanzate specifiche di Linux, non fanno parte delle \acr{glibc}, e +sono fornite da una apposita libreria, \texttt{libattr}, che deve essere +installata a parte;\footnote{la versione corrente della libreria è + \texttt{libattr1}.} pertanto se un programma le utilizza si dovrà indicare +esplicitamente l'uso della suddetta libreria invocando il compilatore con +l'opzione \texttt{-lattr}. -Per la gestione delle \textit{capabilities} il kernel mette a disposizione due -funzioni che permettono rispettivamente di leggere ed impostare i valori dei -tre insiemi illustrati in precedenza. Queste due funzioni sono \funcd{capget} -e \funcd{capset} e costituiscono l'interfaccia di gestione basso livello; i -loro rispettivi prototipi sono: +Per poter leggere gli attributi estesi sono disponibili tre diverse funzioni, +\funcd{getxattr}, \funcd{lgetxattr} e \funcd{fgetxattr}, che consentono +rispettivamente di richiedere gli attributi relativi a un file, a un link +simbolico e ad un file descriptor; i rispettivi prototipi sono: \begin{functions} - \headdecl{sys/capability.h} + \headdecl{sys/types.h} + \headdecl{attr/xattr.h} + + \funcdecl{ssize\_t getxattr(const char *path, const char *name, void + *value, size\_t size)} - \funcdecl{int capget(cap\_user\_header\_t hdrp, cap\_user\_data\_t datap)} - Legge le \textit{capabilities}. + \funcdecl{ssize\_t lgetxattr(const char *path, const char *name, void + *value, size\_t size)} - \funcdecl{int capset(cap\_user\_header\_t hdrp, const cap\_user\_data\_t - datap)} - Imposta le \textit{capabilities}. + \funcdecl{ssize\_t fgetxattr(int filedes, const char *name, void *value, + size\_t size)} + Le funzioni leggono il valore di un attributo esteso. - \bodydesc{Entrambe le funzioni ritornano 0 in caso di successo e -1 in caso - di errore, nel qual caso \var{errno} può assumere i valori: - \begin{errlist} - \item[\errcode{ESRCH}] si è fatto riferimento ad un processo inesistente. - \item[\errcode{EPERM}] si è tentato di aggiungere una capacità - nell'insieme delle \textit{capabilities} permesse, o di impostare una - capacità non presente nell'insieme di quelle permesse negli insieme - delle effettive o ereditate, o si è cercato di impostare una - \textit{capability} di un altro processo senza avare - \const{CAP\_SETPCAP}. + \bodydesc{Le funzioni restituiscono un intero positivo che indica la + dimensione dell'attributo richiesto in caso di successo, e $-1$ in caso di + errore, nel qual caso \var{errno} assumerà i valori: + \begin{errlist} + \item[\errcode{ENOATTR}] l'attributo richiesto non esiste. + \item[\errcode{ERANGE}] la dimensione \param{size} del buffer \param{value} + non è sufficiente per contenere il risultato. + \item[\errcode{ENOTSUP}] gli attributi estesi non sono supportati dal + filesystem o sono disabilitati. \end{errlist} - ed inoltre \errval{EFAULT} ed \errval{EINVAL}. -} - + e tutti gli errori di \func{stat}, come \errcode{EPERM} se non si hanno i + permessi di accesso all'attributo. } \end{functions} -Queste due funzioni prendono come argomenti due tipi di dati dedicati, -definiti come puntatori a due strutture specifiche di Linux, illustrate in -fig.~\ref{fig:cap_kernel_struct}. Per poterle utilizzare occorre anche -cancellare la macro \macro{\_POSIX\_SOURCE}.\footnote{per farlo occorre - utilizzare la direttiva di preprocessore \direct{undef}; si dovrà cioè - inserire una istruzione \texttt{\#undef \_POSIX\_SOURCE} prima di includere - \texttt{sys/capability.h}.} Si tenga presente che le strutture di -fig.~\ref{fig:cap_kernel_struct}, come i prototipi delle due funzioni -\func{capget} e \func{capset}, sono soggette ad essere modificate con il -cambiamento del kernel (in particolare i tipi di dati delle strutture) ed -anche se finora l'interfaccia è risultata stabile, non c'è nessuna -assicurazione che questa venga mantenuta.\footnote{anzi, visto lo scarso - utilizzo di questa funzionalità ci sono state varie discussioni fra gli - sviluppatori del kernel relative all'eliminarla o al modificarla - radicalmente.} Pertanto se si vogliono scrivere programmi portabili che -possano essere eseguiti su qualunque versione del kernel è opportuno -utilizzare le interfacce di alto livello. - -\begin{figure}[!htb] - \footnotesize - \centering - \begin{minipage}[c]{15cm} - \includestruct{listati/cap_user_header_t.h} - \end{minipage} - \normalsize - \caption{Definizione delle strutture a cui fanno riferimento i puntatori - \structd{cap\_user\_header\_t} e \structd{cap\_user\_data\_t} usati per - l'interfaccia di gestione di basso livello delle \textit{capabilities}.} - \label{fig:cap_kernel_struct} -\end{figure} - -La struttura a cui deve puntare l'argomento \param{hdrp} serve ad indicare, -tramite il campo \var{pid}, il processo del quale si vogliono leggere o -modificare le \textit{capabilities}. Il campo \var{version} deve essere -impostato al valore della versione delle usata dal kernel (quello indicato -dalla costante \const{\_LINUX\_CAPABILITY\_VERSION} di -fig.~\ref{fig:cap_kernel_struct}) altrimenti le funzioni ritorneranno con un -errore di \errcode{EINVAL}, restituendo nel campo stesso il valore corretto -della versione in uso. La struttura a cui deve puntare l'argomento -\param{datap} invece conterrà i valori letti o da impostare per i tre insiemi -delle capacità del processo. +Le funzioni \func{getxattr} e \func{lgetxattr} prendono come primo argomento +un pathname che indica il file di cui si vuole richiedere un attributo, la +sola differenza è che la seconda, se il pathname indica un link simbolico, +restituisce gli attributi di quest'ultimo e non quelli del file a cui esso fa +riferimento. La funzione \func{fgetxattr} prende invece come primo argomento +un numero di file descriptor, e richiede gli attributi del file ad esso +associato. -Dato che le precedenti funzioni, oltre ad essere specifiche di Linux, non -garantiscono la stabilità nell'interfaccia, è sempre opportuno effettuare la -gestione delle \textit{capabilities} utilizzando le funzioni di libreria a -questo dedicate. Queste funzioni, che seguono quanto previsto nelle bozze -dello standard POSIX.1e, non fanno parte delle \acr{glibc} e sono fornite in -una libreria a parte,\footnote{la libreria è \texttt{libcap2}, nel caso di - Debian può essere installata con il pacchetto omonimo.} pertanto se un -programma le utilizza si dovrà indicare esplicitamente l'uso della suddetta -libreria attraverso l'opzione \texttt{-lcap} del compilatore. +Tutte e tre le funzioni richiedono di specificare nell'argomento \param{name} +il nome dell'attributo di cui si vuole ottenere il valore. Il nome deve essere +indicato comprensivo di prefisso del \textit{namespace} cui appartiene (uno +dei valori di tab.~\ref{tab:extended_attribute_class}) nella forma +\texttt{namespace.attributename}, come stringa terminata da un carattere NUL. +Il suo valore verrà restituito nel buffer puntato dall'argomento \param{value} +per una dimensione massima di \param{size} byte;\footnote{gli attributi estesi + possono essere costituiti arbitrariamente da dati testuali o binari.} se +quest'ultima non è sufficiente si avrà un errore di \errcode{ERANGE}. -Le funzioni dell'interfaccia delle bozze di POSIX.1e prevedono l'uso di uno -tipo di dato opaco, \type{cap\_t}, come puntatore ai dati mantenuti nel -cosiddetto \textit{capability state},\footnote{si tratta in sostanza di un - puntatore ad una struttura interna utilizzata dalle librerie, i cui campi - non devono mai essere acceduti direttamente.} in sono memorizzati tutti i -dati delle \textit{capabilities}. In questo modo è possibile mascherare i -dettagli della gestione di basso livello, che potranno essere modificati senza -dover cambiare le funzioni dell'interfaccia, che faranno riferimento soltanto -ad oggetti di questo tipo. L'interfaccia pertanto non soltanto fornisce le -funzioni per modificare e leggere le \textit{capabilities}, ma anche quelle -per gestire i dati attraverso \type{cap\_t}. +Per evitare di dover indovinare la dimensione di un attributo per tentativi si +può eseguire una interrogazione utilizzando un valore nullo per \param{size}; +in questo caso non verrà letto nessun dato, ma verrà restituito come valore di +ritorno della funzione chiamata la dimensione totale dell'attributo esteso +richiesto, che si potrà usare come stima per allocare un buffer di dimensioni +sufficienti.\footnote{si parla di stima perché anche se le funzioni + restituiscono la dimensione esatta dell'attributo al momento in cui sono + eseguite, questa potrebbe essere modificata in qualunque momento da un + successivo accesso eseguito da un altro processo.} -La prima funzione dell'interfaccia è quella che permette di inizializzare un -\textit{capability state}, allocando al contempo la memoria necessaria per i -relativi dati. La funzione è \funcd{cap\_init} ed il suo prototipo è: +Un secondo gruppo di funzioni è quello che consente di impostare il valore di +un attributo esteso, queste sono \funcd{setxattr}, \funcd{lsetxattr} e +\funcd{fsetxattr}, e consentono di operare rispettivamente su un file, su un +link simbolico o specificando un file descriptor; i loro prototipi sono: \begin{functions} - \headdecl{sys/capability.h} - - \funcdecl{cap\_t cap\_init(void)} - Crea ed inizializza un \textit{capability state}. + \headdecl{sys/types.h} + \headdecl{attr/xattr.h} - \bodydesc{La funzione ritorna un valore non nullo in caso di successo e - \macro{NULL} in caso di errore, nel qual caso \var{errno} assumerà il - valore \errval{ENOMEM}. - } -\end{functions} - -La funzione restituisce il puntatore \type{cap\_t} ad uno stato inizializzato -con tutte le \textit{capabilities} azzerate. In caso di errore (cioè quando -non c'è memoria sufficiente ad allocare i dati) viene restituito \macro{NULL} -ed \var{errno} viene impostata a \errval{ENOMEM}. La memoria necessaria a -mantenere i dati viene automaticamente allocata da \func{cap\_init}, ma dovrà -essere disallocata esplicitamente quando non è più necessaria utilizzando, per -questo l'interfaccia fornisce una apposita funzione, \funcd{cap\_free}, il cui -prototipo è: -\begin{functions} - \headdecl{sys/capability.h} - - \funcdecl{int cap\_free(void *obj\_d)} - Disalloca la memoria allocata per i dati delle \textit{capabilities}. - - \bodydesc{La funzione ritorna 0 in caso di successo e $-1$ in caso di - errore, nel qual caso \var{errno} assumerà il valore \errval{EINVAL}. - } -\end{functions} + \funcdecl{int setxattr(const char *path, const char *name, const void + *value, size\_t size, int flags)} -La funzione permette di liberare la memoria allocata dalle altre funzioni -della libreria sia per un \textit{capability state}, nel qual caso l'argomento -dovrà essere un dato di tipo \type{cap\_t}, che per una descrizione testuale -dello stesso,\footnote{cioè quanto ottenuto tramite la funzione - \func{cap\_to\_text}.} nel qual caso l'argomento dovrà essere un dato di -tipo \texttt{char *}. Per questo l'argomento \param{obj\_d} è dichiarato come -\texttt{void *} e deve sempre corrispondere ad un puntatore ottenuto tramite -le altre funzioni della libreria, altrimenti la funzione fallirà con un errore -di \errval{EINVAL}. + \funcdecl{int lsetxattr(const char *path, const char *name, const void + *value, size\_t size, int flags)} -Infine si può creare una copia di un \textit{capability state} ottenuto in -precedenza tramite la funzione \funcd{cap\_dup}, il cui prototipo è: -\begin{functions} - \headdecl{sys/capability.h} + \funcdecl{int fsetxattr(int filedes, const char *name, const void *value, + size\_t size, int flags)} - \funcdecl{cap\_t cap\_dup(cap\_t cap\_p)} - Duplica un \textit{capability state} restituendone una copia. + Impostano il valore di un attributo esteso. - \bodydesc{La funzione ritorna un valore non nullo in caso di successo e - \macro{NULL} in caso di errore, nel qual caso \var{errno} potrà assumere i - valori \errval{ENOMEM} o \errval{EINVAL}. - } + \bodydesc{Le funzioni restituiscono 0 in caso di successo, e $-1$ in caso di + errore, nel qual caso \var{errno} assumerà i valori: + \begin{errlist} + \item[\errcode{ENOATTR}] si è usato il flag \const{XATTR\_REPLACE} e + l'attributo richiesto non esiste. + \item[\errcode{EEXIST}] si è usato il flag \const{XATTR\_CREATE} ma + l'attributo esiste già. + \item[\errcode{ENOTSUP}] gli attributi estesi non sono supportati dal + filesystem o sono disabilitati. + \end{errlist} + Oltre a questi potranno essere restituiti tutti gli errori di \func{stat}, + ed in particolare \errcode{EPERM} se non si hanno i permessi di accesso + all'attributo. +} \end{functions} -La funzione crea una copia del \textit{capability state} posto all'indirizzo -\param{cap\_p} che si è passato come argomento, restituendo il puntatore alla -copia, che conterrà gli stessi valori delle \textit{capabilities} presenti -nell'originale. La memoria necessaria viene allocata automaticamente dalla -funzione. Una volta effettuata la copia i due \textit{capability state} -potranno essere modificati in maniera completamente -indipendente.\footnote{alla fine delle operazioni si ricordi però di - disallocare anche la copia, oltre all'originale. } +Le tre funzioni prendono come primo argomento un valore adeguato al loro +scopo, usato in maniera del tutto identica a quanto visto in precedenza per le +analoghe che leggono gli attributi estesi. Il secondo argomento \param{name} +deve indicare, anche in questo caso con gli stessi criteri appena visti per le +analoghe \func{getxattr}, \func{lgetxattr} e \func{fgetxattr}, il nome +(completo di suffisso) dell'attributo su cui si vuole operare. -Una seconda classe di funzioni di servizio previste dall'interfaccia sono -quelle per la gestione dei dati contenuti all'interno di un \textit{capability - state}; la prima di queste è \funcd{cap\_clear}, il cui prototipo è: -\begin{functions} - \headdecl{sys/capability.h} +Il valore che verrà assegnato all'attributo dovrà essere preparato nel buffer +puntato da \param{value}, e la sua dimensione totale (in byte) sarà indicata +dall'argomento \param{size}. Infine l'argomento \param{flag} consente di +controllare le modalità di sovrascrittura dell'attributo esteso, esso può +prendere due valori: con \const{XATTR\_REPLACE} si richiede che l'attributo +esista, nel qual caso verrà sovrascritto, altrimenti si avrà errore, mentre +con \const{XATTR\_CREATE} si richiede che l'attributo non esista, nel qual +caso verrà creato, altrimenti si avrà errore ed il valore attuale non sarà +modificato. Utilizzando per \param{flag} un valore nullo l'attributo verrà +modificato se è già presente, o creato se non c'è. - \funcdecl{int cap\_clear(cap\_t cap\_p)} - Inizializza un \textit{capability state} cancellando tutte le - \textit{capabilities}. +Le funzioni finora illustrate permettono di leggere o scrivere gli attributi +estesi, ma sarebbe altrettanto utile poter vedere quali sono gli attributi +presenti; a questo provvedono le funzioni \funcd{listxattr}, +\funcd{llistxattr} e \funcd{flistxattr} i cui prototipi sono: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{attr/xattr.h} - \bodydesc{La funzione ritorna 0 in caso di successo e $-1$ in caso di - errore, nel qual caso \var{errno} assumerà il valore \errval{EINVAL}. - } -\end{functions} - -La funzione si limita ad azzerare tutte le \textit{capabilities} presenti nel -\textit{capability state} all'indirizzo \param{cap\_p} passato come argomento, -restituendo uno stato \textsl{vuoto}, analogo a quello che si ottiene nella -creazione con \func{cap\_init}. + \funcdecl{ssize\_t listxattr(const char *path, char *list, size\_t size)} -Per la gestione dei valori delle \textit{capabilities} presenti in un -\textit{capability state} l'interfaccia prevede due funzioni, -\funcd{cap\_get\_flag} e \funcd{cap\_set\_flag}, che permettono -rispettivamente di leggere o impostare il valore di un flag delle -\textit{capabilities}; i rispettivi prototipi sono: -\begin{functions} - \headdecl{sys/capability.h} + \funcdecl{ssize\_t llistxattr(const char *path, char *list, size\_t size)} - \funcdecl{int cap\_get\_flag(cap\_t cap\_p, cap\_value\_t cap, cap\_flag\_t - flag, cap\_flag\_value\_t *value\_p)} - Legge il valore di una \textit{capability}. + \funcdecl{ssize\_t flistxattr(int filedes, char *list, size\_t size)} - \funcdecl{int cap\_set\_flag(cap\_t cap\_p, cap\_flag\_t flag, int ncap, - cap\_value\_t *caps, cap\_flag\_value\_t value)} - Imposta il valore di una \textit{capability}. + Leggono la lista degli attributi estesi di un file. - \bodydesc{Le funzioni ritornano 0 in caso di successo e $-1$ in caso di - errore, nel qual caso \var{errno} assumerà il valore \errval{EINVAL}. + \bodydesc{Le funzioni restituiscono un intero positivo che indica la + dimensione della lista in caso di successo, e $-1$ in caso di errore, nel + qual caso \var{errno} assumerà i valori: + \begin{errlist} + \item[\errcode{ERANGE}] la dimensione \param{size} del buffer \param{value} + non è sufficiente per contenere il risultato. + \item[\errcode{ENOTSUP}] gli attributi estesi non sono supportati dal + filesystem o sono disabilitati. + \end{errlist} + Oltre a questi potranno essere restituiti tutti gli errori di \func{stat}, + ed in particolare \errcode{EPERM} se non si hanno i permessi di accesso + all'attributo. } \end{functions} -In entrambe le funzioni l'argomento \param{cap\_p} indica il puntatore al -\textit{capability state} su cui operare, mentre l'argomento \param{flag} -indica su quale dei tre insiemi illustrati a -pag.~\pageref{sec:capabilities_set} si intende operare. Questi devono essere -specificati con una variabile di tipo \type{cap\_flag\_t} che può assumere -esclusivamente\footnote{si tratta in effetti di un tipo enumerato, come si può - verificare dalla sua definizione che si trova in - \texttt{/usr/include/sys/capability.h}.} uno dei valori illustrati in -tab.~\ref{tab:cap_set_identifier}. - -\begin{table}[htb] - \centering - \footnotesize - \begin{tabular}[c]{|l|l|} - \hline - \textbf{Valore} & \textbf{Significato} \\ - \hline - \hline - \const{CAP\_EFFECTIVE} & Capacità dell'insieme \textsl{effettivo}.\\ - \const{CAP\_PERMITTED} & Capacità dell'insieme \textsl{permesso}.\\ - \const{CAP\_INHERITABLE}& Capacità dell'insieme \textsl{ereditabile}.\\ - \hline - \end{tabular} - \caption{Valori possibili per il tipo di dato \type{cap\_flag\_t} che - identifica gli insiemi delle \textit{capabilities}.} - \label{tab:cap_set_identifier} -\end{table} +Come per le precedenti le tre funzioni leggono gli attributi rispettivamente +di un file, un link simbolico o specificando un file descriptor, da +specificare con il loro primo argomento. Gli altri due argomenti, identici per +tutte e tre, indicano rispettivamente il puntatore \param{list} al buffer dove +deve essere letta la lista e la dimensione \param{size} di quest'ultimo. -La capacità che si intende controllare o impostare invece deve essere -specificata attraverso una variabile di tipo \type{cap\_value\_t}, che può -prendere come valore uno qualunque di quelli riportati in -tab.~\ref{tab:proc_capabilities}, in questo caso però non è possibile -combinare diversi valori in una maschera binaria, una variabile di tipo -\type{cap\_value\_t} deve indicare una sola capacità.\footnote{nel file di - header citato nella nota precedente il tipo \type{cap\_value\_t} è definito - come \ctyp{int}, ma i valori validi sono soltanto quelli di - tab.~\ref{tab:proc_capabilities}.} +La lista viene fornita come sequenza non ordinata dei nomi dei singoli +attributi estesi (sempre comprensivi del prefisso della loro classe) ciascuno +dei quali è terminato da un carattere nullo. I nomi sono inseriti nel buffer +uno di seguito all'altro. Il valore di ritorno della funzione indica la +dimensione totale della lista in byte. -Infine lo stato di una capacità è descritto ad una variabile di tipo -\type{cap\_flag\_value\_t}, che a sua volta può assumere soltanto -uno\footnote{anche questo è un tipo enumerato.} dei valori di -tab.~\ref{tab:cap_value_type}. +Come per le funzioni di lettura dei singoli attributi se le dimensioni del +buffer non sono sufficienti si avrà un errore, ma è possibile ottenere dal +valore di ritorno della funzione una stima della dimensione totale della lista +usando per \param{size} un valore nullo. -\begin{table}[htb] - \centering - \footnotesize - \begin{tabular}[c]{|l|l|} - \hline - \textbf{Valore} & \textbf{Significato} \\ - \hline - \hline - \const{CAP\_CLEAR}& La capacità non è impostata.\\ - \const{CAP\_SET} & La capacità è impostata.\\ - \hline - \end{tabular} - \caption{Valori possibili per il tipo di dato \type{cap\_flag\_value\_t} che - indica lo stato di una capacità.} - \label{tab:cap_value_type} -\end{table} +Infine per rimuovere semplicemente un attributo esteso, si ha a disposizione +un ultimo gruppo di funzioni: \funcd{removexattr}, \funcd{lremovexattr} e +\funcd{fremovexattr}; i rispettivi prototipi sono: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{attr/xattr.h} + + \funcdecl{int removexattr(const char *path, const char *name)} -La funzione \func{cap\_get\_flag} legge lo stato della capacità indicata -dall'argomento \param{cap} all'interno dell'insieme indicato dall'argomento -\param{flag} e ne restituisce il valore nella variabile posta all'indirizzo -puntato dall'argomento \param{value\_p}; è possibile cioè leggere soltanto uno -stato di una capacità alla volta. + \funcdecl{int lremovexattr(const char *path, const char *name)} -La funzione \func{cap\_set\_flag} può invece impostare in una sola chiamata -più \textit{capabilities}, anche se solo all'interno dello stesso insieme. Per -questo motivo essa prende un vettore di valori di tipo \type{cap\_value\_t} -nell'argomento \param{caps}, la cui dimensione viene specificata dall'argomento -\param{ncap}. Il tipo di impostazione da eseguire (cancellazione o -impostazione) viene indicato dall'argomento \param{value}. - -Per la visualizzazione dello stato delle \textit{capabilities} l'interfaccia -prevede una funzione apposita, \funcd{cap\_to\_text}, il cui prototipo è: -\begin{functions} - \headdecl{sys/capability.h} + \funcdecl{int fremovexattr(int filedes, const char *name)} - \funcdecl{char * cap\_to\_text(cap\_t caps, ssize\_t * length\_p)} - Genera una visualizzazione testuale delle \textit{capabilities}. + Rimuovono un attributo esteso di un file. - \bodydesc{La funzione ritorna un puntatore alla stringa con la descrizione - delle \textit{capabilities} in caso di successo e \val{NULL} in caso di - errore, nel qual caso \var{errno} può assumere i valori \errval{EINVAL} o - \errval{ENOMEM}. - } + \bodydesc{Le funzioni restituiscono 0 in caso di successo, e $-1$ in caso di + errore, nel qual caso \var{errno} assumerà i valori: + \begin{errlist} + \item[\errcode{ENOATTR}] l'attributo richiesto non esiste. + \item[\errcode{ENOTSUP}] gli attributi estesi non sono supportati dal + filesystem o sono disabilitati. + \end{errlist} + ed inoltre tutti gli errori di \func{stat}. +} \end{functions} -La funzione ritorna l'indirizzo di una stringa contente la descrizione -testuale del contenuto del \textit{capabilities state} \param{caps} passato -come argomento, e, qualora l'argomento \param{length\_p} sia diverso da -\val{NULL}, restituisce nella variabile intera da questo puntata la lunghezza -della stringa. La stringa restituita viene allocata automaticamente dalla -funzione e pertanto dovrà essere liberata con \func{cap\_free}. +Le tre funzioni rimuovono l'attributo esteso indicato dall'argomento +\param{name} rispettivamente di un file, un link simbolico o specificando un +file descriptor, da specificare con il loro primo argomento. Anche in questo +caso l'argomento \param{name} deve essere specificato con le modalità già +illustrate in precedenza per le altre funzioni relative agli attributi estesi. -Fin quei abbiamo trattato solo le funzioni di servizio relative alla -manipolazione dei \textit{capabilities state}; l'interfaccia di gestione -prevede però anche le funzioni per la gestione delle \textit{capabilities} -stesse. La prima di queste è \funcd{cap\_get\_proc} che consente la lettura -delle \textit{capabilities} del processo corrente, il suo prototipo è: -\begin{functions} - \headdecl{sys/capability.h} +\itindend{Extended~Attributes} - \funcdecl{cap\_t cap\_get\_proc(void)} - Legge le \textit{capabilities} del processo corrente. - - \bodydesc{La funzione ritorna un valore diverso da \val{NULL} in caso di - successo e \val{NULL} in caso di errore, nel qual caso \var{errno} può - assumere i valori \errval{EINVAL}, \errval{EPERM} o \errval{ENOMEM}. } -\end{functions} -La funzione legge il valore delle \textit{capabilities} associate al processo -da cui viene invocata, restituendo il risultato tramite il puntatore ad un -\textit{capabilities state} contenente tutti i dati che provvede ad allocare -autonomamente e che di nuovo occorrerà liberare con \func{cap\_free} quando -non sarà più utilizzato. +\subsection{Le \textit{Access Control List}} +\label{sec:file_ACL} -Se invece si vogliono leggere le \textit{capabilities} di un processo -specifico occorre usare la funzione \funcd{capgetp}, il cui -prototipo\footnote{su alcune pagine di manuale la funzione è descritta con un - prototipo sbagliato, che prevede un valore di ritorno di tipo \type{cap\_t}, - ma il valore di ritorno è intero, come si può verificare anche dalla - dichiarazione della stessa in \texttt{sys/capability.h}.} è: -\begin{functions} - \headdecl{sys/capability.h} +% la documentazione di sistema è nei pacchetti libacl1-dev e acl +% vedi anche http://www.suse.de/~agruen/acl/linux-acls/online/ - \funcdecl{int capgetp(pid\_t pid, cap\_t cap\_d)} - Legge le \textit{capabilities} del processo indicato da \param{pid}. - - \bodydesc{La funzione ritorna 0 in caso di successo e $-1$ in caso di - errore, nel qual caso \var{errno} può assumere i valori \errval{EINVAL}, - \errval{EPERM} o \errval{ENOMEM}. - } -\end{functions} -%TODO controllare e correggere i codici di errore!!! - -La funzione legge il valore delle \textit{capabilities} del processo indicato -con l'argomento \param{pid}, e restituisce il risultato nel -\textit{capabilities state} posto all'indirizzo indicato con l'argomento -\param{cap\_d}; a differenza della precedente in questo caso il -\textit{capability state} deve essere stato creato in precedenza. Qualora il -processo indicato non esista si avrà un errore di \errval{ESRCH}. Gli stessi -valori possono essere letti direttamente nel filesystem \textit{proc}, nei -file \texttt{/proc//status}; ad esempio per \texttt{init} si otterrà -qualcosa del tipo: -\begin{Verbatim} -... -CapInh: 0000000000000000 -CapPrm: 00000000fffffeff -CapEff: 00000000fffffeff -... -\end{Verbatim} - -Infine per impostare le \textit{capabilities} del processo corrente (non -esiste una funzione che permetta di cambiare le \textit{capabilities} di un -altro processo) si deve usare la funzione \funcd{cap\_set\_proc}, il cui -prototipo è: -\begin{functions} - \headdecl{sys/capability.h} - - \funcdecl{int cap\_set\_proc(cap\_t cap\_p)} - Imposta le \textit{capabilities} del processo corrente. - - \bodydesc{La funzione ritorna 0 in caso di successo e $-1$ in caso di - errore, nel qual caso \var{errno} può assumere i valori \errval{EINVAL}, - \errval{EPERM} o \errval{ENOMEM}. - } -\end{functions} - -La funzione modifica le \textit{capabilities} del processo corrente secondo -quanto specificato con l'argomento \param{cap\_p}, posto che questo sia -possibile nei termini spiegati in precedenza (non sarà ad esempio possibile -impostare capacità non presenti nell'insieme di quelle permesse). In caso di -successo i nuovi valori saranno effettivi al ritorno della funzione, in caso -di fallimento invece lo stato delle capacità resterà invariato. Si tenga -presente che \textsl{tutte} le capacità specificate tramite \param{cap\_p} -devono essere permesse; se anche una sola non lo è la funzione fallirà, e per -quanto appena detto, lo stato delle \textit{capabilities} non verrà modificato -(neanche per le parti eventualmente permesse). - -Come esempio di utilizzo di queste funzioni nei sorgenti allegati alla guida -si è distribuito il programma \texttt{getcap.c}, che consente di leggere le -\textit{capabilities} del processo corrente\footnote{vale a dire di sé stesso, - quando lo si lancia, il che può sembrare inutile, ma serve a mostrarci quali - sono le \textit{capabilities} standard che ottiene un processo lanciato - dalla riga di comando.} o tramite l'opzione \texttt{-p}, quelle di un -processo qualunque il cui pid viene passato come parametro dell'opzione. - -\begin{figure}[htb] - \footnotesize \centering - \begin{minipage}[c]{15cm} - \includecodesample{listati/getcap.c} - \end{minipage} - \normalsize - \caption{Corpo principale del programma \texttt{getcap.c}.} - \label{fig:proc_getcap} -\end{figure} - -La sezione principale del programma è riportata in fig.~\ref{fig:proc_getcap}, -e si basa su una condizione sulla variabile \var{pid} che se si è usato -l'opzione \texttt{-p} è impostata (nella sezione di gestione delle opzioni, -che si è tralasciata) al valore del \textsl{pid} del processo di cui si vuole -leggere le \textit{capabilities} e nulla altrimenti. Nel primo caso -(\texttt{\small 1--6}) si utilizza direttamente (\texttt{\small 2}) -\func{cap\_get\_proc} per ottenere lo stato delle capacità del processo, nel -secondo (\texttt{\small 7--14}) prima si inizializza (\texttt{\small 8}) uno -stato vuoto e poi (\texttt{\small 9}) si legge il valore delle capacità del -processo indicato. - -Il passo successivo è utilizzare (\texttt{\small 16}) \func{cap\_to\_text} per -tradurre in una stringa lo stato, e poi (\texttt{\small 17}) stamparlo; infine -(\texttt{\small 19--20}) si libera la memoria allocata dalle precedenti -funzioni con \func{cap\_free} per poi ritornare dal ciclo principale della -funzione. - -\itindend{capabilities} - -% TODO vedi http://lwn.net/Articles/198557/ e -% http://www.madore.org/~david/linux/newcaps/ -% TODO documentare prctl ... - -\subsection{Gli attributi estesi} -\label{sec:file_xattr} - -\itindbeg{Extended~Attributes} +\itindbeg{Access~Control~List~(ACL)} -Nelle sezioni precedenti abbiamo trattato in dettaglio le varie informazioni -che il sistema mantiene negli \itindex{inode} \textit{inode}, e le varie -funzioni che permettono di modificarle. Si sarà notato come in realtà queste -informazioni siano estremamente ridotte. Questo è dovuto al fatto che Unix -origina negli anni '70, quando le risorse di calcolo e di spazio disco erano -minime. Con il venir meno di queste restrizioni è incominciata ad emergere -l'esigenza di poter associare ai file delle ulteriori informazioni astratte -(quelli che vengono chiamati i \textsl{meta-dati}) che però non potevano -trovare spazio nei dati classici mantenuti negli \itindex{inode} -\textit{inode}. +Il modello classico dei permessi di Unix, per quanto funzionale ed efficiente, +è comunque piuttosto limitato e per quanto possa aver coperto per lunghi anni +le esigenze più comuni con un meccanismo semplice e potente, non è in grado di +rispondere in maniera adeguata a situazioni che richiedono una gestione +complessa dei permessi di accesso.\footnote{già un requisito come quello di + dare accesso in scrittura ad alcune persone ed in sola lettura ad altre non + si può soddisfare in maniera semplice.} -Per risolvere questo problema alcuni sistemi unix-like (e fra questi anche -Linux) hanno introdotto un meccanismo generico che consenta di associare delle -informazioni ai singoli file,\footnote{l'uso più comune è quello della ACL, - che tratteremo nella prossima sezione, ma si possono inserire anche altre - informazioni.} detto \textit{Extended Attributes}. Gli \textsl{attributi - estesi} non sono altro che delle coppie nome/valore che sono associate -permanentemente ad un oggetto sul filesystem, analoghi di quello che sono le -variabili di ambiente (vedi sez.~\ref{sec:proc_environ}) per un processo. +Per questo motivo erano state progressivamente introdotte nelle varie versioni +di Unix dei meccanismi di gestione dei permessi dei file più flessibili, nella +forma delle cosiddette \textit{Access Control List} (indicate usualmente con +la sigla ACL). Nello sforzo di standardizzare queste funzionalità era stato +creato un gruppo di lavoro il cui scopo era estendere lo standard POSIX 1003 +attraverso due nuovi insiemi di specifiche, la POSIX 1003.1e per l'interfaccia +di programmazione e la POSIX 1003.2c per i comandi di shell. -Altri sistemi (come Solaris, MacOS e Windows) hanno adottato un meccanismo -diverso in cui ad un file sono associati diversi flussi di dati, su cui -possono essere mantenute ulteriori informazioni, che possono essere accedute -con le normali operazioni di lettura e scrittura. Questi non vanno confusi con -gli \textit{Extended Attributes} (anche se su Solaris hanno lo stesso nome), -che sono un meccanismo molto più semplice, che pur essendo limitato (potendo -contenere solo una quantità limitata di informazione) hanno il grande -vantaggio di essere molto più semplici da realizzare, più -efficienti,\footnote{cosa molto importante, specie per le applicazioni che - richiedono una gran numero di accessi, come le ACL.} e di garantire -l'atomicità di tutte le operazioni. +Gli obiettivi erano però forse troppo ambizioni, e nel gennaio del 1998 i +finanziamenti vennero ritirati senza che si fosse arrivati alla definizione di +uno standard, dato però che una parte della documentazione prodotta era di +alta qualità venne deciso di rilasciare al pubblico la diciassettesima bozza +del documento, quella che va sotto il nome di \textit{POSIX 1003.1e Draft 17}, +che è divenuta la base sulla quale si definiscono le cosiddette \textit{Posix + ACL}. -In Linux gli attributi estesi sono sempre associati al singolo \itindex{inode} -\textit{inode} e l'accesso viene sempre eseguito in forma atomica, in lettura -il valore corrente viene scritto su un buffer in memoria, mentre la scrittura -prevede che ogni valore precedente sia sovrascritto. +A differenza di altri sistemi (ad esempio FreeBSD) nel caso di Linux si è +scelto di realizzare le ACL attraverso l'uso degli +\itindex{Extended~Attributes} \textit{Extended Attributes} (appena trattati in +sez.~\ref{sec:file_xattr}), e fornire tutte le relative funzioni di gestione +tramite una libreria, \texttt{libacl} che nasconde i dettagli implementativi +delle ACL e presenta ai programmi una interfaccia che fa riferimento allo +standard POSIX 1003.1e. -Si tenga presente che non tutti i filesystem supportano gli \textit{Extended - Attributes}, in particolare al momento della scrittura di queste dispense -essi sono presenti solo su \textsl{ext2}, \textsl{ext3} e \textsl{XFS}. -Inoltre a seconda della implementazione ci possono essere dei limiti sulla -quantità di attributi che si possono utilizzare.\footnote{ad esempio nel caso - di \textsl{ext2} ed \textsl{ext3} è richiesto che essi siano contenuti - all'interno di un singolo blocco (pertanto con dimensioni massime pari a - 1024, 2048 o 4096 byte a seconda delle dimensioni di quest'ultimo impostate - in fase di creazione del filesystem), mentre con \textsl{XFS} non ci sono - limiti ed i dati vengono memorizzati in maniera diversa (nell'\textit{inode} - stesso, in un blocco a parte, o in una struttura ad albero dedicata) per - mantenerne la scalabilità.} Infine lo spazio utilizzato per mantenere gli -attributi estesi viene tenuto in conto per il calcolo delle quote di utente e -gruppo proprietari del file. +Anche in questo caso le funzioni di questa libreria non fanno parte delle +\acr{glibc} e devono essere installate a parte;\footnote{la versione corrente + della libreria è \texttt{libacl1}, e nel caso si usi Debian la si può + installare con il pacchetto omonimo e con il collegato \texttt{libacl1-dev} + per i file di sviluppo.} pertanto se un programma le utilizza si dovrà +indicare esplicitamente l'uso della libreria \texttt{libacl} invocando il +compilatore con l'opzione \texttt{-lacl}. Si tenga presente inoltre che per +poterle utilizzare le ACL devono essere attivate esplicitamente montando il +filesystem\footnote{che deve supportarle, ma questo è ormai vero per + praticamente tutti i filesystem più comuni, con l'eccezione di NFS per il + quale esiste però un supporto sperimentale.} su cui le si vogliono +utilizzare con l'opzione \texttt{acl} attiva. Dato che si tratta di una +estensione è infatti opportuno utilizzarle soltanto laddove siano necessarie. -Come meccanismo per mantenere informazioni aggiuntive associate al singolo -file, gli \textit{Extended Attributes} possono avere usi anche molto diversi -fra loro. Per poterli distinguere allora sono stati suddivisi in -\textsl{classi}, a cui poter applicare requisiti diversi per l'accesso e la -gestione. Per questo motivo il nome di un attributo deve essere sempre -specificato nella forma \texttt{namespace.attribute}, dove \texttt{namespace} -fa riferimento alla classe a cui l'attributo appartiene, mentre -\texttt{attribute} è il nome ad esso assegnato. In tale forma il nome di un -attributo esteso deve essere univoco. Al momento\footnote{della scrittura di - questa sezione, kernel 2.6.23, ottobre 2007.} sono state definite le quattro -classi di attributi riportate in tab.~\ref{tab:extended_attribute_class}. +Una ACL è composta da un insieme di voci, e ciascuna voce è a sua volta +costituita da un \textsl{tipo}, da un eventuale +\textsl{qualificatore},\footnote{deve essere presente soltanto per le voci di + tipo \const{ACL\_USER} e \const{ACL\_GROUP}.} e da un insieme di permessi. +Ad ogni oggetto sul filesystem si può associare una ACL che ne governa i +permessi di accesso, detta \textit{access ACL}. Inoltre per le directory si +può impostare una ACL aggiuntiva, detta \textit{default ACL}, che serve ad +indicare quale dovrà essere la ACL assegnata di default nella creazione di un +file all'interno della directory stessa. Come avviene per i permessi le ACL +possono essere impostate solo del proprietario del file, o da un processo con +la capability \index{capabilities} \const{CAP\_FOWNER}. \begin{table}[htb] \centering \footnotesize - \begin{tabular}{|l|p{10cm}|} + \begin{tabular}{|l|p{8cm}|} \hline - \textbf{Nome} & \textbf{Descrizione} \\ + \textbf{Tipo} & \textbf{Descrizione} \\ \hline \hline - \texttt{security}&Gli \textit{extended security attributes}: vengono - utilizzati dalle estensioni di sicurezza del kernel (i - \itindex{Linux~Security~Modules} \textit{Linux - Security Modules}), per le realizzazione di meccanismi - evoluti di controllo di accesso come \index{SELinux} - SELinux o le \textit{capabilities} dei file di - sez.~\ref{sec:proc_capabilities}.\\ - \texttt{system} & Gli \textit{extended security attributes}: sono usati - dal kernel per memorizzare dati di sistema associati ai - file come le \itindex{Access~Control~List} ACL (vedi - sez.~\ref{sec:file_ACL}) o le \itindex{capabilities} - \textit{capabilities} (vedi - sez.~\ref{sec:proc_capabilities}).\\ - \texttt{trusted}& I \textit{trusted extended attributes}: vengono - utilizzati per poter realizzare in user space - meccanismi che consentano di mantenere delle - informazioni sui file che non devono essere accessibili - ai processi ordinari.\\ - \texttt{user} & Gli \textit{extended user attributes}: utilizzati per - mantenere informazioni aggiuntive sui file (come il - \textit{mime-type}, la codifica dei caratteri o del - file) accessibili dagli utenti.\\ + \const{ACL\_USER\_OBJ} & voce che contiene i diritti di accesso del + proprietario del file.\\ + \const{ACL\_USER} & voce che contiene i diritti di accesso per + l'utente indicato dal rispettivo + qualificatore.\\ + \const{ACL\_GROUP\_OBJ}& voce che contiene i diritti di accesso del + gruppo proprietario del file.\\ + \const{ACL\_GROUP} & voce che contiene i diritti di accesso per + il gruppo indicato dal rispettivo + qualificatore.\\ + \const{ACL\_MASK} & voce che contiene la maschera dei massimi + permessi di accesso che possono essere garantiti + da voci del tipo \const{ACL\_USER}, + \const{ACL\_GROUP} e \const{ACL\_GROUP\_OBJ}.\\ + \const{ACL\_OTHER} & voce che contiene i diritti di accesso di chi + non corrisponde a nessuna altra voce dell'ACL.\\ \hline \end{tabular} - \caption{I nomi utilizzati valore di \texttt{namespace} per distinguere le - varie classi di \textit{Extended Attributes}.} - \label{tab:extended_attribute_class} + \caption{Le costanti che identificano i tipi delle voci di una ACL.} + \label{tab:acl_tag_types} \end{table} +L'elenco dei vari tipi di voci presenti in una ACL, con una breve descrizione +del relativo significato, è riportato in tab.~\ref{tab:acl_tag_types}. Tre di +questi tipi, \const{ACL\_USER\_OBJ}, \const{ACL\_GROUP\_OBJ} e +\const{ACL\_OTHER}, corrispondono direttamente ai tre permessi ordinari dei +file (proprietario, gruppo proprietario e tutti gli altri) e per questo una +ACL valida deve sempre contenere una ed una sola voce per ciascuno di questi +tipi. -Dato che uno degli usi degli \textit{Extended Attributes} è quello che li -impiega per realizzare delle estensioni (come le \itindex{Access~Control~List} -ACL, \index{SELinux} SELinux, ecc.) al tradizionale meccanismo dei controlli -di accesso di Unix, l'accesso ai loro valori viene regolato in maniera diversa -a seconda sia della loro classe sia di quali, fra le estensioni che li -utilizzano, sono poste in uso. In particolare, per ciascuna delle classi -riportate in tab.~\ref{tab:extended_attribute_class}, si hanno i seguenti -casi: -\begin{basedescript}{\desclabelwidth{1.7cm}\desclabelstyle{\nextlinelabel}} -\item[\texttt{security}] L'accesso agli \textit{extended security attributes} - dipende dalle politiche di sicurezza stabilite da loro stessi tramite - l'utilizzo di un sistema di controllo basato sui - \itindex{Linux~Security~Modules} \textit{Linux Security Modules} (ad esempio - \index{SELinux} SELinux). Pertanto l'accesso in lettura o scrittura dipende - dalle politiche di sicurezza implementate all'interno dal modulo di - sicurezza che si sta utilizzando al momento (ciascuno avrà le sue). Se non è - stato caricato nessun modulo di sicurezza l'accesso in lettura sarà - consentito a tutti i processi, mentre quello in scrittura solo ai processi - con privilegi amministrativi dotati della \index{capabilities} - \textit{capability} \const{CAP\_SYS\_ADMIN}. +Una ACL può poi contenere un numero arbitrario di voci di tipo +\const{ACL\_USER} e \const{ACL\_GROUP}, ciascuna delle quali indicherà i +permessi assegnati all'utente e al gruppo indicato dal relativo qualificatore; +ovviamente ciascuna di queste voci dovrà fare riferimento ad un utente o ad un +gruppo diverso, e non corrispondenti a quelli proprietari del file. Inoltre se +in una ACL esiste una voce di uno di questi due tipi è obbligatoria anche la +presenza di una ed una sola voce di tipo \const{ACL\_MASK}, che negli altri +casi è opzionale. -\item[\texttt{system}] Anche l'accesso agli \textit{extended system - attributes} dipende dalle politiche di accesso che il kernel realizza - anche utilizzando gli stessi valori in essi contenuti. Ad esempio nel caso - delle \itindex{Access~Control~List} ACL l'accesso è consentito in lettura ai - processi che hanno la capacità di eseguire una ricerca sul file (cioè hanno - il permesso di lettura sulla directory che contiene il file) ed in scrittura - al proprietario del file o ai processi dotati della \textit{capability} - \index{capabilities} \const{CAP\_FOWNER}.\footnote{vale a dire una politica - di accesso analoga a quella impiegata per gli ordinari permessi dei file.} +Quest'ultimo tipo di voce contiene la maschera dei permessi che possono essere +assegnati tramite voci di tipo \const{ACL\_USER}, \const{ACL\_GROUP} e +\const{ACL\_GROUP\_OBJ}; se in una di queste voci si fosse specificato un +permesso non presente in \const{ACL\_MASK} questo verrebbe ignorato. L'uso di +una ACL di tipo \const{ACL\_MASK} è di particolare utilità quando essa +associata ad una \textit{default ACL} su una directory, in quanto i permessi +così specificati verranno ereditati da tutti i file creati nella stessa +directory. Si ottiene così una sorta di \itindex{umask} \textit{umask} +associata ad un oggetto sul filesystem piuttosto che a un processo. -\item[\texttt{trusted}] L'accesso ai \textit{trusted extended attributes}, sia - per la lettura che per la scrittura, è consentito soltanto ai processi con - privilegi amministrativi dotati della \index{capabilities} - \textit{capability} \const{CAP\_SYS\_ADMIN}. In questo modo si possono - utilizzare questi attributi per realizzare in user space dei meccanismi di - controllo che accedono ad informazioni non disponibili ai processi ordinari. +Dato che le ACL vengono a costituire una estensione dei permessi ordinari, uno +dei problemi che si erano posti nella loro standardizzazione era appunto +quello della corrispondenza fra questi e le ACL. Come accennato i permessi +ordinari vengono mappati le tre voci di tipo \const{ACL\_USER\_OBJ}, +\const{ACL\_GROUP\_OBJ} e \const{ACL\_OTHER} che devono essere presenti in +qualunque ACL; un cambiamento ad una di queste voci viene automaticamente +riflesso sui permessi ordinari dei file\footnote{per permessi ordinari si + intende quelli mantenuti nell'\textit{inode}, che devono restare dato che un + filesystem può essere montato senza abilitare le ACL.} e viceversa. In +realtà la mappatura è diretta solo per le voci \const{ACL\_USER\_OBJ} e +\const{ACL\_OTHER}, nel caso di \const{ACL\_GROUP\_OBJ} questo vale soltanto +se non è presente una voce di tipo \const{ACL\_MASK}, se invece questa è +presente verranno tolti dai permessi di \const{ACL\_GROUP\_OBJ} tutti quelli +non presenti in \const{ACL\_MASK}.\footnote{questo diverso comportamento a + seconda delle condizioni è stato introdotto dalla standardizzazione + \textit{POSIX 1003.1e Draft 17} per mantenere il comportamento invariato sui + sistemi dotati di ACL per tutte quelle applicazioni che sono conformi + soltanto all'ordinario standard \textit{POSIX 1003.1}.} -\item[\texttt{user}] L'accesso agli \textit{extended user attributes} è - regolato dai normali permessi dei file: occorre avere il permesso di lettura - per leggerli e quello di scrittura per scriverli o modificarli. Dato l'uso - di questi attributi si è scelto di applicare al loro accesso gli stessi - criteri che si usano per l'accesso al contenuto dei file (o delle directory) - cui essi fanno riferimento. Questa scelta vale però soltanto per i file e le - directory ordinarie, se valesse in generale infatti si avrebbe un serio - problema di sicurezza dato che esistono diversi oggetti sul filesystem per i - quali è normale avere avere il permesso di scrittura consentito a tutti gli - utenti, come i link simbolici, o alcuni \index{file!di~dispositivo} file di - dispositivo come \texttt{/dev/null}. Se fosse possibile usare su di essi gli - \textit{extended user attributes} un utente qualunque potrebbe inserirvi - dati a piacere.\footnote{la cosa è stata notata su XFS, dove questo - comportamento permetteva, non essendovi limiti sullo spazio occupabile - dagli \textit{Extended Attributes}, di bloccare il sistema riempiendo il - disco.} +Un secondo aspetto dell'incidenza delle ACL sul comportamento del sistema è +quello relativo alla creazione di nuovi file,\footnote{o oggetti sul + filesystem, il comportamento discusso vale per le funzioni \func{open} e + \func{creat} (vedi sez.~\ref{sec:file_open}), \func{mkdir} (vedi + sez.~\ref{sec:file_dir_creat_rem}), \func{mknod} e \func{mkfifo} (vedi + sez.~\ref{sec:file_mknod}).} che come accennato può essere modificato dalla +presenza di una \textit{default ACL} sulla directory che contiene quel file. +Se questa non c'è valgono le regole usuali illustrate in +sez.~\ref{sec:file_perm_management}, per cui essi sono determinati dalla +\itindex{umask} \textit{umask} del processo, e la sola differenza è che i +permessi ordinari da esse risultanti vengono automaticamente rimappati anche +su una ACL di accesso assegnata automaticamente al nuovo file, che contiene +soltanto le tre corrispondenti voci di tipo \const{ACL\_USER\_OBJ}, +\const{ACL\_GROUP\_OBJ} e \const{ACL\_OTHER}. - La semantica del controllo di accesso indicata inoltre non avrebbe alcun - senso al di fuori di file e directory: i permessi di lettura e scrittura per - un \index{file!di~dispositivo} file di dispositivo attengono alle capacità - di accesso al dispositivo sottostante,\footnote{motivo per cui si può - formattare un disco anche se \texttt{/dev} è su un filesystem in sola - lettura.} mentre per i link simbolici questi vengono semplicemente - ignorati: in nessuno dei due casi hanno a che fare con il contenuto del - file, e nella discussione relativa all'uso degli \textit{extended user - attributes} nessuno è mai stato capace di indicare una qualche forma - sensata di utilizzo degli stessi per link simbolici o - \index{file!di~dispositivo} file di dispositivo, e neanche per le fifo o i - socket. Per questo motivo essi sono stati completamente disabilitati per - tutto ciò che non sia un file regolare o una directory.\footnote{si può - verificare la semantica adottata consultando il file \texttt{fs/xattr.c} - dei sorgenti del kernel.} Inoltre per le directory è stata introdotta una - ulteriore restrizione, dovuta di nuovo alla presenza ordinaria di permessi - di scrittura completi su directory come \texttt{/tmp}. Per questo motivo, - per evitare eventuali abusi, se una directory ha lo \itindex{sticky~bit} - \textit{sticky bit} attivo sarà consentito scrivere i suoi \textit{extended - user attributes} soltanto se si è proprietari della stessa, o si hanno i - privilegi amministrativi della capability \index{capabilities} - \const{CAP\_FOWNER}. -\end{basedescript} +Se invece è presente una ACL di default sulla directory che contiene il nuovo +file questa diventerà automaticamente la sua ACL di accesso, a meno di non +aver indicato, nelle funzioni di creazione che lo consentono, uno specifico +valore per i permessi ordinari;\footnote{tutte le funzioni citate in + precedenza supportano un argomento \var{mode} che indichi un insieme di + permessi iniziale.} in tal caso saranno eliminati dalle voci corrispondenti +nella ACL tutti quelli non presenti in tale indicazione. -Le funzioni per la gestione degli attributi estesi, come altre funzioni di -gestione avanzate specifiche di Linux, non fanno parte delle \acr{glibc}, e -sono fornite da una apposita libreria, \texttt{libattr}, che deve essere -installata a parte;\footnote{la versione corrente della libreria è - \texttt{libattr1}.} pertanto se un programma le utilizza si dovrà indicare -esplicitamente l'uso della suddetta libreria invocando il compilatore con -l'opzione \texttt{-lattr}. +Dato che questa è la ragione che ha portato alla loro creazione, la principale +modifica introdotta con la presenza della ACL è quella alle regole del +controllo di accesso ai file illustrate in sez.~\ref{sec:file_perm_overview}. +Come nel caso ordinario per il controllo vengono sempre utilizzati gli +identificatori del gruppo \textit{effective} del processo, ma in presenza di +ACL i passi attraverso i quali viene stabilito se esso ha diritto di accesso +sono i seguenti: +\begin{enumerate*} +\item Se l'user-ID del processo è nullo l'accesso è sempre garantito senza + nessun controllo. +\item Se l'user-ID del processo corrisponde al proprietario del file allora: + \begin{itemize*} + \item se la voce \const{ACL\_USER\_OBJ} contiene il permesso richiesto, + l'accesso è consentito; + \item altrimenti l'accesso è negato. + \end{itemize*} +\item Se l'user-ID del processo corrisponde ad un qualunque qualificatore + presente in una voce \const{ACL\_USER} allora: + \begin{itemize*} + \item se la voce \const{ACL\_USER} corrispondente e la voce + \const{ACL\_MASK} contengono entrambe il permesso richiesto, l'accesso è + consentito; + \item altrimenti l'accesso è negato. + \end{itemize*} +\item Se è il group-ID del processo o uno dei group-ID supplementari + corrisponde al gruppo proprietario del file allora: + \begin{itemize*} + \item se la voce \const{ACL\_GROUP\_OBJ} e una eventuale voce + \const{ACL\_MASK} (se non vi sono voci di tipo \const{ACL\_GROUP} questa + può non essere presente) contengono entrambe il permesso richiesto, + l'accesso è consentito; + \item altrimenti l'accesso è negato. + \end{itemize*} +\item Se è il group-ID del processo o uno dei group-ID supplementari + corrisponde ad un qualunque qualificatore presente in una voce + \const{ACL\_GROUP} allora: + \begin{itemize*} + \item se la voce \const{ACL\_GROUP} corrispondente e la voce + \const{ACL\_MASK} contengono entrambe il permesso richiesto, l'accesso è + consentito; + \item altrimenti l'accesso è negato. + \end{itemize*} +\item Se la voce \const{ACL\_USER\_OBJ} contiene il permesso richiesto, + l'accesso è consentito, altrimenti l'accesso è negato. +\end{enumerate*} -Per poter leggere gli attributi estesi sono disponibili tre diverse funzioni, -\funcd{getxattr}, \funcd{lgetxattr} e \funcd{fgetxattr}, che consentono -rispettivamente di richiedere gli attributi relativi a un file, a un link -simbolico e ad un file descriptor; i rispettivi prototipi sono: +I passi di controllo vengono eseguiti esattamente in questa sequenza, e la +decisione viene presa non appena viene trovata una corrispondenza con gli +identificatori del processo. Questo significa che i permessi presenti in una +voce di tipo \const{ACL\_USER} hanno la precedenza sui permessi ordinari +associati al gruppo proprietario del file (vale a dire su +\const{ACL\_GROUP\_OBJ}). + +Per la gestione delle ACL lo standard \textit{POSIX 1003.1e Draft 17} ha +previsto delle apposite funzioni ed tutta una serie di tipi di dati +dedicati;\footnote{fino a definire un tipo di dato e delle costanti apposite + per identificare i permessi standard di lettura, scrittura ed esecuzione.} +tutte le operazioni devono essere effettuate attraverso tramite questi tipi di +dati, che incapsulano tutte le informazioni contenute nelle ACL. La prima di +queste funzioni che prendiamo in esame è \funcd{acl\_init}, il cui prototipo +è: \begin{functions} \headdecl{sys/types.h} - \headdecl{attr/xattr.h} + \headdecl{sys/acl.h} - \funcdecl{ssize\_t getxattr(const char *path, const char *name, void - *value, size\_t size)} - - \funcdecl{ssize\_t lgetxattr(const char *path, const char *name, void - *value, size\_t size)} - - \funcdecl{ssize\_t fgetxattr(int filedes, const char *name, void *value, - size\_t size)} + \funcdecl{acl\_t acl\_init(int count)} - Le funzioni leggono il valore di un attributo esteso. + Inizializza un'area di lavoro per una ACL di \param{count} voci. - \bodydesc{Le funzioni restituiscono un intero positivo che indica la - dimensione dell'attributo richiesto in caso di successo, e $-1$ in caso di - errore, nel qual caso \var{errno} assumerà i valori: + \bodydesc{La funzione restituisce un puntatore all'area di lavoro in caso di + successo e \val{NULL} in caso di errore, nel qual caso \var{errno} + assumerà uno dei valori: \begin{errlist} - \item[\errcode{ENOATTR}] l'attributo richiesto non esiste. - \item[\errcode{ERANGE}] la dimensione \param{size} del buffer \param{value} - non è sufficiente per contenere il risultato. - \item[\errcode{ENOTSUP}] gli attributi estesi non sono supportati dal - filesystem o sono disabilitati. + \item[\errcode{EINVAL}] il valore di \param{count} è negativo. + \item[\errcode{ENOMEM}] non c'è sufficiente memoria disponibile. \end{errlist} - e tutti gli errori di \func{stat}, come \errcode{EPERM} se non si hanno i - permessi di accesso all'attributo. } +} \end{functions} -Le funzioni \func{getxattr} e \func{lgetxattr} prendono come primo argomento -un pathname che indica il file di cui si vuole richiedere un attributo, la -sola differenza è che la seconda, se il pathname indica un link simbolico, -restituisce gli attributi di quest'ultimo e non quelli del file a cui esso fa -riferimento. La funzione \func{fgetxattr} prende invece come primo argomento -un numero di file descriptor, e richiede gli attributi del file ad esso -associato. - -Tutte e tre le funzioni richiedono di specificare nell'argomento \param{name} -il nome dell'attributo di cui si vuole ottenere il valore. Il nome deve essere -indicato comprensivo di prefisso del \textit{namespace} cui appartiene (uno -dei valori di tab.~\ref{tab:extended_attribute_class}) nella forma -\texttt{namespace.attributename}, come stringa terminata da un carattere NUL. -Il suo valore verrà restituito nel buffer puntato dall'argomento \param{value} -per una dimensione massima di \param{size} byte;\footnote{gli attributi estesi - possono essere costituiti arbitrariamente da dati testuali o binari.} se -quest'ultima non è sufficiente si avrà un errore di \errcode{ERANGE}. - -Per evitare di dover indovinare la dimensione di un attributo per tentativi si -può eseguire una interrogazione utilizzando un valore nullo per \param{size}; -in questo caso non verrà letto nessun dato, ma verrà restituito come valore di -ritorno della funzione chiamata la dimensione totale dell'attributo esteso -richiesto, che si potrà usare come stima per allocare un buffer di dimensioni -sufficienti.\footnote{si parla di stima perché anche se le funzioni - restituiscono la dimensione esatta dell'attributo al momento in cui sono - eseguite, questa potrebbe essere modificata in qualunque momento da un - successivo accesso eseguito da un altro processo.} +La funzione alloca ed inizializza un'area di memoria che verrà usata per +mantenere i dati di una ACL contenente fino ad un massimo di \param{count} +voci. La funzione ritorna un valore di tipo \type{acl\_t}, da usare in tutte +le altre funzioni che operano sulla ACL. La funzione si limita alla +allocazione iniziale e non inserisce nessun valore nella ACL che resta vuota. +Si tenga presente che pur essendo \type{acl\_t} un \index{tipo!opaco} tipo +opaco che identifica ``\textsl{l'oggetto}'' ACL, il valore restituito dalla +funzione non è altro che un puntatore all'area di memoria allocata per i dati +richiesti; pertanto in caso di fallimento verrà restituito un puntatore nullo +e si dovrà confrontare il valore di ritorno della funzione con +``\code{(acl\_t) NULL}''. -Un secondo gruppo di funzioni è quello che consente di impostare il valore di -un attributo esteso, queste sono \funcd{setxattr}, \funcd{lsetxattr} e -\funcd{fsetxattr}, e consentono di operare rispettivamente su un file, su un -link simbolico o specificando un file descriptor; i loro prototipi sono: +Una volta che si siano completate le operazioni sui dati di una ACL la memoria +allocata dovrà essere liberata esplicitamente attraverso una chiamata alla +funzione \funcd{acl\_free}, il cui prototipo è: \begin{functions} \headdecl{sys/types.h} - \headdecl{attr/xattr.h} + \headdecl{sys/acl.h} - \funcdecl{int setxattr(const char *path, const char *name, const void - *value, size\_t size, int flags)} + \funcdecl{int acl\_free(void * obj\_p)} - \funcdecl{int lsetxattr(const char *path, const char *name, const void - *value, size\_t size, int flags)} + Disalloca la memoria riservata per i dati di una ACL. + + \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ se + \param{obj\_p} non è un puntatore valido, nel qual caso \var{errno} + assumerà il valore \errcode{EINVAL} +} +\end{functions} - \funcdecl{int fsetxattr(int filedes, const char *name, const void *value, - size\_t size, int flags)} +Si noti come la funzione richieda come argomento un puntatore di tipo +``\ctyp{void *}'', essa infatti può essere usata non solo per liberare la +memoria allocata per i dati di una ACL, ma anche per quella usata per creare +le stringhe di descrizione testuale delle ACL o per ottenere i valori dei +qualificatori di una voce; pertanto a seconda dei casi occorrerà eseguire un +\textit{cast} a ``\ctyp{void *}'' del tipo di dato di cui si vuole eseguire la +disallocazione. Si tenga presente poi che oltre a \func{acl\_init} esistono +molte altre funzioni che possono allocare memoria per i dati delle ACL, è +pertanto opportuno tenere traccia di tutte queste funzioni perché alla fine +delle operazioni tutta la memoria allocata dovrà essere liberata con +\func{acl\_free}. - Impostano il valore di un attributo esteso. +Una volta che si abbiano a disposizione i dati di una ACL tramite il +riferimento ad oggetto di tipo \type{acl\_t} questi potranno essere copiati +con la funzione \funcd{acl\_dup}, il cui prototipo è: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{sys/acl.h} - \bodydesc{Le funzioni restituiscono 0 in caso di successo, e $-1$ in caso di - errore, nel qual caso \var{errno} assumerà i valori: + \funcdecl{acl\_t acl\_dup(acl\_t acl)} + + Crea una copia della ACL \param{acl}. + + \bodydesc{La funzione restituisce un oggetto di tipo \type{acl\_t} in caso + di successo e \code{(acl\_t)NULL} in caso di errore, nel qual caso + \var{errno} assumerà uno dei valori: \begin{errlist} - \item[\errcode{ENOATTR}] si è usato il flag \const{XATTR\_REPLACE} e - l'attributo richiesto non esiste. - \item[\errcode{EEXIST}] si è usato il flag \const{XATTR\_CREATE} ma - l'attributo esiste già. - \item[\errcode{ENOTSUP}] gli attributi estesi non sono supportati dal - filesystem o sono disabilitati. + \item[\errcode{EINVAL}] l'argomento \param{acl} non è un puntatore valido + per una ACL. + \item[\errcode{ENOMEM}] non c'è sufficiente memoria disponibile per eseguire + la copia. \end{errlist} - Oltre a questi potranno essere restituiti tutti gli errori di \func{stat}, - ed in particolare \errcode{EPERM} se non si hanno i permessi di accesso - all'attributo. } \end{functions} -Le tre funzioni prendono come primo argomento un valore adeguato al loro -scopo, usato in maniera del tutto identica a quanto visto in precedenza per le -analoghe che leggono gli attributi estesi. Il secondo argomento \param{name} -deve indicare, anche in questo caso con gli stessi criteri appena visti per le -analoghe \func{getxattr}, \func{lgetxattr} e \func{fgetxattr}, il nome -(completo di suffisso) dell'attributo su cui si vuole operare. - -Il valore che verrà assegnato all'attributo dovrà essere preparato nel buffer -puntato da \param{value}, e la sua dimensione totale (in byte) sarà indicata -dall'argomento \param{size}. Infine l'argomento \param{flag} consente di -controllare le modalità di sovrascrittura dell'attributo esteso, esso può -prendere due valori: con \const{XATTR\_REPLACE} si richiede che l'attributo -esista, nel qual caso verrà sovrascritto, altrimenti si avrà errore, mentre -con \const{XATTR\_CREATE} si richiede che l'attributo non esista, nel qual -caso verrà creato, altrimenti si avrà errore ed il valore attuale non sarà -modificato. Utilizzando per \param{flag} un valore nullo l'attributo verrà -modificato se è già presente, o creato se non c'è. +La funzione crea una copia dei dati della ACL indicata tramite l'argomento +\param{acl}, allocando autonomamente tutto spazio necessario alla copia e +restituendo un secondo oggetto di tipo \type{acl\_t} come riferimento a +quest'ultima. Valgono per questo le stesse considerazioni fatte per il valore +di ritorno di \func{acl\_init}, ed in particolare il fatto che occorrerà +prevedere una ulteriore chiamata esplicita a \func{acl\_free} per liberare la +memoria occupata dalla copia. -Le funzioni finora illustrate permettono di leggere o scrivere gli attributi -estesi, ma sarebbe altrettanto utile poter vedere quali sono gli attributi -presenti; a questo provvedono le funzioni \funcd{listxattr}, -\funcd{llistxattr} e \funcd{flistxattr} i cui prototipi sono: +Se si deve creare una ACL manualmente l'uso di \func{acl\_init} è scomodo, +dato che la funzione restituisce una ACL vuota, una alternativa allora è usare +\funcd{acl\_from\_mode} che consente di creare una ACL a partire da un valore +di permessi ordinari, il prototipo della funzione è: \begin{functions} \headdecl{sys/types.h} - \headdecl{attr/xattr.h} + \headdecl{sys/acl.h} - \funcdecl{ssize\_t listxattr(const char *path, char *list, size\_t size)} + \funcdecl{acl\_t acl\_from\_mode(mode\_t mode)} - \funcdecl{ssize\_t llistxattr(const char *path, char *list, size\_t size)} + Crea una ACL inizializzata con i permessi di \param{mode}. + + \bodydesc{La funzione restituisce un oggetto di tipo \type{acl\_t} in caso + di successo e \code{(acl\_t)NULL} in caso di errore, nel qual caso + \var{errno} assumerà il valore \errval{ENOMEM}. - \funcdecl{ssize\_t flistxattr(int filedes, char *list, size\_t size)} +} +\end{functions} - Leggono la lista degli attributi estesi di un file. +La funzione restituisce una ACL inizializzata con le tre voci obbligatorie +\const{ACL\_USER\_OBJ}, \const{ACL\_GROUP\_OBJ} e \const{ACL\_OTHER} già +impostate secondo la corrispondenza ai valori dei permessi ordinari indicati +dalla maschera passata nell'argomento \param{mode}. Questa funzione è una +estensione usata dalle ACL di Linux e non è portabile, ma consente di +semplificare l'inizializzazione in maniera molto comoda. + +Altre due funzioni che consentono di creare una ACL già inizializzata sono +\funcd{acl\_get\_fd} e \funcd{acl\_get\_file}, che però sono per lo più +utilizzate per leggere la ACL corrente di un file; i rispettivi prototipi +sono: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{sys/acl.h} - \bodydesc{Le funzioni restituiscono un intero positivo che indica la - dimensione della lista in caso di successo, e $-1$ in caso di errore, nel - qual caso \var{errno} assumerà i valori: + \funcdecl{acl\_t acl\_get\_file(const char *path\_p, acl\_type\_t type)} + \funcdecl{acl\_t acl\_get\_fd(int fd)} + + Ottiene i dati delle ACL di un file. + + \bodydesc{La funzione restituisce un oggetto di tipo \type{acl\_t} in caso + di successo e \code{(acl\_t)NULL} in caso di errore, nel qual caso + \var{errno} assumerà uno dei valori: \begin{errlist} - \item[\errcode{ERANGE}] la dimensione \param{size} del buffer \param{value} - non è sufficiente per contenere il risultato. - \item[\errcode{ENOTSUP}] gli attributi estesi non sono supportati dal - filesystem o sono disabilitati. + \item[\errcode{ENOMEM}] non c'è memoria sufficiente per allocare i dati. + \item[\errcode{ENOTSUP}] il filesystem cui fa riferimento il file non + supporta le ACL. \end{errlist} - Oltre a questi potranno essere restituiti tutti gli errori di \func{stat}, - ed in particolare \errcode{EPERM} se non si hanno i permessi di accesso - all'attributo. + ed inoltre \errval{EBADF} per \func{acl\_get\_fd}, ed \errval{EINVAL} per + valori scorretti di \param{type} e tutti i possibili errori per l'accesso ad + un file per \func{acl\_get\_file}. + } \end{functions} -Come per le precedenti le tre funzioni leggono gli attributi rispettivamente -di un file, un link simbolico o specificando un file descriptor, da -specificare con il loro primo argomento. Gli altri due argomenti, identici per -tutte e tre, indicano rispettivamente il puntatore \param{list} al buffer dove -deve essere letta la lista e la dimensione \param{size} di quest'ultimo. +Le due funzioni ritornano, con un oggetto di tipo \type{acl\_t}, il valore +della ACL correntemente associata ad un file, che può essere identificato +tramite un file descriptor usando \func{acl\_get\_fd} o con un pathname usando +\func{acl\_get\_file}. Nel caso di quest'ultima funzione, che può richiedere +anche la ACL relativa ad una directory, il secondo argomento \param{type} +consente di specificare se si vuole ottenere la ACL di default o quella di +accesso. Questo argomento deve essere di tipo \type{acl\_type\_t} e può +assumere solo i due valori riportati in tab.~\ref{tab:acl_type}. -La lista viene fornita come sequenza non ordinata dei nomi dei singoli -attributi estesi (sempre comprensivi del prefisso della loro classe) ciascuno -dei quali è terminato da un carattere nullo. I nomi sono inseriti nel buffer -uno di seguito all'altro. Il valore di ritorno della funzione indica la -dimensione totale della lista in byte. +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}{|l|l|} + \hline + \textbf{Tipo} & \textbf{Descrizione} \\ + \hline + \hline + \const{ACL\_TYPE\_ACCESS} & indica una ACL di accesso.\\ + \const{ACL\_TYPE\_DEFAULT}& indica una ACL di default.\\ + \hline + \end{tabular} + \caption{Le costanti che identificano il tipo di ACL.} + \label{tab:acl_type} +\end{table} -Come per le funzioni di lettura dei singoli attributi se le dimensioni del -buffer non sono sufficienti si avrà un errore, ma è possibile ottenere dal -valore di ritorno della funzione una stima della dimensione totale della lista -usando per \param{size} un valore nullo. +Si tenga presente che nel caso di \func{acl\_get\_file} occorrerà che il +processo chiamante abbia privilegi di accesso sufficienti a poter leggere gli +attributi estesi dei file (come illustrati in sez.~\ref{sec:file_xattr}); +inoltre una ACL di tipo \const{ACL\_TYPE\_DEFAULT} potrà essere richiesta +soltanto per una directory, e verrà restituita solo se presente, altrimenti +verrà restituita una ACL vuota. -Infine per rimuovere semplicemente un attributo esteso, si ha a disposizione -un ultimo gruppo di funzioni: \funcd{removexattr}, \funcd{lremovexattr} e -\funcd{fremovexattr}; i rispettivi prototipi sono: +Infine si potrà creare una ACL direttamente dalla sua rappresentazione +testuale con la funzione \funcd{acl\_from\_text}, il cui prototipo è: \begin{functions} \headdecl{sys/types.h} - \headdecl{attr/xattr.h} + \headdecl{sys/acl.h} - \funcdecl{int removexattr(const char *path, const char *name)} - - \funcdecl{int lremovexattr(const char *path, const char *name)} - - \funcdecl{int fremovexattr(int filedes, const char *name)} - + \funcdecl{acl\_t acl\_from\_text(const char *buf\_p)} - Rimuovono un attributo esteso di un file. + Crea una ACL a partire dalla sua rappresentazione testuale. - \bodydesc{Le funzioni restituiscono 0 in caso di successo, e $-1$ in caso di - errore, nel qual caso \var{errno} assumerà i valori: + \bodydesc{La funzione restituisce un oggetto di tipo \type{acl\_t} in caso + di successo e \code{(acl\_t)NULL} in caso di errore, nel qual caso + \var{errno} assumerà uno dei valori: \begin{errlist} - \item[\errcode{ENOATTR}] l'attributo richiesto non esiste. - \item[\errcode{ENOTSUP}] gli attributi estesi non sono supportati dal - filesystem o sono disabilitati. + \item[\errcode{ENOMEM}] non c'è memoria sufficiente per allocare i dati. + \item[\errcode{EINVAL}] la rappresentazione testuale all'indirizzo + \param{buf\_p} non è valida. \end{errlist} - ed inoltre tutti gli errori di \func{stat}. + } \end{functions} -Le tre funzioni rimuovono l'attributo esteso indicato dall'argomento -\param{name} rispettivamente di un file, un link simbolico o specificando un -file descriptor, da specificare con il loro primo argomento. Anche in questo -caso l'argomento \param{name} deve essere specificato con le modalità già -illustrate in precedenza per le altre funzioni relative agli attributi estesi. - -\itindend{Extended~Attributes} - +La funzione prende come argomento il puntatore ad un buffer dove si è inserita +la rappresentazione testuale della ACL che si vuole creare, la memoria +necessaria viene automaticamente allocata ed in caso di successo viene +restituito come valore di ritorno un oggetto di tipo \type{acl\_t} con il +contenuto della stessa, che come per le precedenti funzioni, dovrà essere +disallocato esplicitamente al termine del suo utilizzo. -\subsection{Le \textit{Access Control List}} -\label{sec:file_ACL} +La rappresentazione testuale di una ACL è quella usata anche dai comandi +ordinari per la gestione delle ACL (\texttt{getfacl} e \texttt{setfacl}), che +prevede due diverse forme, estesa e breve, entrambe supportate da +\func{acl\_from\_text}. La forma estesa prevede che sia specificata una voce +per riga, nella forma: +\begin{Verbatim} + tipo:qualificatore:permessi +\end{Verbatim} +dove il tipo può essere uno fra \texttt{user}, \texttt{group}, \texttt{other} +e \texttt{mask}. Il qualificatore è presente solo per \texttt{user} e +\texttt{group} e indica l'utente o il gruppo a cui la voce si riferisce; i +permessi sono espressi con una tripletta di lettere analoga a quella usata per +i permessi dei file.\footnote{vale a dire \texttt{r} per il permesso di + lettura, \texttt{w} per il permesso di scrittura, \texttt{x} per il permesso + di esecuzione (scritti in quest'ordine) e \texttt{-} per l'assenza del + permesso.} -% la documentazione di sistema è nei pacchetti libacl1-dev e acl -% vedi anche http://www.suse.de/~agruen/acl/linux-acls/online/ +Va precisato che i due tipi \texttt{user} e \texttt{group} sono usati +rispettivamente per indicare delle voci relative ad utenti e +gruppi,\footnote{cioè per voci di tipo \const{ACL\_USER\_OBJ} e + \const{ACL\_USER} per \texttt{user} e \const{ACL\_GROUP\_OBJ} e + \const{ACL\_GROUP} per \texttt{group}.} applicate sia a quelli proprietari +del file che a quelli generici; quelle dei proprietari si riconoscono per +l'assenza di un qualificatore, ed in genere si scrivono per prima delle altre. +Il significato delle voci di tipo \texttt{mask} e \texttt{mark} è evidente. In +questa forma si possono anche inserire dei commenti precedendoli con il +carattere ``\texttt{\#}''. -\itindbeg{Access~Control~List} +La forma breve prevede invece la scrittura delle singole voci su una riga, +separate da virgole; come specificatori del tipo di voce si possono usare le +iniziali dei valori usati nella forma estesa (cioè ``\texttt{u}'', +``\texttt{g}'', ``\texttt{o}'' e ``\texttt{m}''), mentre le altri parte della +voce sono le stesse. In questo caso non sono consentiti permessi. -Il modello classico dei permessi di Unix, per quanto funzionale ed efficiente, -è comunque piuttosto limitato e per quanto possa aver coperto per lunghi anni -le esigenze più comuni con un meccanismo semplice e potente, non è in grado di -rispondere in maniera adeguata a situazioni che richiedono una gestione -complessa dei permessi di accesso.\footnote{già un requisito come quello di - dare accesso in scrittura ad alcune persone ed in sola lettura ad altre non - si può soddisfare in maniera semplice.} +Per la conversione inversa, che consente di ottenere la rappresentazione +testuale di una ACL, sono invece disponibili due funzioni, la prima delle due, +di uso più immediato, è \funcd{acl\_to\_text}, il cui prototipo è: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{sys/acl.h} + + \funcdecl{char * acl\_to\_text(acl\_t acl, ssize\_t *len\_p)} -Per questo motivo erano state progressivamente introdotte nelle varie versioni -di Unix dei meccanismi di gestione dei permessi dei file più flessibili, nella -forma delle cosiddette \textit{Access Control List} (indicate usualmente con -la sigla ACL). Nello sforzo di standardizzare queste funzionalità era stato -creato un gruppo di lavoro il cui scopo era estendere lo standard POSIX 1003 -attraverso due nuovi insiemi di specifiche, la POSIX 1003.1e per l'interfaccia -di programmazione e la POSIX 1003.2c per i comandi di shell. + Produce la rappresentazione testuale di una ACL. + + \bodydesc{La funzione restituisce il puntatore ad una stringa con la + rappresentazione testuale della ACL in caso di successo e + \code(acl\_t){NULL} in caso di errore, nel qual caso \var{errno} assumerà + uno dei valori: + \begin{errlist} + \item[\errcode{ENOMEM}] non c'è memoria sufficiente per allocare i dati. + \item[\errcode{EINVAL}] la ACL indicata da \param{acl} non è valida. + \end{errlist} -Gli obiettivi erano però forse troppo ambizioni, e nel gennaio del 1998 i -finanziamenti vennero ritirati senza che si fosse arrivati alla definizione di -uno standard, dato però che una parte della documentazione prodotta era di -alta qualità venne deciso di rilasciare al pubblico la diciassettesima bozza -del documento, quella che va sotto il nome di \textit{POSIX 1003.1e Draft 17}, -che è divenuta la base sulla quale si definiscono le cosiddette \textit{Posix - ACL}. +} +\end{functions} -A differenza di altri sistemi (ad esempio FreeBSD) nel caso di Linux si è -scelto di realizzare le ACL attraverso l'uso degli -\itindex{Extended~Attributes} \textit{Extended Attributes} (appena trattati in -sez.~\ref{sec:file_xattr}), e fornire tutte le relative funzioni di gestione -tramite una libreria, \texttt{libacl} che nasconde i dettagli implementativi -delle ACL e presenta ai programmi una interfaccia che fa riferimento allo -standard POSIX 1003.1e. +La funzione restituisce il puntatore ad una stringa terminata da NUL +contenente la rappresentazione in forma estesa della ACL passata come +argomento, ed alloca automaticamente la memoria necessaria. Questa dovrà poi +essere liberata, quando non più necessaria, con \func{acl\_free}. Se +nell'argomento \param{len\_p} si passa un valore puntatore ad una variabile +intera in questa verrà restituita la dimensione della stringa con la +rappresentazione testuale (non comprendente il carattere nullo finale). -Anche in questo caso le funzioni di questa libreria non fanno parte delle -\acr{glibc} e devono essere installate a parte;\footnote{la versione corrente - della libreria è \texttt{libacl1}, e nel caso si usi Debian la si può - installare con il pacchetto omonimo e con il collegato \texttt{libacl1-dev} - per i file di sviluppo.} pertanto se un programma le utilizza si dovrà -indicare esplicitamente l'uso della libreria \texttt{libacl} invocando il -compilatore con l'opzione \texttt{-lacl}. Si tenga presente inoltre che per -poterle utilizzare le ACL devono essere attivate esplicitamente montando il -filesystem\footnote{che deve supportarle, ma questo è ormai vero per - praticamente tutti i filesystem più comuni, con l'eccezione di NFS per il - quale esiste però un supporto sperimentale.} su cui le si vogliono -utilizzare con l'opzione \texttt{acl} attiva. Dato che si tratta di una -estensione è infatti opportuno utilizzarle soltanto laddove siano necessarie. +La seconda funzione, \funcd{acl\_to\_any\_text}, permette di controllare con +dovizia di dettagli la generazione della stringa contenente la +rappresentazione testuale della ACL, il suo prototipo è: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{sys/acl.h} + + \funcdecl{char * acl\_to\_any\_text(acl\_t acl, const char *prefix, char + separator, int options)} -Una ACL è composta da un insieme di voci, e ciascuna voce è a sua volta -costituita da un \textsl{tipo}, da un eventuale -\textsl{qualificatore},\footnote{deve essere presente soltanto per le voci di - tipo \const{ACL\_USER} e \const{ACL\_GROUP}.} e da un insieme di permessi. -Ad ogni oggetto sul filesystem si può associare una ACL che ne governa i -permessi di accesso, detta \textit{access ACL}. Inoltre per le directory si -può impostare una ACL aggiuntiva, detta \textit{default ACL}, che serve ad -indicare quale dovrà essere la ACL assegnata di default nella creazione di un -file all'interno della directory stessa. Come avviene per i permessi le ACL -possono essere impostate solo del proprietario del file, o da un processo con -la capability \index{capabilities} \const{CAP\_FOWNER}. + Produce la rappresentazione testuale di una ACL. + + \bodydesc{La funzione restituisce il puntatore ad una stringa con la + rappresentazione testuale della ACL in caso di successo e \val{NULL} in + caso di errore, nel qual caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{ENOMEM}] non c'è memoria sufficiente per allocare i dati. + \item[\errcode{EINVAL}] la ACL indicata da \param{acl} non è valida. + \end{errlist} + +} +\end{functions} + +La funzione converte in formato testo la ACL indicata dall'argomento +\param{acl}, usando il carattere \param{separator} come separatore delle +singole voci; se l'argomento \param{prefix} non è nullo la stringa da esso +indicata viene utilizzata come prefisso per le singole voci. + +L'ultimo argomento, \param{options}, consente di controllare la modalità con +cui viene generata la rappresentazione testuale. Un valore nullo fa si che +vengano usati gli identificatori standard \texttt{user}, \texttt{group}, +\texttt{other} e \texttt{mask} con i nomi di utenti e gruppi risolti rispetto +ai loro valori numerici. Altrimenti si può specificare un valore in forma di +maschera binaria, da ottenere con un OR aritmetico dei valori riportati in +tab.~\ref{tab:acl_to_text_options}. \begin{table}[htb] \centering @@ -4178,708 +3911,1881 @@ la capability \index{capabilities} \const{CAP\_FOWNER}. \textbf{Tipo} & \textbf{Descrizione} \\ \hline \hline - \const{ACL\_USER\_OBJ} & voce che contiene i diritti di accesso del - proprietario del file.\\ - \const{ACL\_USER} & voce che contiene i diritti di accesso per - l'utente indicato dal rispettivo - qualificatore.\\ - \const{ACL\_GROUP\_OBJ}& voce che contiene i diritti di accesso del - gruppo proprietario del file.\\ - \const{ACL\_GROUP} & voce che contiene i diritti di accesso per - il gruppo indicato dal rispettivo - qualificatore.\\ - \const{ACL\_MASK} & voce che contiene la maschera dei massimi - permessi di accesso che possono essere garantiti - da voci del tipo \const{ACL\_USER}, - \const{ACL\_GROUP} e \const{ACL\_GROUP\_OBJ}.\\ - \const{ACL\_OTHER} & voce che contiene i diritti di accesso di chi - non corrisponde a nessuna altra voce dell'ACL.\\ + \const{TEXT\_ABBREVIATE} & stampa le voci in forma abbreviata.\\ + \const{TEXT\_NUMERIC\_IDS} & non effettua la risoluzione numerica di + user-ID e group-ID.\\ + \const{TEXT\_SOME\_EFFECTIVE}& per ciascuna voce che contiene permessi che + vengono eliminati dalla \const{ACL\_MASK} + viene generato un commento con i permessi + effettivamente risultanti; il commento è + separato con un tabulatore.\\ + \const{TEXT\_ALL\_EFFECTIVE} & viene generato un commento con i permessi + effettivi per ciascuna voce che contiene + permessi citati nella \const{ACL\_MASK}, + anche quando questi non vengono modificati + da essa; il commento è separato con un + tabulatore.\\ + \const{TEXT\_SMART\_INDENT} & da usare in combinazione con le precedenti + \const{TEXT\_SOME\_EFFECTIVE} e + \const{TEXT\_ALL\_EFFECTIVE} aumenta + automaticamente il numero di spaziatori + prima degli eventuali commenti in modo da + mantenerli allineati.\\ \hline \end{tabular} - \caption{Le costanti che identificano i tipi delle voci di una ACL.} - \label{tab:acl_tag_types} + \caption{Possibili valori per l'argomento \param{options} di + \func{acl\_to\_any\_text}.} + \label{tab:acl_to_text_options} \end{table} -L'elenco dei vari tipi di voci presenti in una ACL, con una breve descrizione -del relativo significato, è riportato in tab.~\ref{tab:acl_tag_types}. Tre di -questi tipi, \const{ACL\_USER\_OBJ}, \const{ACL\_GROUP\_OBJ} e -\const{ACL\_OTHER}, corrispondono direttamente ai tre permessi ordinari dei -file (proprietario, gruppo proprietario e tutti gli altri) e per questo una -ACL valida deve sempre contenere una ed una sola voce per ciascuno di questi -tipi. +Come per \func{acl\_to\_text} anche in questo caso il buffer contenente la +rappresentazione testuale dell'ACL, di cui la funzione restituisce +l'indirizzo, viene allocato automaticamente, e dovrà essere esplicitamente +disallocato con una chiamata ad \func{acl\_free}. Si tenga presente infine che +questa funzione è una estensione specifica di Linux, e non è presente nella +bozza dello standard POSIX.1e. -Una ACL può poi contenere un numero arbitrario di voci di tipo -\const{ACL\_USER} e \const{ACL\_GROUP}, ciascuna delle quali indicherà i -permessi assegnati all'utente e al gruppo indicato dal relativo qualificatore; -ovviamente ciascuna di queste voci dovrà fare riferimento ad un utente o ad un -gruppo diverso, e non corrispondenti a quelli proprietari del file. Inoltre se -in una ACL esiste una voce di uno di questi due tipi è obbligatoria anche la -presenza di una ed una sola voce di tipo \const{ACL\_MASK}, che negli altri -casi è opzionale. +Per quanto utile per la visualizzazione o l'impostazione da comando delle ACL, +la forma testuale non è la più efficiente per poter memorizzare i dati +relativi ad una ACL, ad esempio quando si vuole eseguirne una copia a scopo di +archiviazione. Per questo è stata prevista la possibilità di utilizzare una +rappresentazione delle ACL in una apposita forma binaria contigua e +persistente. È così possibile copiare il valore di una ACL in un buffer e da +questa rappresentazione tornare indietro e generare una ACL. -Quest'ultimo tipo di voce contiene la maschera dei permessi che possono essere -assegnati tramite voci di tipo \const{ACL\_USER}, \const{ACL\_GROUP} e -\const{ACL\_GROUP\_OBJ}; se in una di queste voci si fosse specificato un -permesso non presente in \const{ACL\_MASK} questo verrebbe ignorato. L'uso di -una ACL di tipo \const{ACL\_MASK} è di particolare utilità quando essa -associata ad una \textit{default ACL} su una directory, in quanto i permessi -così specificati verranno ereditati da tutti i file creati nella stessa -directory. Si ottiene così una sorta di \itindex{umask} \textit{umask} -associata ad un oggetto sul filesystem piuttosto che a un processo. +Lo standard POSIX.1e prevede a tale scopo tre funzioni, la prima e più +semplice è \funcd{acl\_size}, che consente di ottenere la dimensione che avrà +la citata rappresentazione binaria, in modo da poter allocare per essa un +buffer di dimensione sufficiente, il suo prototipo è: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{sys/acl.h} + + \funcdecl{ssize\_t acl\_size(acl\_t acl)} -Dato che le ACL vengono a costituire una estensione dei permessi ordinari, uno -dei problemi che si erano posti nella loro standardizzazione era appunto -quello della corrispondenza fra questi e le ACL. Come accennato i permessi -ordinari vengono mappati le tre voci di tipo \const{ACL\_USER\_OBJ}, -\const{ACL\_GROUP\_OBJ} e \const{ACL\_OTHER} che devono essere presenti in -qualunque ACL; un cambiamento ad una di queste voci viene automaticamente -riflesso sui permessi ordinari dei file\footnote{per permessi ordinari si - intende quelli mantenuti nell'\textit{inode}, che devono restare dato che un - filesystem può essere montato senza abilitare le ACL.} e viceversa. In -realtà la mappatura è diretta solo per le voci \const{ACL\_USER\_OBJ} e -\const{ACL\_OTHER}, nel caso di \const{ACL\_GROUP\_OBJ} questo vale soltanto -se non è presente una voce di tipo \const{ACL\_MASK}, se invece questa è -presente verranno tolti dai permessi di \const{ACL\_GROUP\_OBJ} tutti quelli -non presenti in \const{ACL\_MASK}.\footnote{questo diverso comportamento a - seconda delle condizioni è stato introdotto dalla standardizzazione - \textit{POSIX 1003.1e Draft 17} per mantenere il comportamento invariato sui - sistemi dotati di ACL per tutte quelle applicazioni che sono conformi - soltanto all'ordinario standard \textit{POSIX 1003.1}.} + Determina la dimensione della rappresentazione binaria di una ACL. -Un secondo aspetto dell'incidenza delle ACL sul comportamento del sistema è -quello relativo alla creazione di nuovi file,\footnote{o oggetti sul - filesystem, il comportamento discusso vale per le funzioni \func{open} e - \func{creat} (vedi sez.~\ref{sec:file_open}), \func{mkdir} (vedi - sez.~\ref{sec:file_dir_creat_rem}), \func{mknod} e \func{mkfifo} (vedi - sez.~\ref{sec:file_mknod}).} che come accennato può essere modificato dalla -presenza di una \textit{default ACL} sulla directory che contiene quel file. -Se questa non c'è valgono le regole usuali illustrate in -sez.~\ref{sec:file_perm_management}, per cui essi sono determinati dalla -\itindex{umask} \textit{umask} del processo, e la sola differenza è che i -permessi ordinari da esse risultanti vengono automaticamente rimappati anche -su una ACL di accesso assegnata automaticamente al nuovo file, che contiene -soltanto le tre corrispondenti voci di tipo \const{ACL\_USER\_OBJ}, -\const{ACL\_GROUP\_OBJ} e \const{ACL\_OTHER}. + \bodydesc{La funzione restituisce in caso di successo la dimensione in byte + della rappresentazione binaria della ACL indicata da \param{acl} e $-1$ in + caso di errore, nel qual caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{EINVAL}] la ACL indicata da \param{acl} non è valida. + \end{errlist} -Se invece è presente una ACL di default sulla directory che contiene il nuovo -file questa diventerà automaticamente la sua ACL di accesso, a meno di non -aver indicato, nelle funzioni di creazione che lo consentono, uno specifico -valore per i permessi ordinari;\footnote{tutte le funzioni citate in - precedenza supportano un argomento \var{mode} che indichi un insieme di - permessi iniziale.} in tal caso saranno eliminati dalle voci corrispondenti -nella ACL tutti quelli non presenti in tale indicazione. +} +\end{functions} -Dato che questa è la ragione che ha portato alla loro creazione, la principale -modifica introdotta con la presenza della ACL è quella alle regole del -controllo di accesso ai file illustrate in sez.~\ref{sec:file_perm_overview}. -Come nel caso ordinario per il controllo vengono sempre utilizzati gli -identificatori del gruppo \textit{effective} del processo, ma in presenza di -ACL i passi attraverso i quali viene stabilito se esso ha diritto di accesso -sono i seguenti: -\begin{enumerate*} -\item Se l'user-ID del processo è nullo l'accesso è sempre garantito senza - nessun controllo. -\item Se l'user-ID del processo corrisponde al proprietario del file allora: - \begin{itemize*} - \item se la voce \const{ACL\_USER\_OBJ} contiene il permesso richiesto, - l'accesso è consentito; - \item altrimenti l'accesso è negato. - \end{itemize*} -\item Se l'user-ID del processo corrisponde ad un qualunque qualificatore - presente in una voce \const{ACL\_USER} allora: - \begin{itemize*} - \item se la voce \const{ACL\_USER} corrispondente e la voce - \const{ACL\_MASK} contengono entrambe il permesso richiesto, l'accesso è - consentito; - \item altrimenti l'accesso è negato. - \end{itemize*} -\item Se è il group-ID del processo o uno dei group-ID supplementari - corrisponde al gruppo proprietario del file allora: - \begin{itemize*} - \item se la voce \const{ACL\_GROUP\_OBJ} e una eventuale voce - \const{ACL\_MASK} (se non vi sono voci di tipo \const{ACL\_GROUP} questa - può non essere presente) contengono entrambe il permesso richiesto, - l'accesso è consentito; - \item altrimenti l'accesso è negato. - \end{itemize*} -\item Se è il group-ID del processo o uno dei group-ID supplementari - corrisponde ad un qualunque qualificatore presente in una voce - \const{ACL\_GROUP} allora: - \begin{itemize*} - \item se la voce \const{ACL\_GROUP} corrispondente e la voce - \const{ACL\_MASK} contengono entrambe il permesso richiesto, l'accesso è - consentito; - \item altrimenti l'accesso è negato. - \end{itemize*} -\item Se la voce \const{ACL\_USER\_OBJ} contiene il permesso richiesto, - l'accesso è consentito, altrimenti l'accesso è negato. +Prima di effettuare la lettura della rappresentazione binaria è sempre +necessario allocare un buffer di dimensione sufficiente a contenerla, pertanto +prima si dovrà far ricorso a \funcd{acl\_size} per ottenere tale dimensione e +poi allocare il buffer con una delle funzioni di +sez.~\ref{sec:proc_mem_alloc}. Una volta terminato l'uso della +rappresentazione binaria, il buffer dovrà essere esplicitamente disallocato. + +La funzione che consente di leggere la rappresentazione binaria di una ACL è +\funcd{acl\_copy\_ext}, il cui prototipo è: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{sys/acl.h} + + \funcdecl{ssize\_t acl\_copy\_ext(void *buf\_p, acl\_t acl, ssize\_t size)} + + Ottiene la rappresentazione binaria di una ACL. + + \bodydesc{La funzione restituisce in caso di successo la dimensione in byte + della rappresentazione binaria della ACL indicata da \param{acl} e $-1$ in + caso di errore, nel qual caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{EINVAL}] la ACL indicata da \param{acl} non è valida o + \param{size} è negativo o nullo. + \item[\errcode{ERANGE}] il valore di \param{size} è più piccolo della + dimensione della rappresentazione della ACL. + \end{errlist} + +} +\end{functions} + +La funzione salverà la rappresentazione binaria della ACL indicata da +\param{acl} sul buffer posto all'indirizzo \param{buf\_p} e lungo \param{size} +byte, restituendo la dimensione della stessa come valore di ritorno. Qualora +la dimensione della rappresentazione ecceda il valore di \param{size} la +funzione fallirà con un errore di \errcode{ERANGE}. La funzione non ha nessun +effetto sulla ACL indicata da \param{acl}. + +Viceversa se si vuole ripristinare una ACL a partire dalla rappresentazione +binaria della stessa disponibile in un buffer si potrà usare la funzione +\funcd{acl\_copy\_int}, il cui prototipo è: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{sys/acl.h} + + \funcdecl{ssize\_t acl\_copy\_int(const void *buf\_p)} + + Ripristina la rappresentazione binaria di una ACL. + + \bodydesc{La funzione restituisce un oggetto di tipo \type{acl\_t} in caso + di successo e \code{(acl\_t)NULL} in caso di errore, nel qual caso + \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{EINVAL}] il buffer all'indirizzo \param{buf\_p} non contiene + una rappresentazione corretta di una ACL. + \item[\errcode{ENOMEM}] non c'è memoria sufficiente per allocare un oggetto + \type{acl\_t} per la ACL richiesta. + \end{errlist} + +} +\end{functions} + +La funzione in caso di successo alloca autonomamente un oggetto di tipo +\type{acl\_t} che viene restituito come valore di ritorno con il contenuto +della ACL rappresentata dai dati contenuti nel buffer puntato da +\param{buf\_p}. Si ricordi che come per le precedenti funzioni l'oggetto +\type{acl\_t} dovrà essere disallocato esplicitamente al termine del suo +utilizzo. + +Una volta che si disponga della ACL desiderata, questa potrà essere impostata +su un file o una directory. Per impostare una ACL sono disponibili due +funzioni; la prima è \funcd{acl\_set\_file}, che opera sia su file che su +directory, ed il cui prototipo è: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{sys/acl.h} + + \funcdecl{int acl\_set\_file(const char *path, acl\_type\_t type, acl\_t + acl)} + + Imposta una ACL su un file o una directory. + + \bodydesc{La funzione restituisce $0$ in caso di successo e $-1$ in caso di + errore, nel qual caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{EACCES}] o un generico errore di accesso a \param{path} o il + valore di \param{type} specifica una ACL il cui tipo non può essere + assegnato a \param{path}. + \item[\errcode{EINVAL}] o \param{acl} non è una ACL valida, o \param{type} + ha in valore non corretto. + \item[\errcode{ENOSPC}] non c'è spazio disco sufficiente per contenere i + dati aggiuntivi della ACL. + \item[\errcode{ENOTSUP}] si è cercato di impostare una ACL su un file + contenuto in un filesystem che non supporta le ACL. + \end{errlist} + ed inoltre \errval{ENOENT}, \errval{ENOTDIR}, \errval{ENAMETOOLONG}, + \errval{EROFS}, \errval{EPERM}. +} +\end{functions} + +La funzione consente di assegnare la ACL contenuta in \param{acl} al file o +alla directory indicate dal pathname \param{path}, mentre con \param{type} si +indica il tipo di ACL utilizzando le costanti di tab.~\ref{tab:acl_type}, ma +si tenga presente che le ACL di default possono essere solo impostate +qualora \param{path} indichi una directory. Inoltre perché la funzione abbia +successo la ACL dovrà essere valida, e contenere tutti le voci necessarie, +unica eccezione è quella in cui si specifica una ACL vuota per cancellare la +ACL di default associata a \func{path}.\footnote{questo però è una estensione + della implementazione delle ACL di Linux, la bozza di standard POSIX.1e + prevedeva l'uso della apposita funzione \funcd{acl\_delete\_def\_file}, che + prende come unico argomento il pathname della directory di cui si vuole + cancellare l'ACL di default, per i dettagli si ricorra alla pagina di + manuale.} La seconda funzione che consente di impostare una ACL è +\funcd{acl\_set\_fd}, ed il suo prototipo è: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{sys/acl.h} + + \funcdecl{int acl\_set\_fd(int fd, acl\_t acl)} + + Imposta una ACL su un file descriptor. + + \bodydesc{La funzione restituisce $0$ in caso di successo e $-1$ in caso di + errore, nel qual caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{EINVAL}] o \param{acl} non è una ACL valida, o \param{type} + ha in valore non corretto. + \item[\errcode{ENOSPC}] non c'è spazio disco sufficiente per contenere i + dati aggiuntivi della ACL. + \item[\errcode{ENOTSUP}] si è cercato di impostare una ACL su un file + contenuto in un filesystem che non supporta le ACL. + \end{errlist} + ed inoltre \errval{EBADF}, \errval{EROFS}, \errval{EPERM}. +} +\end{functions} + +La funzione è del tutto è analoga a \funcd{acl\_set\_file} ma opera +esclusivamente sui file identificati tramite un file descriptor. Non dovendo +avere a che fare con directory (e con la conseguente possibilità di avere una +ACL di default) la funzione non necessita che si specifichi il tipo di ACL, +che sarà sempre di accesso, e prende come unico argomento, a parte il file +descriptor, la ACL da impostare. + +Le funzioni viste finora operano a livello di una intera ACL, eseguendo in una +sola volta tutte le operazioni relative a tutte le voci in essa contenuta. In +generale è possibile modificare un singolo valore all'interno di una singola +voce direttamente con le funzioni previste dallo standard POSIX.1e. Queste +funzioni però sono alquanto macchinose da utilizzare per cui è molto più +semplice operare direttamente sulla rappresentazione testuale. Questo è il +motivo per non tratteremo nei dettagli dette funzioni, fornendone solo una +descrizione sommaria; chi fosse interessato potrà ricorrere alle pagina di +manuale. + +Se si vuole operare direttamente sui contenuti di un oggetto di tipo +\type{acl\_t} infatti occorre fare riferimento alle singole voci tramite gli +opportuni puntatori di tipo \type{acl\_entry\_t}, che possono essere ottenuti +dalla funzione \funcd{acl\_get\_entry} (per una voce esistente) o dalla +funzione \funcd{acl\_create\_entry} per una voce da aggiungere. Nel caso della +prima funzione si potrà poi ripetere la lettura per ottenere i puntatori alle +singole voci successive alla prima. + +Una volta ottenuti detti puntatori si potrà operare sui contenuti delle singole +voci; con le funzioni \funcd{acl\_get\_tag\_type}, \funcd{acl\_get\_qualifier}, +\funcd{acl\_get\_permset} si potranno leggere rispettivamente tipo, +qualificatore e permessi mentre con le corrispondente funzioni +\funcd{acl\_set\_tag\_type}, \funcd{acl\_set\_qualifier}, +\funcd{acl\_set\_permset} si possono impostare i valori; in entrambi i casi +vengono utilizzati tipi di dato ad hoc.\footnote{descritti nelle singole + pagine di manuale.} Si possono poi copiare i valori di una voce da una ACL +ad un altra con \funcd{acl\_copy\_entry} o eliminare una voce da una ACL con +\funcd{acl\_delete\_entry}. + +\itindend{Access~Control~List~(ACL)} + + +\subsection{La gestione delle quote disco} +\label{sec:disk_quota} + +Quella delle quote disco è una funzionalità introdotta inizialmente da BSD, e +presente in Linux fino dai kernel dalla serie 2.0, che consente di porre dei +tetti massimi al consumo delle risorse di un filesystem (spazio disco e +\textit{inode}) da parte di utenti e gruppi. Dato che la funzionalità ha senso +solo per i filesystem su cui si mantengono i dati degli utenti\footnote{in + genere la si attiva sul filesystem che contiene le \textit{home} degli + utenti, dato che non avrebbe senso per i file di sistema che in genere + appartengono all'amministratore.} essa deve essere esplicitamente richiesta; +questo si fa tramite due distinte opzioni di montaggio, \texttt{usrquota} e +\texttt{grpquota} che abilitano le quote rispettivamente per gli utenti e per +i gruppi. Grazie a questo è possibile usare le limitazioni sulle quote solo +sugli utenti o solo sui gruppi. + +Il meccanismo prevede che per ciascun filesystem che supporta le quote disco +(i vari \textit{extN}, \textit{btrfs}, \textit{XFS}, \textit{JFS}, +\textit{ReiserFS}) il kernel provveda sia a mantenere aggiornati i dati +relativi al consumo delle risorse da parte di utenti e/o gruppi che a far +rispettare i limiti imposti dal sistema, con la generazione di un errore di +\errval{EDQUOT} per tutte le operazioni sui file che porterebbero ad un +superamento degli stessi. Si tenga presente che questi due compiti sono +separati, il primo si attiva al montaggio del filesystem con le quote +attivate, il secondo deve essere abilitato esplicitamente. + +Per il mantenimento dei dati di consumo delle risorse vengono usati due file +riservati (uno per le quote utente e l'altro per le quote gruppo) nella +directory radice del filesystem su cui si sono attivate le quote;\footnote{la + cosa vale per tutti i filesystem tranne \textit{XFS} che mantiene i dati + internamente.} con la versione 2 del supporto delle quote, l'unica rimasta +in uso, questi file sono \texttt{aquota.user} e \texttt{aquota.group}, in +precedenza erano \texttt{quota.user} e \texttt{quota.group}. Dato che i file +vengono aggiornati soltanto se il filesystem è stato montato con il supporto +delle quote, se si abilita questo in un secondo tempo (o se si eseguono +operazioni sul filesystem senza averlo abilitato) i dati contenuti possono non +corrispondere esattamente allo stato corrente del consumo delle risorse; per +questo in genere prima di montare in scrittura un filesystem su cui sono +abilitate le quote in genere viene utilizzato il comando \cmd{quotacheck} per +verificare e aggiornare i dati. + +Le restrizioni sul consumo delle risorse prevedono due limiti, il primo viene +detto \textit{soft limit} e può essere superato per brevi periodi di tempo, il +secondo viene detto \textit{hard limit} non può mai essere superato. Il +periodo di tempo per cui è possibile superare il \textit{soft limit} è detto +``\textsl{periodo di grazia}'' (\textit{grace period}), passato questo tempo +il passaggio del \textit{soft limit} viene trattato allo stesso modo +dell'\textit{hard limit}. Questi limiti riguardano separatamente sia lo +spazio disco (i blocchi) che il numero di file (gli \textit{inode}) e devono +pertanto essere specificati per entrambe le risorse. + +La funzione che consente di controllare tutti i vari aspetti della gestione +delle quote è \funcd{quotactl}, ed il suo prototipo è: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{sys/quota.h} + + \funcdecl{quotactl(int cmd, const char *dev, int id, caddr\_t addr)} + + Esegue una operazione di controllo sulle quote disco. + + \bodydesc{La funzione restituisce $0$ in caso di successo e $-1$ in caso di + errore, nel qual caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{EACCES}] il file delle quote non è un file ordinario. + \item[\errcode{EBUSY}] si è richiesto \const{Q\_QUOTAON} ma le quote sono + già attive. + \item[\errcode{EFAULT}] l'indirizzo \param{addr} non è valido. + \item[\errcode{EIO}] errore di lettura/scrittura sul file delle quote. + \item[\errcode{EMFILE}] non si può aprire il file delle quote avendo + superato il limite sul numero di file aperti nel sistema. + \item[\errcode{EINVAL}] o \param{cmd} non è un comando valido, + o il dispositivo \param{dev} non esiste. + \item[\errcode{ENODEV}] \param{dev} non corrisponde ad un \textit{mount + point} attivo. + \item[\errcode{ENOPKG}] il kernel è stato compilato senza supporto per le + quote. + \item[\errcode{ENOTBLK}] \param{dev} non è un dispositivo a blocchi. + \item[\errcode{EPERM}] non si hanno i permessi per l'operazione richiesta. + \item[\errcode{ESRCH}] è stato richiesto uno fra \const{Q\_GETQUOTA}, + \const{Q\_SETQUOTA}, \const{Q\_SETUSE}, \const{Q\_SETQLIM} per un + filesystem senza quote attivate. + \end{errlist} +} +\end{functions} + +La funzione richiede che il filesystem sul quale si vuole operare sia montato +con il supporto delle quote abilitato; esso deve essere specificato con il +nome del file di dispositivo nell'argomento \param{dev}. Per le operazioni che +lo richiedono inoltre si dovrà indicare con l'argomento \param{id} l'utente o +il gruppo (specificati rispettivamente per \acr{uid} e \acr{gid}) su cui si +vuole operare. Alcune operazioni usano l'argomento \param{addr} per indicare +un indirizzo ad un area di memoria il cui utilizzo dipende dall'operazione +stessa. + +Il tipo di operazione che si intende effettuare deve essere indicato tramite +il primo argomento \param{cmd}, questo in genere viene specificato con +l'ausilio della macro \macro{QCMD}: +\begin{functions} + \funcdecl{int QCMD(subcmd,type)} Imposta il comando \param{subcmd} per il + tipo di quote (utente o gruppo) \param{type}. +\end{functions} +\noindent che consente di specificare, oltre al tipo di operazione, se questa +deve applicarsi alle quote utente o alle quote gruppo, nel qual +caso \param{type} deve essere rispettivamente \const{USRQUOTA} o +\const{GRPQUOTA}. + + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}{|l|p{10cm}|} + \hline + \textbf{Comando} & \textbf{Descrizione} \\ + \hline + \hline + \const{Q\_QUOTAON} & Attiva l'applicazione delle quote disco per il + filesystem indicato da \param{dev}, si deve passare + in \param{addr} il pathname al file che mantiene le + quote, che deve esistere, e \param{id} deve indicare + la versione del formato con uno dei valori di + tab.~\ref{tab:quotactl_id_format}; l'operazione + richiede i privilegi di amministratore.\\ + \const{Q\_QUOTAOFF} & Disattiva l'applicazione delle quote disco per il + filesystem indicato da \param{dev}, \param{id} + e \param{addr} vengono ignorati; l'operazione + richiede i privilegi di amministratore.\\ + \const{Q\_GETQUOTA} & Legge i limiti ed i valori correnti delle quote nel + filesystem indicato da \param{dev} per l'utente o + il gruppo specificato da \param{id}; si devono avere + i privilegi di amministratore per leggere i dati + relativi ad altri utenti o a gruppi di cui non si fa + parte, il risultato viene restituito in una struttura + \struct{dqblk} all'indirizzo indicato + da \param{addr}.\\ + \const{Q\_SETQUOTA} & Imposta i limiti per le quote nel filesystem + indicato da \param{dev} per l'utente o il gruppo + specificato da \param{id} secondo i valori ottenuti + dalla struttura \struct{dqblk} puntata + da \param{addr}; l'operazione richiede i privilegi + di amministratore.\\ + \const{Q\_GETINFO} & Legge le informazioni (in sostanza i \textit{grace + time}) delle quote del filesystem indicato + da \param{dev} sulla struttura \struct{dqinfo} + puntata da \param{addr}, \param{id} viene ignorato.\\ + \const{Q\_SETINFO} & Imposta le informazioni delle quote del filesystem + indicato da \param{dev} come ottenuti dalla + struttura \struct{dqinfo} puntata + da \param{addr}, \param{id} viene ignorato; + l'operazione richiede i privilegi di amministratore.\\ + \const{Q\_GETFMT} & Richiede il valore identificativo (quello di + tab.~\ref{tab:quotactl_id_format}) per il formato + delle quote attualmente in uso sul filesystem + indicato da \param{dev}, che sarà memorizzato + sul buffer di 4 byte puntato da \param{addr}.\\ + \const{Q\_SYNC} & Aggiorna la copia su disco dei dati delle quote del + filesystem indicato da \param{dev}; in questo + caso \param{dev} può anche essere \val{NULL} nel + qual caso verranno aggiornati i dati per tutti i + filesystem con quote attive, \param{id} + e \param{addr} vengono comunque ignorati.\\ + \const{Q\_GETSTATS} & Ottiene statistiche ed altre informazioni generali + relative al sistema delle quote per il filesystem + indicato da \param{dev}, richiede che si + passi come argomento \param{addr} l'indirizzo di una + struttura \struct{dqstats}, mentre i valori + di \param{id} e \param{dev} vengono ignorati; + l'operazione è obsoleta e non supportata nei kernel + più recenti, che espongono la stessa informazione + nei file sotto \procfile{/proc/self/fs/quota/}.\\ +% \const{} & .\\ + \hline + \end{tabular} + \caption{Possibili valori per l'argomento \param{subcmd} di + \macro{QCMD}.} + \label{tab:quotactl_commands} +\end{table} + + +Le diverse operazioni supportate da \func{quotactl}, da indicare con +l'argomento \param{subcmd} di \macro{QCMD}, sono riportate in +tab.~\ref{tab:quotactl_commands}. In generale le operazione di attivazione, +disattivazione e di modifica dei limiti delle quote sono riservate e +richiedono i privilegi di amministratore.\footnote{per essere precisi tutte le + operazioni indicate come privilegiate in tab.~\ref{tab:quotactl_commands} + richiedono la \textit{capability} \const{CAP\_SYS\_ADMIN}.} Inoltre gli +utenti possono soltanto richiedere i dati relativi alle proprie quote, solo +l'amministratore può ottenere i dati di tutti. + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}{|l|p{10cm}|} + \hline + \textbf{Identificatore} & \textbf{Descrizione} \\ + \hline + \hline + \const{QFMT\_VFS\_OLD}& il vecchio (ed obsoleto) formato delle quote.\\ + \const{QFMT\_VFS\_V0} & la versione 0 usata dal VFS di Linux (supporta + \acr{uid} e \acr{gid} a 32 bit e limiti fino a + $2^{42}$ byte e $2^{32}$ file.\\ + \const{QFMT\_VFS\_V1} & la versione 1 usata dal VFS di Linux (supporta + \acr{uid} e \acr{GID} a 32 bit e limiti fino a + $2^{64}$ byte e $2^{64}$ file.\\ + \hline + \end{tabular} + \caption{Valori di identificazione del formato delle quote.} + \label{tab:quotactl_id_format} +\end{table} + +Alcuni dei comandi di tab.~\ref{tab:quotactl_commands} sono alquanto complessi +e richiedono un approfondimento maggiore, in particolare \const{Q\_GETQUOTA} e +\const{Q\_SETQUOTA} fanno riferimento ad una specifica struttura +\struct{dqblk}, la cui definizione è riportata in +fig.~\ref{fig:dqblk_struct},\footnote{la definizione mostrata è quella usata + fino dal kernel 2.4.22, non prenderemo in considerazione le versioni + obsolete.} nella quale vengono inseriti i dati relativi alle quote di un +singolo utente. + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{\textwidth} + \includestruct{listati/dqblk.h} + \end{minipage} + \normalsize + \caption{La struttura \structd{dqblk} per i dati delle quote disco.} + \label{fig:dqblk_struct} +\end{figure} + +La struttura viene usata sia con \const{Q\_GETQUOTA} per ottenere i valori +correnti dei limiti e dell'occupazione delle risorse, che con +\const{Q\_SETQUOTA} per effettuare modifiche ai limiti; come si può notare ci +sono alcuni campi (in sostanza \val{dqb\_curspace}, \val{dqb\_curinodes}, +\val{dqb\_btime}, \val{dqb\_itime}) che hanno senso solo in lettura in quanto +riportano uno stato non modificabile da \func{quotactl}, come l'uso corrente +di spazio e \textit{inode} o il tempo che resta nel caso si sia superato un +\textit{soft limit}. + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}{|l|p{10cm}|} + \hline + \textbf{Costante} & \textbf{Descrizione} \\ + \hline + \hline + \const{QIF\_BLIMITS}& Limiti sui blocchi di + spazio disco (\val{dqb\_bhardlimit} e + \val{dqb\_bsoftlimit}).\\ + \const{QIF\_SPACE} & Uso corrente + dello spazio disco (\val{dqb\_curspace}).\\ + \const{QIF\_ILIMITS}& Limiti sugli \textit{inode} + (\val{dqb\_ihardlimit} e \val{dqb\_isoftlimit}).\\ + \const{QIF\_INODES} & Uso corrente + degli \textit{inode} (\val{dqb\_curinodes}).\\ + \const{QIF\_BTIME} & Tempo di + sforamento del \textit{soft limit} sul numero di + blocchi (\val{dqb\_btime}).\\ + \const{QIF\_ITIME} & Tempo di + sforamento del \textit{soft limit} sul numero di + \textit{inode} (\val{dqb\_itime}).\\ + \const{QIF\_LIMITS} & L'insieme di \const{QIF\_BLIMITS} e + \const{QIF\_ILIMITS}.\\ + \const{QIF\_USAGE} & L'insieme di \const{QIF\_SPACE} e + \const{QIF\_INODES}.\\ + \const{QIF\_TIMES} & L'insieme di \const{QIF\_BTIME} e + \const{QIF\_ITIME}.\\ + \const{QIF\_ALL} & Tutti i precedenti.\\ + \hline + \end{tabular} + \caption{Costanti per il campo \val{dqb\_valid} di \struct{dqblk}.} + \label{tab:quotactl_qif_const} +\end{table} + + +Inoltre in caso di modifica di un limite si può voler operare solo su una +delle risorse (blocchi o \textit{inode});\footnote{non è possibile modificare + soltanto uno dei limiti (\textit{hard} o \textit{soft}) occorre sempre + rispecificarli entrambi.} per questo la struttura prevede un campo apposito, +\val{dqb\_valid}, il cui scopo è quello di indicare quali sono gli altri campi +che devono essere considerati validi. Questo campo è una maschera binaria che +deve essere espressa nei termini di OR aritmetico delle apposite costanti di +tab.~\ref{tab:quotactl_qif_const}, dove si è riportato il significato di +ciascuna di esse ed i campi a cui fanno riferimento. + +In lettura con \const{Q\_SETQUOTA} eventuali valori presenti in \struct{dqblk} +vengono comunque ignorati, al momento la funzione sovrascrive tutti i campi e +li marca come validi in \val{dqb\_valid}. Si possono invece usare +\const{QIF\_BLIMITS} o \const{QIF\_ILIMITS} per richiedere di impostare solo +la rispettiva tipologia di limiti con \const{Q\_SETQUOTA}. Si tenga presente +che il sistema delle quote richiede che l'occupazione di spazio disco sia +indicata in termini di blocchi e non di byte; dato che questo dipende da come +si è creato il filesystem potrà essere necessario effettuare qualche +controllo.\footnote{in genere viene usato un default di 1024 byte per blocco, + ma quando si hanno file di dimensioni medie maggiori può convenire usare + valori più alti per ottenere prestazioni migliori in conseguenza di un + minore frazionamento dei dati e di indici più corti.} + +Altre due operazioni che necessitano di un approfondimento sono +\const{Q\_GETINFO} e \const{Q\_SETINFO}, che sostanzialmente consentono di +ottenere i dati relativi alle impostazioni delle altre proprietà delle quote, +che si riducono poi alla durata del \textit{grace time} per i due tipi di +limiti. In questo caso queste si proprietà generali sono identiche per tutti +gli utenti, per cui viene usata una operazione distinta dalle +precedenti. Anche in questo caso le due operazioni richiedono l'uso di una +apposita struttura \struct{dqinfo}, la cui definizione è riportata in +fig.~\ref{fig:dqinfo_struct}. + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{\textwidth} + \includestruct{listati/dqinfo.h} + \end{minipage} + \normalsize + \caption{La struttura \structd{dqinfo} per i dati delle quote disco.} + \label{fig:dqinfo_struct} +\end{figure} + +Come per \struct{dqblk} anche in questo caso viene usato un campo della +struttura, \val{dqi\_valid} come maschera binaria per dichiarare quale degli +altri campi sono validi; le costanti usate per comporre questo valore sono +riportate in tab.~\ref{tab:quotactl_iif_const} dove si è riportato il +significato di ciascuna di esse ed i campi a cui fanno riferimento. + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}{|l|l|} + \hline + \textbf{Costante} & \textbf{Descrizione} \\ + \hline + \hline + \const{IIF\_BGRACE}& Il \textit{grace period} per i blocchi + (\val{dqi\_bgrace}).\\ + \const{IIF\_IGRACE}& Il \textit{grace period} per gli \textit{inode} + (\val{dqi\_igrace}).\\ + \const{IIF\_FLAGS} & I flag delle quote (\val{dqi\_flags}) (inusato ?).\\ + \const{IIF\_ALL} & Tutti i precedenti.\\ + \hline + \end{tabular} + \caption{Costanti per il campo \val{dqi\_valid} di \struct{dqinfo}.} + \label{tab:quotactl_iif_const} +\end{table} + +Come in precedenza con \const{Q\_GETINFO} tutti i valori vengono letti +sovrascrivendo il contenuto di \struct{dqinfo} e marcati come validi in +\val{dqi\_valid}. In scrittura con \const{Q\_SETINFO} si può scegliere quali +impostare, si tenga presente che i tempi dei campi \val{dqi\_bgrace} e +\val{dqi\_igrace} devono essere specificati in secondi. + +Come esempi dell'uso di \func{quotactl} utilizzeremo estratti del codice di un +modulo Python usato per fornire una interfaccia diretta a \func{quotactl} +senza dover passare dalla scansione dei risultati di un comando. Il modulo si +trova fra i pacchetti Debian messi a disposizione da Truelite Srl, +all'indirizzo \url{http://labs.truelite.it/projects/packages}.\footnote{in + particolare il codice C del modulo è nel file \texttt{quotamodule.c} + visionabile a partire dall'indirizzo indicato nella sezione + \textit{Repository}.} + +\begin{figure}[!htbp] + \footnotesize \centering + \begin{minipage}[c]{\codesamplewidth} + \includecodesample{listati/get_quota.c} + \end{minipage} + \caption{Esempio di codice per ottenere i dati delle quote.} + \label{fig:get_quota} +\end{figure} + +Il primo esempio, riportato in fig.~\ref{fig:get_quota}, riporta il codice +della funzione che consente di leggere le quote. La funzione fa uso +dell'interfaccia dal C verso Python, che definisce i vari simboli \texttt{Py*} +(tipi di dato e funzioni). Non staremo ad approfondire i dettagli di questa +interfaccia, per la quale esistono numerose trattazioni dettagliate, ci +interessa solo esaminare l'uso di \func{quotactl}. + +In questo caso la funzione prende come argomenti (\texttt{\small 1}) l'intero +\texttt{who} che indica se si vuole operare sulle quote utente o gruppo, +l'identificatore \texttt{id} dell'utente o del gruppo scelto, ed il nome del +file di dispositivo del filesystem su cui si sono attivate le +quote.\footnote{questi vengono passati come argomenti dalle funzioni mappate + come interfaccia pubblica del modulo (una per gruppi ed una per gli utenti) + che si incaricano di decodificare i dati passati da una chiamata nel codice + Python.} Questi argomenti vengono passati direttamente alla chiamata a +\func{quotactl} (\texttt{\small 5}), a parte \texttt{who} che viene abbinato +con \macro{QCMD} al comando \const{Q\_GETQUOTA} per ottenere i dati. + +La funzione viene eseguita all'interno di un condizionale (\texttt{\small + 5--16}) che in caso di successo provvede a costruire (\texttt{\small 6--12}) +opportunamente una risposta restituendo tramite la opportuna funzione di +interfaccia un oggetto Python contenente i dati della struttura \struct{dqblk} +relativi a uso corrente e limiti sia per i blocchi che per gli +\textit{inode}. In caso di errore (\texttt{\small 13--15}) si usa un'altra +funzione dell'interfaccia per passare il valore di \var{errno} come eccezione. + +\begin{figure}[!htbp] + \footnotesize \centering + \begin{minipage}[c]{\codesamplewidth} + \includecodesample{listati/set_block_quota.c} + \end{minipage} + \caption{Esempio di codice per impostare i limiti sullo spazio disco.} + \label{fig:set_block_quota} +\end{figure} + +Per impostare i limiti sullo spazio disco si potrà usare una seconda funzione, +riportata in fig.~\ref{fig:set_block_quota}, che prende gli stessi argomenti +della precedente, con lo stesso significato, a cui si aggiungono i valori per +il \textit{soft limit} e l'\textit{hard limit}. In questo caso occorrerà, +prima di chiamare \func{quotactl}, inizializzare opportunamente +(\texttt{\small 5--7}) i campi della struttura \struct{dqblk} che si vogliono +utilizzare (quelli relativi ai limiti sui blocchi) e specificare gli stessi +con \const{QIF\_BLIMITS} in \var{dq.dqb\_valid}. + +Fatto questo la chiamata a \func{quotactl}, stavolta con il comando +\const{Q\_SETQUOTA}, viene eseguita come in precedenza all'interno di un +condizionale (\texttt{\small 9--14}). In questo caso non essendovi da +restituire nessun dato in caso di successo si usa (\texttt{\small 10}) una +apposita funzione di uscita, mentre si restituisce come prima una eccezione +con il valore di \var{errno} in caso di errore (\texttt{\small 12--13}). + + +\subsection{La gestione delle \textit{capabilities}} +\label{sec:proc_capabilities} + +\itindbeg{capabilities} + +Come accennato in sez.~\ref{sec:proc_access_id} l'architettura classica della +gestione dei privilegi in un sistema unix-like ha il sostanziale problema di +fornire all'amministratore dei poteri troppo ampi, questo comporta che anche +quando si siano predisposte delle misure di protezione per in essere in grado +di difendersi dagli effetti di una eventuale compromissione del +sistema,\footnote{come montare un filesystem in sola lettura per impedirne + modifiche, o marcare un file come immutabile.} una volta che questa sia +stata effettuata e si siano ottenuti i privilegi di amministratore, queste +potranno essere comunque rimosse.\footnote{nei casi elencati nella precedente + nota si potrà sempre rimontare il sistema in lettura-scrittura, o togliere + la marcatura di immutabilità.} + +Il problema consiste nel fatto che nell'architettura tradizionale di un +sistema unix-like i controlli di accesso sono basati su un solo livello di +separazione: per i processi normali essi sono posti in atto, mentre per i +processi con i privilegi di amministratore essi non vengono neppure eseguiti; +per questo motivo non era previsto alcun modo per evitare che un processo con +diritti di amministratore non potesse eseguire certe operazioni, o per cedere +definitivamente alcuni privilegi da un certo momento in poi. + +Per ovviare a tutto ciò, a partire dai kernel della serie 2.2, è stato +introdotto un meccanismo, detto \textit{capabilities}, che consentisse di +suddividere i vari privilegi tradizionalmente associati all'amministratore in +un insieme di \textsl{capacità} distinte. L'idea era che queste capacità +potessero essere abilitate e disabilitate in maniera indipendente per ciascun +processo con privilegi di amministratore, permettendo così una granularità +molto più fine nella distribuzione degli stessi che evitasse la originaria +situazione di ``\textsl{tutto o nulla}''. + +Il meccanismo completo delle \textit{capabilities}\footnote{l'implementazione + si rifà ad una bozza di quello che doveva diventare lo standard POSIX.1e, + poi abbandonato.} prevede inoltre la possibilità di associare le stesse ai +singoli file eseguibili, in modo da poter stabilire quali capacità possono +essere utilizzate quando viene messo in esecuzione uno specifico programma; ma +il supporto per questa funzionalità, chiamata \textit{file capabilities}, è +stato introdotto soltanto a partire dal kernel 2.6.24. Fino ad allora doveva +essere il programma stesso ad eseguire una riduzione esplicita delle sue +capacità, cosa che ha reso l'uso di questa funzionalità poco diffuso, vista la +presenza di meccanismi alternativi per ottenere limitazioni delle capacità +dell'amministratore a livello di sistema operativo, come \index{SELinux} +SELinux. + +Con questo supporto e con le ulteriori modifiche introdotte con il kernel +2.6.25 il meccanismo delle \textit{capabilities} è stato totalmente +rivoluzionato, rendendolo più aderente alle intenzioni originali dello +standard POSIX, rimuovendo il significato che fino ad allora aveva avuto la +capacità \const{CAP\_SETPCAP} e cambiando le modalità di funzionamento del +cosiddetto \itindex{capabilities~bounding~set} \textit{capabilities bounding + set}. Ulteriori modifiche sono state apportate con il kernel 2.6.26 per +consentire la rimozione non ripristinabile dei privilegi di +amministratore. Questo fa sì che il significato ed il comportamento del kernel +finisca per dipendere dalla versione dello stesso e dal fatto che le nuove +\textit{file capabilities} siano abilitate o meno. Per capire meglio la +situazione e cosa è cambiato conviene allora spiegare con maggiori dettagli +come funziona il meccanismo delle \textit{capabilities}. + +Il primo passo per frazionare i privilegi garantiti all'amministratore, +supportato fin dalla introduzione iniziale del kernel 2.2, è stato quello in +cui a ciascun processo sono stati associati tre distinti insiemi di +\textit{capabilities}, denominati rispettivamente \textit{permitted}, +\textit{inheritable} ed \textit{effective}. Questi insiemi vengono mantenuti +in forma di tre diverse maschere binarie,\footnote{il kernel li mantiene, come + i vari identificatori di sez.~\ref{sec:proc_setuid}, all'interno della + \struct{task\_struct} di ciascun processo (vedi + fig.~\ref{fig:proc_task_struct}), nei tre campi \texttt{cap\_effective}, + \texttt{cap\_inheritable}, \texttt{cap\_permitted} del tipo + \texttt{kernel\_cap\_t}; questo era, fino al kernel 2.6.25 definito come + intero a 32 bit per un massimo di 32 \textit{capabilities} distinte, + attualmente è stato aggiornato ad un vettore in grado di mantenerne fino a + 64.} in cui ciascun bit corrisponde ad una capacità diversa. + +L'utilizzo di tre distinti insiemi serve a fornire una interfaccia flessibile +per l'uso delle \textit{capabilities}, con scopi analoghi a quelli per cui +sono mantenuti i diversi insiemi di identificatori di +sez.~\ref{sec:proc_setuid}; il loro significato, che è rimasto sostanzialmente +lo stesso anche dopo le modifiche seguite alla introduzione delle +\textit{file capabilities} è il seguente: +\begin{basedescript}{\desclabelwidth{2.1cm}\desclabelstyle{\nextlinelabel}} +\item[\textit{permitted}] l'insieme delle \textit{capabilities} + ``\textsl{permesse}'', cioè l'insieme di quelle capacità che un processo + \textsl{può} impostare come \textsl{effettive} o come + \textsl{ereditabili}. Se un processo cancella una capacità da questo insieme + non potrà più riassumerla.\footnote{questo nei casi ordinari, sono + previste però una serie di eccezioni, dipendenti anche dal tipo di + supporto, che vedremo meglio in seguito dato il notevole intreccio nella + casistica.} +\item[\textit{inheritable}] l'insieme delle \textit{capabilities} + ``\textsl{ereditabili}'', cioè di quelle che verranno trasmesse come insieme + delle \textsl{permesse} ad un nuovo programma eseguito attraverso una + chiamata ad \func{exec}. +\item[\textit{effective}] l'insieme delle \textit{capabilities} + ``\textsl{effettive}'', cioè di quelle che vengono effettivamente usate dal + kernel quando deve eseguire il controllo di accesso per le varie operazioni + compiute dal processo. +\label{sec:capabilities_set} +\end{basedescript} + +Con l'introduzione delle \textit{file capabilities} sono stati introdotti +altri tre insiemi associabili a ciascun file.\footnote{la realizzazione viene + eseguita con l'uso di uno specifico attributo esteso, + \texttt{security.capability}, la cui modifica è riservata, (come illustrato + in sez.~\ref{sec:file_xattr}) ai processi dotato della capacità + \const{CAP\_SYS\_ADMIN}.} Le \textit{file capabilities} hanno effetto +soltanto quando il file che le porta viene eseguito come programma con una +\func{exec}, e forniscono un meccanismo che consente l'esecuzione dello stesso +con maggiori privilegi; in sostanza sono una sorta di estensione del +\acr{suid} bit limitato ai privilegi di amministratore. Anche questi tre +insiemi sono identificati con gli stessi nomi di quello dei processi, ma il +loro significato è diverso: +\begin{basedescript}{\desclabelwidth{2.1cm}\desclabelstyle{\nextlinelabel}} +\item[\textit{permitted}] (chiamato originariamente \textit{forced}) l'insieme + delle capacità che con l'esecuzione del programma verranno aggiunte alle + capacità \textsl{permesse} del processo. +\item[\textit{inheritable}] (chiamato originariamente \textit{allowed}) + l'insieme delle capacità che con l'esecuzione del programma possono essere + ereditate dal processo originario (che cioè non vengono tolte + dall'\textit{inheritable set} del processo originale all'esecuzione di + \func{exec}). +\item[\textit{effective}] in questo caso non si tratta di un insieme ma di un + unico valore logico; se attivo all'esecuzione del programma tutte le + capacità che risulterebbero \textsl{permesse} verranno pure attivate, + inserendole automaticamente nelle \textsl{effettive}, se disattivato nessuna + capacità verrà attivata (cioè l'\textit{effective set} resterà vuoto). +\end{basedescript} + +\itindbeg{capabilities~bounding~set} + +Infine come accennato, esiste un ulteriore insieme, chiamato +\textit{capabilities bounding set}, il cui scopo è quello di costituire un +limite alle capacità che possono essere attivate per un programma. Il suo +funzionamento però è stato notevolmente modificato con l'introduzione delle +\textit{file capabilities} e si deve pertanto prendere in considerazione una +casistica assai complessa. + +Per i kernel fino al 2.6.25, o se non si attiva il supporto per le +\textit{file capabilities}, il \textit{capabilities bounding set} è un +parametro generale di sistema, il cui valore viene riportato nel file +\procfile{/proc/sys/kernel/cap-bound}. Il suo valore iniziale è definito in +sede di compilazione del kernel, e da sempre ha previsto come default la +presenza di tutte le \textit{capabilities} eccetto \const{CAP\_SETPCAP}. In +questa situazione solo il primo processo eseguito nel sistema (quello con +\textsl{pid} 1, di norma \texttt{/sbin/init}) ha la possibilità di +modificarlo; ogni processo eseguito successivamente, se dotato dei privilegi +di amministratore, è in grado soltanto di rimuovere una delle +\textit{capabilities} già presenti dell'insieme.\footnote{per essere precisi + occorreva la capacità \const{CAP\_SYS\_MODULE}.} + +In questo caso l'effetto complessivo del \textit{capabilities bounding set} è +che solo le capacità in esso presenti possono essere trasmesse ad un altro +programma attraverso una \func{exec}. Questo in sostanza significa che se un +qualunque programma elimina da esso una capacità, considerato che +\texttt{init} (almeno nelle versioni ordinarie) non supporta la reimpostazione +del \textit{bounding set}, questa non sarà più disponibile per nessun processo +a meno di un riavvio, eliminando così in forma definitiva quella capacità per +tutti, compreso l'amministratore.\footnote{la qual cosa, visto il default + usato per il \textit{capabilities bounding set}, significa anche che + \const{CAP\_SETPCAP} non è stata praticamente mai usata nella sua forma + originale.} + +Con il kernel 2.6.25 e le \textit{file capabilities} il \textit{bounding set} +è diventato una proprietà di ciascun processo, che viene propagata invariata +sia attraverso una \func{fork} che una \func{exec}. In questo caso il file +\procfile{/proc/sys/kernel/cap-bound} non esiste e \texttt{init} non ha nessun +ruolo speciale, inoltre in questo caso all'avvio il valore iniziale prevede la +presenza di tutte le capacità (compresa \const{CAP\_SETPCAP}). + +Con questo nuovo meccanismo il \textit{bounding set} continua a ricoprire un +ruolo analogo al precedente nel passaggio attraverso una \func{exec}, come +limite alle capacità che possono essere aggiunte al processo in quanto +presenti nel \textit{permitted set} del programma messo in esecuzione, in +sostanza il nuovo programma eseguito potrà ricevere una capacità presente nel +suo \textit{permitted set} (quello del file) solo se questa è anche nel +\textit{bounding set} (del processo). In questo modo si possono rimuovere +definitivamente certe capacità da un processo, anche qualora questo dovesse +eseguire un programma privilegiato che prevede di riassegnarle. + +Si tenga presente però che in questo caso il \textit{bounding set} blocca +esclusivamente le capacità indicate nel \textit{permitted set} del programma +che verrebbero attivate in caso di esecuzione, e non quelle eventualmente già +presenti nell'\textit{inheritable set} del processo (ad esempio perché +presenti prima di averle rimosse dal \textit{bounding set}). In questo caso +eseguendo un programma che abbia anche lui dette capacità nel suo +\textit{inheritable set} queste verrebbero assegnate. + +In questa seconda versione inoltre il \textit{bounding set} costituisce anche +un limite per le capacità che possono essere aggiunte all'\textit{inheritable + set} del processo stesso con \func{capset}, sempre nel senso che queste +devono essere presenti nel \textit{bounding set} oltre che nel +\textit{permitted set} del processo. Questo limite vale anche per processi con +i privilegi di amministratore,\footnote{si tratta sempre di avere la + \textit{capability} \const{CAP\_SETPCAP}.} per i quali invece non vale la +condizione che le \textit{capabilities} da aggiungere nell'\textit{inheritable + set} debbano essere presenti nel proprio \textit{permitted set}.\footnote{lo + scopo anche in questo caso è ottenere una rimozione definitiva della + possibilità di passare una capacità rimossa dal \textit{bounding set}.} + +Come si può notare per fare ricorso alle \textit{capabilities} occorre +comunque farsi carico di una notevole complessità di gestione, aggravata dalla +presenza di una radicale modifica del loro funzionamento con l'introduzione +delle \textit{file capabilities}. Considerato che il meccanismo originale era +incompleto e decisamente problematico nel caso di programmi che non ne +sapessero tener conto,\footnote{c'è stato un grosso problema di sicurezza con + \texttt{sendmail}, riuscendo a rimuovere \const{CAP\_SETGID} + dall'\textit{inheritable set} di un processo si ottenne di far fallire + \func{setuid} in maniera inaspettata per il programma (che aspettandosi + sempre il successo della funzione non ne controllava lo stato di uscita) con + la conseguenza di effettuare come amministratore operazioni che altrimenti + sarebbero state eseguite, senza poter apportare danni, da utente normale.} +ci soffermeremo solo sulla implementazione completa presente a partire dal +kernel 2.6.25, tralasciando ulteriori dettagli riguardo la versione +precedente. + +Riassumendo le regole finora illustrate tutte le \textit{capabilities} vengono +ereditate senza modifiche attraverso una \func{fork} mentre, indicati con +\texttt{orig\_*} i valori degli insiemi del processo chiamante, con +\texttt{file\_*} quelli del file eseguito e con \texttt{bound\_set} il +\textit{capabilities bounding set}, dopo l'invocazione di \func{exec} il +processo otterrà dei nuovi insiemi di capacità \texttt{new\_*} secondo la +formula (espressa in pseudo-codice C) di fig.~\ref{fig:cap_across_exec}; si +noti come in particolare il \textit{capabilities bounding set} non viene +comunque modificato e resta lo stesso sia attraverso una \func{fork} che +attraverso una \func{exec}. + +\begin{figure}[!htbp] + \footnotesize \centering + \begin{minipage}[c]{12cm} + \includecodesnip{listati/cap-results.c} + \end{minipage} + \caption{Espressione della modifica delle \textit{capabilities} attraverso + una \func{exec}.} + \label{fig:cap_across_exec} +\end{figure} + +\itindend{capabilities~bounding~set} + +A queste regole se ne aggiungono delle altre che servono a riprodurre il +comportamento tradizionale di un sistema unix-like in tutta una serie di +circostanze. La prima di queste è relativa a quello che avviene quando si +esegue un file senza \textit{capabilities}; se infatti si considerasse questo +equivalente al non averne assegnata alcuna, non essendo presenti capacità né +nel \textit{permitted set} né nell'\textit{inheritable set} del file, +nell'esecuzione di un qualunque programma l'amministratore perderebbe tutti i +privilegi originali dal processo. + +Per questo motivo se un programma senza \textit{capabilities} assegnate viene +eseguito da un processo con \textit{real user-ID} 0, esso verrà trattato come +se tanto il \textit{permitted set} che l'\textit{inheritable set} fossero con +tutte le \textit{capabilities} abilitate, con l'\textit{effective set} attivo, +col risultato di fornire comunque al processo tutte le capacità presenti nel +proprio \textit{bounding set}. Lo stesso avviene quando l'eseguibile ha attivo +il \acr{suid} bit ed appartiene all'amministratore, in entrambi i casi si +riesce così a riottenere il comportamento classico di un sistema unix-like. + +Una seconda circostanza è quella relativa a cosa succede alle +\textit{capabilities} di un processo nelle possibili transizioni da +\textit{user-ID} nullo a \textit{user-ID} non nullo o viceversa (corrispondenti +rispettivamente a cedere o riottenere i i privilegi di amministratore) che si +possono effettuare con le varie funzioni viste in +sez.~\ref{sec:proc_setuid}. In questo caso la casistica è di nuovo alquanto +complessa, considerata anche la presenza dei diversi gruppi di identificatori +illustrati in tab.~\ref{tab:proc_uid_gid}, si avrà allora che: +\begin{enumerate*} +\item se si passa da \textit{effective user-ID} nullo a non nullo + l'\textit{effective set} del processo viene totalmente azzerato, se + viceversa si passa da \textit{effective user-ID} non nullo a nullo il + \textit{permitted set} viene copiato nell'\textit{effective set}; +\item se si passa da \textit{file system user-ID} nullo a non nullo verranno + cancellate dall'\textit{effective set} del processo tutte le capacità + attinenti i file, e cioè \const{CAP\_LINUX\_IMMUTABLE}, \const{CAP\_MKNOD}, + \const{CAP\_DAC\_OVERRIDE}, \const{CAP\_DAC\_READ\_SEARCH}, + \const{CAP\_MAC\_OVERRIDE}, \const{CAP\_CHOWN}, \const{CAP\_FSETID} e + \const{CAP\_FOWNER} (le prime due a partire dal kernel 2.2.30), nella + transizione inversa verranno invece inserite nell'\textit{effective set} + quelle capacità della precedente lista che sono presenti nel suo + \textit{permitted set}. +\item se come risultato di una transizione riguardante gli identificativi dei + gruppi \textit{real}, \textit{saved} ed \textit{effective} in cui si passa + da una situazione in cui uno di questi era nullo ad una in cui sono tutti + non nulli,\footnote{in sostanza questo è il caso di quando si chiama + \func{setuid} per rimuovere definitivamente i privilegi di amministratore + da un processo.} verranno azzerati completamente sia il \textit{permitted + set} che l'\textit{effective set}. \end{enumerate*} +\label{sec:capability-uid-transition} + +La combinazione di tutte queste regole consente di riprodurre il comportamento +ordinario di un sistema di tipo Unix tradizionale, ma può risultare +problematica qualora si voglia passare ad una configurazione di sistema +totalmente basata sull'applicazione delle \textit{capabilities}; in tal caso +infatti basta ad esempio eseguire un programma con \acr{suid} bit di proprietà +dell'amministratore per far riottenere ad un processo tutte le capacità +presenti nel suo \textit{bounding set}, anche se si era avuta la cura di +cancellarle dal \textit{permitted set}. + +\itindbeg{securebits} + +Per questo motivo a partire dal kernel 2.6.26, se le \textit{file + capabilities} sono abilitate, ad ogni processo viene stata associata una +ulteriore maschera binaria, chiamata \textit{securebits flags}, su cui sono +mantenuti una serie di flag (vedi tab.~\ref{tab:securebits_values}) il cui +valore consente di modificare queste regole speciali che si applicano ai +processi con \textit{user-ID} nullo. La maschera viene sempre mantenuta +attraverso una \func{fork}, mentre attraverso una \func{exec} viene sempre +cancellato il flag \const{SECURE\_KEEP\_CAPS}. + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}{|l|p{10cm}|} + \hline + \textbf{Flag} & \textbf{Descrizione} \\ + \hline + \hline + \const{SECURE\_KEEP\_CAPS}& Il processo non subisce la cancellazione delle + sue \textit{capabilities} quando tutti i suoi + \textit{user-ID} passano ad un valore non + nullo (regola di compatibilità per il cambio + di \textit{user-ID} n. 3 del precedente + elenco), sostituisce il precedente uso + dell'operazione \const{PR\_SET\_KEEPCAPS} di + \func{prctl}.\\ + \const{SECURE\_NO\_SETUID\_FIXUP}&Il processo non subisce le modifiche + delle sue \textit{capabilities} nel passaggio + da nullo a non nullo degli \textit{user-ID} + dei gruppi \textit{effective} e + \textit{file system} (regole di compatibilità + per il cambio di \textit{user-ID} nn. 1 e 2 del + precedente elenco).\\ + \const{SECURE\_NOROOT} & Il processo non assume nessuna capacità + aggiuntiva quando esegue un programma, anche + se ha \textit{user-ID} nullo o il programma ha + il \acr{suid} bit attivo ed appartiene + all'amministratore (regola di compatibilità + per l'esecuzione di programmi senza + \textit{capabilities}).\\ + \hline + \end{tabular} + \caption{Costanti identificative dei flag che compongono la maschera dei + \textit{securebits}.} + \label{tab:securebits_values} +\end{table} + +A ciascuno dei flag di tab.~\ref{tab:securebits_values} è inoltre abbinato un +corrispondente flag di blocco, identificato da una costante omonima con +l'estensione \texttt{\_LOCKED}, la cui attivazione è irreversibile ed ha +l'effetto di rendere permanente l'impostazione corrente del corrispondente +flag ordinario; in sostanza con \const{SECURE\_KEEP\_CAPS\_LOCKED} si rende +non più modificabile \const{SECURE\_KEEP\_CAPS}, ed analogamente avviene con +\const{SECURE\_NO\_SETUID\_FIXUP\_LOCKED} per +\const{SECURE\_NO\_SETUID\_FIXUP} e con \const{SECURE\_NOROOT\_LOCKED} per +\const{SECURE\_NOROOT}. + +Per l'impostazione di questi flag sono stata predisposte due specifiche +operazioni di \func{prctl} (vedi sez.~\ref{sec:process_prctl}), +\const{PR\_GET\_SECUREBITS}, che consente di ottenerne il valore, e +\const{PR\_SET\_SECUREBITS}, che consente di modificarne il valore; per +quest'ultima sono comunque necessari i privilegi di amministratore ed in +particolare la capacità \const{CAP\_SETPCAP}. Prima dell'introduzione dei +\textit{securebits} era comunque possibile ottenere lo stesso effetto di +\const{SECURE\_KEEP\_CAPS} attraverso l'uso di un'altra operazione di +\func{prctl}, \const{PR\_SET\_KEEPCAPS}. + +\itindend{securebits} + +Oltre alla gestione dei \textit{securebits} la nuova versione delle +\textit{file capabilities} prevede l'uso di \func{prctl} anche per la gestione +del \textit{capabilities bounding set}, attraverso altre due operazioni +dedicate, \const{PR\_CAPBSET\_READ} per controllarne il valore e +\const{PR\_CAPBSET\_DROP} per modificarlo; quest'ultima di nuovo è una +operazione privilegiata che richiede la capacità \const{CAP\_SETPCAP} e che, +come indica chiaramente il nome, permette solo la rimozione di una +\textit{capability} dall'insieme; per i dettagli sull'uso di tutte queste +operazioni si rimanda alla rilettura di sez.~\ref{sec:process_prctl}. + +% TODO verificare per process capability bounding set, vedi: +% http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=3b7391de67da515c91f48aa371de77cb6cc5c07e + +% TODO capire cosa cambia con i patch vari, vedi +% http://lwn.net/Articles/280279/ +% http://lwn.net/Articles/256519/ +% http://lwn.net/Articles/211883/ + + +Un elenco delle delle \textit{capabilities} disponibili su Linux, con una +breve descrizione ed il nome delle costanti che le identificano, è riportato +in tab.~\ref{tab:proc_capabilities};\footnote{l'elenco presentato questa + tabella, ripreso dalla pagina di manuale (accessibile con \texttt{man + capabilities}) e dalle definizioni in \texttt{linux/capabilities.h}, è + aggiornato al kernel 2.6.26.} la tabella è divisa in due parti, la prima +riporta le \textit{capabilities} previste anche nella bozza dello standard +POSIX1.e, la seconda quelle specifiche di Linux. Come si può notare dalla +tabella alcune \textit{capabilities} attengono a singole funzionalità e sono +molto specializzate, mentre altre hanno un campo di applicazione molto vasto, +che è opportuno dettagliare maggiormente. + +\begin{table}[!h!btp] + \centering + \footnotesize + \begin{tabular}{|l|p{11.9cm}|} + \hline + \textbf{Capacità}&\textbf{Descrizione}\\ + \hline + \hline +% +% POSIX-draft defined capabilities. +% + \const{CAP\_AUDIT\_CONTROL}& La capacità di abilitare e disabilitare il + controllo dell'auditing (dal kernel 2.6.11).\\ + \const{CAP\_AUDIT\_WRITE}&La capacità di scrivere dati nel giornale di + auditing del kernel (dal kernel 2.6.11).\\ + % TODO verificare questa roba dell'auditing + \const{CAP\_CHOWN} & La capacità di cambiare proprietario e gruppo + proprietario di un file (vedi + sez.~\ref{sec:file_ownership_management}).\\ + \const{CAP\_DAC\_OVERRIDE}& La capacità di evitare il controllo dei + permessi di lettura, scrittura ed esecuzione dei + file,\footnotemark (vedi + sez.~\ref{sec:file_access_control}).\\ + \const{CAP\_DAC\_READ\_SEARCH}& La capacità di evitare il controllo dei + permessi di lettura ed esecuzione per + le directory (vedi + sez.~\ref{sec:file_access_control}).\\ + \const{CAP\_FOWNER} & La capacità di evitare il controllo della + proprietà di un file per tutte + le operazioni privilegiate non coperte dalle + precedenti \const{CAP\_DAC\_OVERRIDE} e + \const{CAP\_DAC\_READ\_SEARCH}.\\ + \const{CAP\_FSETID} & La capacità di evitare la cancellazione + automatica dei bit \itindex{suid~bit} \acr{suid} + e \itindex{sgid~bit} \acr{sgid} quando un file + per i quali sono impostati viene modificato da + un processo senza questa capacità e la capacità + di impostare il bit \acr{sgid} su un file anche + quando questo è relativo ad un gruppo cui non si + appartiene (vedi + sez.~\ref{sec:file_perm_management}).\\ + \const{CAP\_KILL} & La capacità di mandare segnali a qualunque + processo (vedi sez.~\ref{sec:sig_kill_raise}).\\ + \const{CAP\_SETFCAP} & La capacità di impostare le + \textit{capabilities} di un file (dal kernel + 2.6.24).\\ + \const{CAP\_SETGID} & La capacità di manipolare i group ID dei + processi, sia il principale che i supplementari, + (vedi sez.~\ref{sec:proc_setgroups}) che quelli + trasmessi tramite i socket \textit{unix domain} + (vedi sez.~\ref{sec:unix_socket}).\\ + \const{CAP\_SETUID} & La capacità di manipolare gli user ID del + processo (vedi sez.~\ref{sec:proc_setuid}) e di + trasmettere un user ID arbitrario nel passaggio + delle credenziali coi socket \textit{unix + domain} (vedi sez.~\ref{sec:unix_socket}).\\ +% +% Linux specific capabilities +% +\hline + \const{CAP\_IPC\_LOCK} & La capacità di effettuare il \textit{memory + locking} \itindex{memory~locking} con le + funzioni \func{mlock}, \func{mlockall}, + \func{shmctl}, \func{mmap} (vedi + sez.~\ref{sec:proc_mem_lock} e + sez.~\ref{sec:file_memory_map}). \\ + \const{CAP\_IPC\_OWNER} & La capacità di evitare il controllo dei permessi + per le operazioni sugli oggetti di + intercomunicazione fra processi (vedi + sez.~\ref{sec:ipc_sysv}).\\ + \const{CAP\_LEASE} & La capacità di creare dei \textit{file lease} + \index{file!lease} (vedi + sez.~\ref{sec:file_asyncronous_lease}) + pur non essendo proprietari del file (dal kernel + 2.4).\\ + \const{CAP\_LINUX\_IMMUTABLE}& La capacità di impostare sui file gli + attributi \textit{immutable} e + \itindex{append~mode} \textit{append only} (se + supportati).\\ + \const{CAP\_MKNOD} & La capacità di creare + \index{file!di~dispositivo} file di dispositivo + con \func{mknod} (vedi + sez.~\ref{sec:file_mknod}) (dal kernel 2.4).\\ + \const{CAP\_NET\_ADMIN} & La capacità di eseguire alcune operazioni + privilegiate sulla rete.\\ + \const{CAP\_NET\_BIND\_SERVICE}& La capacità di porsi in ascolto + su porte riservate (vedi + sez.~\ref{sec:TCP_func_bind}).\\ + \const{CAP\_NET\_BROADCAST}& La capacità di consentire l'uso di socket in + \itindex{broadcast} \textit{broadcast} e + \itindex{multicast} \textit{multicast}.\\ + \const{CAP\_NET\_RAW} & La capacità di usare socket \texttt{RAW} e + \texttt{PACKET} (vedi sez.~\ref{sec:sock_type}).\\ + \const{CAP\_SETPCAP} & La capacità di modifiche privilegiate alle + \textit{capabilities}.\\ + \const{CAP\_SYS\_ADMIN} & La capacità di eseguire una serie di compiti + amministrativi.\\ + \const{CAP\_SYS\_BOOT} & La capacità di fare eseguire un riavvio del + sistema (vedi sez.~\ref{sec:sys_reboot}).\\ + \const{CAP\_SYS\_CHROOT}& La capacità di eseguire la funzione + \func{chroot} (vedi sez.~\ref{sec:file_chroot}).\\ + \const{CAP\_MAC\_ADMIN} & La capacità amministrare il \textit{Mandatory + Access Control} di Smack (dal kernel 2.6.25).\\ + \const{CAP\_MAC\_OVERRIDE}& La capacità evitare il \textit{Mandatory + Access Control} di Smack (dal kernel 2.6.25).\\ + \const{CAP\_SYS\_MODULE}& La capacità di caricare e rimuovere moduli del + kernel.\\ + \const{CAP\_SYS\_NICE} & La capacità di modificare le varie priorità dei + processi (vedi sez.~\ref{sec:proc_priority}).\\ + \const{CAP\_SYS\_PACCT} & La capacità di usare le funzioni di + \textit{accounting} dei processi (vedi + sez.~\ref{sec:sys_bsd_accounting}).\\ + \const{CAP\_SYS\_PTRACE}& La capacità di tracciare qualunque processo con + \func{ptrace} (vedi + sez.~\ref{sec:process_ptrace}).\\ + \const{CAP\_SYS\_RAWIO} & La capacità di operare sulle porte + di I/O con \func{ioperm} e \func{iopl} (vedi + sez.~\ref{sec:process_io_port}).\\ + \const{CAP\_SYS\_RESOURCE}& La capacità di superare le varie limitazioni + sulle risorse.\\ + \const{CAP\_SYS\_TIME} & La capacità di modificare il tempo di sistema + (vedi sez.~\ref{sec:sys_time}).\\ + \const{CAP\_SYS\_TTY\_CONFIG}& La capacità di simulare un \textit{hangup} + della console, con la funzione + \func{vhangup}.\\ + \const{CAP\_SYSLOG} & La capacità di gestire il buffer dei messaggi + del kernel, (vedi sez.~\ref{sec:sess_daemon}), + introdotta dal kernel 2.6.38 come capacità + separata da \const{CAP\_SYS\_ADMIN}.\\ + \const{CAP\_WAKE\_ALARM}& La capacità di usare i timer di tipo + \const{CLOCK\_BOOTTIME\_ALARM} e + \const{CLOCK\_REALTIME\_ALARM}, vedi + sez.~\ref{sec:sig_timer_adv} (dal kernel 3.0).\\ + \hline + \end{tabular} + \caption{Le costanti che identificano le \textit{capabilities} presenti nel + kernel.} +\label{tab:proc_capabilities} +\end{table} + +\footnotetext{vale a dire i permessi caratteristici del modello classico del + controllo di accesso chiamato \itindex{Discrectionary~Access~Control~(DAC)} + \textit{Discrectionary Access Control} (da cui il nome DAC).} + + +Prima di dettagliare il significato della capacità più generiche, conviene +però dedicare un discorso a parte a \const{CAP\_SETPCAP}, il cui significato è +stato completamente cambiato con l'introduzione delle \textit{file + capabilities} nel kernel 2.6.24. In precedenza questa capacità era quella +che permetteva al processo che la possedeva di impostare o rimuovere le +\textit{capabilities} che fossero presenti nel \textit{permitted set} del +chiamante di un qualunque altro processo. In realtà questo non è mai stato +l'uso inteso nelle bozze dallo standard POSIX, ed inoltre, come si è già +accennato, dato che questa capacità è assente nel \textit{capabilities + bounding set} usato di default, essa non è neanche mai stata realmente +disponibile. + +Con l'introduzione \textit{file capabilities} e il cambiamento del significato +del \textit{capabilities bounding set} la possibilità di modificare le +capacità di altri processi è stata completamente rimossa, e +\const{CAP\_SETPCAP} ha acquisito quello che avrebbe dovuto essere il suo +significato originario, e cioè la capacità del processo di poter inserire nel +suo \textit{inheritable set} qualunque capacità presente nel \textit{bounding + set}. Oltre a questo la disponibilità di \const{CAP\_SETPCAP} consente ad un +processo di eliminare una capacità dal proprio \textit{bounding set} (con la +conseguente impossibilità successiva di eseguire programmi con quella +capacità), o di impostare i \textit{securebits} delle \textit{capabilities}. + +La prima fra le capacità ``\textsl{ampie}'' che occorre dettagliare +maggiormente è \const{CAP\_FOWNER}, che rimuove le restrizioni poste ad un +processo che non ha la proprietà di un file in un vasto campo di +operazioni;\footnote{vale a dire la richiesta che l'user-ID effettivo del + processo (o meglio il \textit{filesystem user-ID}, vedi + sez.~\ref{sec:proc_setuid}) coincida con quello del proprietario.} queste +comprendono i cambiamenti dei permessi e dei tempi del file (vedi +sez.~\ref{sec:file_perm_management} e sez.~\ref{sec:file_file_times}), le +impostazioni degli attributi dei file (vedi sez.~\ref{sec:file_ioctl}) e delle +ACL (vedi sez.~\ref{sec:file_xattr} e \ref{sec:file_ACL}), poter ignorare lo +\itindex{sticky~bit} \textit{sticky bit} nella cancellazione dei file (vedi +sez.~\ref{sec:file_special_perm}), la possibilità di impostare il flag di +\const{O\_NOATIME} con \func{open} e \func{fcntl} (vedi +sez.~\ref{sec:file_open} e sez.~\ref{sec:file_fcntl}) senza restrizioni. -I passi di controllo vengono eseguiti esattamente in questa sequenza, e la -decisione viene presa non appena viene trovata una corrispondenza con gli -identificatori del processo. Questo significa che i permessi presenti in una -voce di tipo \const{ACL\_USER} hanno la precedenza sui permessi ordinari -associati al gruppo proprietario del file (vale a dire su -\const{ACL\_GROUP\_OBJ}). +Una seconda capacità che copre diverse operazioni, in questo caso riguardanti +la rete, è \const{CAP\_NET\_ADMIN}, che consente di impostare le opzioni +privilegiate dei socket (vedi sez.~\ref{sec:sock_generic_options}), abilitare +il \itindex{multicast} \textit{multicasting}, eseguire la configurazione delle +interfacce di rete (vedi sez.~\ref{sec:sock_ioctl_netdevice}) ed impostare la +tabella di instradamento. -Per la gestione delle ACL lo standard \textit{POSIX 1003.1e Draft 17} ha -previsto delle apposite funzioni ed tutta una serie di tipi di dati -dedicati;\footnote{fino a definire un tipo di dato e delle costanti apposite - per identificare i permessi standard di lettura, scrittura ed esecuzione.} -tutte le operazioni devono essere effettuate attraverso tramite questi tipi di -dati, che incapsulano tutte le informazioni contenute nelle ACL. La prima di -queste funzioni che prendiamo in esame è \funcd{acl\_init}, il cui prototipo -è: +Una terza \textit{capability} con vasto campo di applicazione è +\const{CAP\_SYS\_ADMIN}, che copre una serie di operazioni amministrative, +come impostare le quote disco (vedi sez.\ref{sec:disk_quota}), attivare e +disattivare la swap, montare, rimontare e smontare filesystem (vedi +sez.~\ref{sec:sys_file_config}), effettuare operazioni di controllo su +qualunque oggetto dell'IPC di SysV (vedi sez.~\ref{sec:ipc_sysv}), operare +sugli attributi estesi dei file di classe \texttt{security} o \texttt{trusted} +(vedi sez.~\ref{sec:file_xattr}), specificare un \textit{user-ID} arbitrario +nella trasmissione delle credenziali dei socket (vedi +sez.~\ref{sec:socket_credential_xxx}), assegnare classi privilegiate +(\const{IOPRIO\_CLASS\_RT} e prima del kernel 2.6.25 anche +\const{IOPRIO\_CLASS\_IDLE}) per lo scheduling dell'I/O (vedi +sez.~\ref{sec:io_priority}), superare il limite di sistema sul numero massimo +di file aperti,\footnote{quello indicato da \procfile{/proc/sys/fs/file-max}.} +effettuare operazioni privilegiate sulle chiavi mantenute dal kernel (vedi +sez.~\ref{sec:keyctl_management}), usare la funzione \func{lookup\_dcookie}, +usare \const{CLONE\_NEWNS} con \func{unshare} e \func{clone}, (vedi +sez.~\ref{sec:process_clone}). + +Originariamente \const{CAP\_SYS\_NICE} riguardava soltanto la capacità di +aumentare le priorità di esecuzione dei processi, come la diminuzione del +valore di \textit{nice} (vedi sez.~\ref{sec:proc_sched_stand}), l'uso delle +priorità \textit{real-time} (vedi sez.~\ref{sec:proc_real_time}), o +l'impostazione delle affinità di processore (vedi +sez.~\ref{sec:proc_sched_multiprocess}); ma con l'introduzione di priorità +anche riguardo le operazioni di accesso al disco, e, nel caso di sistemi NUMA, +alla memoria, essa viene a coprire anche la possibilità di assegnare priorità +arbitrarie nell'accesso a disco (vedi sez.~\ref{sec:io_priority}) e nelle +politiche di allocazione delle pagine di memoria ai nodi di un sistema NUMA. + +Infine la \textit{capability} \const{CAP\_SYS\_RESOURCE} attiene alla +possibilità di superare i limiti imposti sulle risorse di sistema, come usare +lo spazio disco riservato all'amministratore sui filesystem che lo supportano, +usare la funzione \func{ioctl} per controllare il \textit{journaling} sul +filesystem \acr{ext3}, non subire le quote disco, aumentare i limiti sulle +risorse di un processo (vedi sez.~\ref{sec:sys_resource_limit}) e quelle sul +numero di processi, ed i limiti sulle dimensioni dei messaggi delle code del +SysV IPC (vedi sez.~\ref{sec:ipc_sysv_mq}). + +Per la gestione delle \textit{capabilities} il kernel mette a disposizione due +funzioni che permettono rispettivamente di leggere ed impostare i valori dei +tre insiemi illustrati in precedenza. Queste due funzioni sono \funcd{capget} +e \funcd{capset} e costituiscono l'interfaccia di gestione basso livello; i +loro rispettivi prototipi sono: \begin{functions} - \headdecl{sys/types.h} - \headdecl{sys/acl.h} - - \funcdecl{acl\_t acl\_init(int count)} + \headdecl{sys/capability.h} + + \funcdecl{int capget(cap\_user\_header\_t hdrp, cap\_user\_data\_t datap)} + Legge le \textit{capabilities}. + + \funcdecl{int capset(cap\_user\_header\_t hdrp, const cap\_user\_data\_t + datap)} + Imposta le \textit{capabilities}. - Inizializza un'area di lavoro per una ACL di \param{count} voci. - \bodydesc{La funzione restituisce un puntatore all'area di lavoro in caso di - successo e \const{NULL} in caso di errore, nel qual caso \var{errno} - assumerà uno dei valori: - \begin{errlist} - \item[\errcode{EINVAL}] il valore di \param{count} è negativo. - \item[\errcode{ENOMEM}] non c'è sufficiente memoria disponibile. + \bodydesc{Entrambe le funzioni ritornano 0 in caso di successo e -1 in caso + di errore, nel qual caso \var{errno} può assumere i valori: + \begin{errlist} + \item[\errcode{ESRCH}] si è fatto riferimento ad un processo inesistente. + \item[\errcode{EPERM}] si è tentato di aggiungere una capacità + nell'insieme delle \textit{capabilities} permesse, o di impostare una + capacità non presente nell'insieme di quelle permesse negli insieme + delle effettive o ereditate, o si è cercato di impostare una + \textit{capability} di un altro processo senza avare + \const{CAP\_SETPCAP}. \end{errlist} + ed inoltre \errval{EFAULT} ed \errval{EINVAL}. } \end{functions} -La funzione alloca ed inizializza un'area di memoria che verrà usata per -mantenere i dati di una ACL contenente fino ad un massimo di \param{count} -voci. La funzione ritorna un valore di tipo \type{acl\_t}, da usare in tutte -le altre funzioni che operano sulla ACL. La funzione si limita alla -allocazione iniziale e non inserisce nessun valore nella ACL che resta vuota. -Si tenga presente che pur essendo \type{acl\_t} un tipo opaco che identifica -``\textsl{l'oggetto}'' ACL, il valore restituito dalla funzione non è altro -che un puntatore all'area di memoria allocata per i dati richiesti; pertanto -in caso di fallimento verrà restituito un puntatore nullo e si dovrà -confrontare il valore di ritorno della funzione con ``\code{(acl\_t) NULL}''. +Queste due funzioni prendono come argomenti due tipi di dati dedicati, +definiti come puntatori a due strutture specifiche di Linux, illustrate in +fig.~\ref{fig:cap_kernel_struct}. Per un certo periodo di tempo era anche +indicato che per poterle utilizzare fosse necessario che la macro +\macro{\_POSIX\_SOURCE} risultasse non definita (ed era richiesto di inserire +una istruzione \texttt{\#undef \_POSIX\_SOURCE} prima di includere +\texttt{sys/capability.h}) requisito che non risulta più presente.\footnote{e + non è chiaro neanche quanto sia mai stato davvero necessario.} + +Si tenga presente che le strutture di fig.~\ref{fig:cap_kernel_struct}, come i +prototipi delle due funzioni \func{capget} e \func{capset}, sono soggette ad +essere modificate con il cambiamento del kernel (in particolare i tipi di dati +delle strutture) ed anche se finora l'interfaccia è risultata stabile, non c'è +nessuna assicurazione che questa venga mantenuta,\footnote{viene però + garantito che le vecchie funzioni continuino a funzionare.} Pertanto se si +vogliono scrivere programmi portabili che possano essere eseguiti senza +modifiche o adeguamenti su qualunque versione del kernel è opportuno +utilizzare le interfacce di alto livello che vedremo più avanti. -Una volta che si siano completate le operazioni sui dati di una ACL la memoria -allocata dovrà essere liberata esplicitamente attraverso una chiamata alla -funzione \funcd{acl\_free}, il cui prototipo è: +\begin{figure}[!htb] + \footnotesize + \centering + \begin{minipage}[c]{\textwidth} + \includestruct{listati/cap_user_header_t.h} + \end{minipage} + \normalsize + \caption{Definizione delle strutture a cui fanno riferimento i puntatori + \structd{cap\_user\_header\_t} e \structd{cap\_user\_data\_t} usati per + l'interfaccia di gestione di basso livello delle \textit{capabilities}.} + \label{fig:cap_kernel_struct} +\end{figure} + +La struttura a cui deve puntare l'argomento \param{hdrp} serve ad indicare, +tramite il campo \var{pid}, il PID del processo del quale si vogliono leggere +o modificare le \textit{capabilities}. Con \func{capset} questo, se si usano +le \textit{file capabilities}, può essere solo 0 o PID del processo chiamante, +che sono equivalenti. Il campo \var{version} deve essere impostato al valore +della versione delle stesse usata dal kernel (quello indicato da una delle +costanti \texttt{\_LINUX\_CAPABILITY\_VERSION\_n} di +fig.~\ref{fig:cap_kernel_struct}) altrimenti le funzioni ritorneranno con un +errore di \errcode{EINVAL}, restituendo nel campo stesso il valore corretto +della versione in uso. La versione due è comunque deprecata e non deve essere +usata (il kernel stamperà un avviso). I valori delle \textit{capabilities} +devono essere passati come maschere binarie;\footnote{e si tenga presente che + i valori di tab.~\ref{tab:proc_capabilities} non possono essere combinati + direttamente, indicando il numero progressivo del bit associato alla + relativa capacità.} con l'introduzione delle \textit{capabilities} a 64 bit +inoltre il puntatore \param{datap} non può essere più considerato come +relativo ad una singola struttura, ma ad un vettore di due +strutture.\footnote{è questo cambio di significato che ha portato a deprecare + la versione 2, che con \func{capget} poteva portare ad un buffer overflow + per vecchie applicazioni che continuavano a considerare \param{datap} come + puntatore ad una singola struttura.} + +Dato che le precedenti funzioni, oltre ad essere specifiche di Linux, non +garantiscono la stabilità nell'interfaccia, è sempre opportuno effettuare la +gestione delle \textit{capabilities} utilizzando le funzioni di libreria a +questo dedicate. Queste funzioni, che seguono quanto previsto nelle bozze +dello standard POSIX.1e, non fanno parte delle \acr{glibc} e sono fornite in +una libreria a parte,\footnote{la libreria è \texttt{libcap2}, nel caso di + Debian può essere installata con il pacchetto omonimo.} pertanto se un +programma le utilizza si dovrà indicare esplicitamente l'uso della suddetta +libreria attraverso l'opzione \texttt{-lcap} del compilatore. + +Le funzioni dell'interfaccia delle bozze di POSIX.1e prevedono l'uso di un +\index{tipo!opaco} tipo di dato opaco, \type{cap\_t}, come puntatore ai dati +mantenuti nel cosiddetto \textit{capability state},\footnote{si tratta in + sostanza di un puntatore ad una struttura interna utilizzata dalle librerie, + i cui campi non devono mai essere acceduti direttamente.} in sono +memorizzati tutti i dati delle \textit{capabilities}. In questo modo è +possibile mascherare i dettagli della gestione di basso livello, che potranno +essere modificati senza dover cambiare le funzioni dell'interfaccia, che +faranno riferimento soltanto ad oggetti di questo tipo. L'interfaccia +pertanto non soltanto fornisce le funzioni per modificare e leggere le +\textit{capabilities}, ma anche quelle per gestire i dati attraverso +\type{cap\_t}. + +La prima funzione dell'interfaccia è quella che permette di inizializzare un +\textit{capability state}, allocando al contempo la memoria necessaria per i +relativi dati. La funzione è \funcd{cap\_init} ed il suo prototipo è: \begin{functions} - \headdecl{sys/types.h} - \headdecl{sys/acl.h} - - \funcdecl{int acl\_free(void * obj\_p)} + \headdecl{sys/capability.h} - Disalloca la memoria riservata per i dati di una ACL. + \funcdecl{cap\_t cap\_init(void)} + Crea ed inizializza un \textit{capability state}. - \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ se - \param{obj\_p} non è un puntatore valido, nel qual caso \var{errno} - assumerà il valore \errcode{EINVAL} -} + \bodydesc{La funzione ritorna un valore non nullo in caso di successo e + \val{NULL} in caso di errore, nel qual caso \var{errno} assumerà il + valore \errval{ENOMEM}. + } \end{functions} -Si noti come la funzione richieda come argomento un puntatore di tipo -``\ctyp{void *}'', essa infatti può essere usata non solo per liberare la -memoria allocata per i dati di una ACL, ma anche per quella usata per creare -le stringhe di descrizione testuale delle ACL o per ottenere i valori dei -qualificatori di una voce; pertanto a seconda dei casi occorrerà eseguire un -\textit{cast} a ``\ctyp{void *}'' del tipo di dato di cui si vuole eseguire la -disallocazione. Si tenga presente poi che oltre a \func{acl\_init} esistono -molte altre funzioni che possono allocare memoria per i dati delle ACL, è -pertanto opportuno tenere traccia di tutte queste funzioni perché alla fine -delle operazioni tutta la memoria allocata dovrà essere liberata con -\func{acl\_free}. - -Una volta che si abbiano a disposizione i dati di una ACL tramite il -riferimento ad oggetto di tipo \type{acl\_t} questi potranno essere copiati -con la funzione \funcd{acl\_dup}, il cui prototipo è: +La funzione restituisce il puntatore \type{cap\_t} ad uno stato inizializzato +con tutte le \textit{capabilities} azzerate. In caso di errore (cioè quando +non c'è memoria sufficiente ad allocare i dati) viene restituito \val{NULL} +ed \var{errno} viene impostata a \errval{ENOMEM}. La memoria necessaria a +mantenere i dati viene automaticamente allocata da \func{cap\_init}, ma dovrà +essere disallocata esplicitamente quando non è più necessaria utilizzando, per +questo l'interfaccia fornisce una apposita funzione, \funcd{cap\_free}, il cui +prototipo è: \begin{functions} - \headdecl{sys/types.h} - \headdecl{sys/acl.h} - - \funcdecl{acl\_t acl\_dup(acl\_t acl)} + \headdecl{sys/capability.h} - Crea una copia della ACL \param{acl}. + \funcdecl{int cap\_free(void *obj\_d)} + Disalloca la memoria allocata per i dati delle \textit{capabilities}. - \bodydesc{La funzione restituisce un oggetto di tipo \type{acl\_t} in caso - di successo e \code{(acl\_t)NULL} in caso di errore, nel qual caso - \var{errno} assumerà uno dei valori: - \begin{errlist} - \item[\errcode{EINVAL}] l'argomento \param{acl} non è un puntatore valido - per una ACL. - \item[\errcode{ENOMEM}] non c'è sufficiente memoria disponibile per eseguire - la copia. - \end{errlist} -} + \bodydesc{La funzione ritorna 0 in caso di successo e $-1$ in caso di + errore, nel qual caso \var{errno} assumerà il valore \errval{EINVAL}. + } \end{functions} -La funzione crea una copia dei dati della ACL indicata tramite l'argomento -\param{acl}, allocando autonomamente tutto spazio necessario alla copia e -restituendo un secondo oggetto di tipo \type{acl\_t} come riferimento a -quest'ultima. Valgono per questo le stesse considerazioni fatte per il valore -di ritorno di \func{acl\_init}, ed in particolare il fatto che occorrerà -prevedere una ulteriore chiamata esplicita a \func{acl\_free} per liberare la -memoria occupata dalla copia. +La funzione permette di liberare la memoria allocata dalle altre funzioni +della libreria sia per un \textit{capability state}, nel qual caso l'argomento +dovrà essere un dato di tipo \type{cap\_t}, che per una descrizione testuale +dello stesso,\footnote{cioè quanto ottenuto tramite la funzione + \func{cap\_to\_text}.} nel qual caso l'argomento dovrà essere un dato di +tipo \texttt{char *}. Per questo motivo l'argomento \param{obj\_d} è +dichiarato come \texttt{void *} e deve sempre corrispondere ad un puntatore +ottenuto tramite le altre funzioni della libreria, altrimenti la funzione +fallirà con un errore di \errval{EINVAL}. -Se si deve creare una ACL manualmente l'uso di \func{acl\_init} è scomodo, -dato che la funzione restituisce una ACL vuota, una alternativa allora è usare -\funcd{acl\_from\_mode} che consente di creare una ACL a partire da un valore -di permessi ordinari, il prototipo della funzione è: +Infine si può creare una copia di un \textit{capability state} ottenuto in +precedenza tramite la funzione \funcd{cap\_dup}, il cui prototipo è: \begin{functions} - \headdecl{sys/types.h} - \headdecl{sys/acl.h} - - \funcdecl{acl\_t acl\_from\_mode(mode\_t mode)} + \headdecl{sys/capability.h} - Crea una ACL inizializzata con i permessi di \param{mode}. + \funcdecl{cap\_t cap\_dup(cap\_t cap\_p)} + Duplica un \textit{capability state} restituendone una copia. - \bodydesc{La funzione restituisce un oggetto di tipo \type{acl\_t} in caso - di successo e \code{(acl\_t)NULL} in caso di errore, nel qual caso - \var{errno} assumerà il valore \errval{ENOMEM}. - -} + \bodydesc{La funzione ritorna un valore non nullo in caso di successo e + \val{NULL} in caso di errore, nel qual caso \var{errno} potrà assumere i + valori \errval{ENOMEM} o \errval{EINVAL}. + } \end{functions} -La funzione restituisce una ACL inizializzata con le tre voci obbligatorie -\const{ACL\_USER\_OBJ}, \const{ACL\_GROUP\_OBJ} e \const{ACL\_OTHER} già -impostate secondo la corrispondenza ai valori dei permessi ordinari indicati -dalla maschera passata nell'argomento \param{mode}. Questa funzione è una -estensione usata dalle ACL di Linux e non è portabile, ma consente di -semplificare l'inizializzazione in maniera molto comoda. +La funzione crea una copia del \textit{capability state} posto all'indirizzo +\param{cap\_p} che si è passato come argomento, restituendo il puntatore alla +copia, che conterrà gli stessi valori delle \textit{capabilities} presenti +nell'originale. La memoria necessaria viene allocata automaticamente dalla +funzione. Una volta effettuata la copia i due \textit{capability state} +potranno essere modificati in maniera completamente +indipendente.\footnote{alla fine delle operazioni si ricordi però di + disallocare anche la copia, oltre all'originale. } -Altre due funzioni che consentono di creare una ACL già inizializzata sono -\funcd{acl\_get\_fd} e \funcd{acl\_get\_file}, che però sono per lo più -utilizzate per leggere la ACL corrente di un file; i rispettivi prototipi -sono: +Una seconda classe di funzioni di servizio previste dall'interfaccia sono +quelle per la gestione dei dati contenuti all'interno di un \textit{capability + state}; la prima di queste è \funcd{cap\_clear}, il cui prototipo è: \begin{functions} - \headdecl{sys/types.h} - \headdecl{sys/acl.h} - - \funcdecl{acl\_t acl\_get\_file(const char *path\_p, acl\_type\_t type)} - \funcdecl{acl\_t acl\_get\_fd(int fd)} - - Ottiene i dati delle ACL di un file. - - \bodydesc{La funzione restituisce un oggetto di tipo \type{acl\_t} in caso - di successo e \code{(acl\_t)NULL} in caso di errore, nel qual caso - \var{errno} assumerà uno dei valori: - \begin{errlist} - \item[\errcode{ENOMEM}] non c'è memoria sufficiente per allocare i dati. - \item[\errcode{ENOTSUP}] il filesystem cui fa riferimento il file non - supporta le ACL. - \end{errlist} - ed inoltre \errval{EBADF} per \func{acl\_get\_fd}, ed \errval{EINVAL} per - valori scorretti di \param{type} e tutti i possibili errori per l'accesso ad - un file per \func{acl\_get\_file}. + \headdecl{sys/capability.h} -} + \funcdecl{int cap\_clear(cap\_t cap\_p)} + Inizializza un \textit{capability state} cancellando tutte le + \textit{capabilities}. + + \bodydesc{La funzione ritorna 0 in caso di successo e $-1$ in caso di + errore, nel qual caso \var{errno} assumerà il valore \errval{EINVAL}. + } \end{functions} -Le due funzioni ritornano, con un oggetto di tipo \type{acl\_t}, il valore -della ACL correntemente associata ad un file, che può essere identificato -tramite un file descriptor usando \func{acl\_get\_fd} o con un pathname usando -\func{acl\_get\_file}. Nel caso di quest'ultima funzione, che può richiedere -anche la ACL relativa ad una directory, il secondo argomento \param{type} -consente di specificare se si vuole ottenere la ACL di default o quella di -accesso. Questo argomento deve essere di tipo \type{acl\_type\_t} e può -assumere solo i due valori riportati in tab.~\ref{tab:acl_type}. +La funzione si limita ad azzerare tutte le \textit{capabilities} presenti nel +\textit{capability state} all'indirizzo \param{cap\_p} passato come argomento, +restituendo uno stato \textsl{vuoto}, analogo a quello che si ottiene nella +creazione con \func{cap\_init}. \begin{table}[htb] \centering \footnotesize - \begin{tabular}{|l|l|} + \begin{tabular}[c]{|l|l|} \hline - \textbf{Tipo} & \textbf{Descrizione} \\ + \textbf{Valore} & \textbf{Significato} \\ \hline \hline - \const{ACL\_TYPE\_ACCESS} & indica una ACL di accesso.\\ - \const{ACL\_TYPE\_DEFAULT}& indica una ACL di default.\\ + \const{CAP\_EFFECTIVE} & Capacità dell'insieme \textsl{effettivo}.\\ + \const{CAP\_PERMITTED} & Capacità dell'insieme \textsl{permesso}.\\ + \const{CAP\_INHERITABLE}& Capacità dell'insieme \textsl{ereditabile}.\\ \hline \end{tabular} - \caption{Le costanti che identificano il tipo di ACL.} - \label{tab:acl_type} + \caption{Valori possibili per il tipo di dato \type{cap\_flag\_t} che + identifica gli insiemi delle \textit{capabilities}.} + \label{tab:cap_set_identifier} \end{table} -Si tenga presente che nel caso di \func{acl\_get\_file} occorrerà che il -processo chiamante abbia privilegi di accesso sufficienti a poter leggere gli -attributi estesi dei file (come illustrati in sez.~\ref{sec:file_xattr}); -inoltre una ACL di tipo \const{ACL\_TYPE\_DEFAULT} potrà essere richiesta -soltanto per una directory, e verrà restituita solo se presente, altrimenti -verrà restituita una ACL vuota. - -Infine si potrà creare una ACL direttamente dalla sua rappresentazione -testuale con la funzione \funcd{acl\_from\_text}, il cui prototipo è: +Una variante di \func{cap\_clear} è \funcd{cap\_clear\_flag} che cancella da +un \textit{capability state} tutte le \textit{capabilities} di un certo +insieme fra quelli di pag.~\pageref{sec:capabilities_set}, il suo prototipo +è: \begin{functions} - \headdecl{sys/types.h} - \headdecl{sys/acl.h} - - \funcdecl{acl\_t acl\_from\_text(const char *buf\_p)} + \headdecl{sys/capability.h} - Crea una ACL a partire dalla sua rappresentazione testuale. - - \bodydesc{La funzione restituisce un oggetto di tipo \type{acl\_t} in caso - di successo e \code{(acl\_t)NULL} in caso di errore, nel qual caso - \var{errno} assumerà uno dei valori: - \begin{errlist} - \item[\errcode{ENOMEM}] non c'è memoria sufficiente per allocare i dati. - \item[\errcode{EINVAL}] la rappresentazione testuale all'indirizzo - \param{buf\_p} non è valida. - \end{errlist} + \funcdecl{int cap\_clear\_flag(cap\_t cap\_p, cap\_flag\_t flag)} -} + Cancella dal \textit{capability state} \param{cap\_p} tutte le + \textit{capabilities} dell'insieme \param{flag}. + + \bodydesc{La funzione ritorna 0 in caso di successo e $-1$ in caso di + errore, nel qual caso \var{errno} assumerà il valore \errval{EINVAL}. } \end{functions} -La funzione prende come argomento il puntatore ad un buffer dove si è inserita -la rappresentazione testuale della ACL che si vuole creare, la memoria -necessaria viene automaticamente allocata ed in caso di successo viene -restituito come valore di ritorno un oggetto di tipo \type{acl\_t} con il -contenuto della stessa, che come per le precedenti funzioni, dovrà essere -disallocato esplicitamente al termine del suo utilizzo. - -La rappresentazione testuale di una ACL è quella usata anche dai comandi -ordinari per la gestione delle ACL (\texttt{getfacl} e \texttt{setfacl}), che -prevede due diverse forme, estesa e breve, entrambe supportate da -\func{acl\_from\_text}. La forma estesa prevede che sia specificata una voce -per riga, nella forma: -\begin{Verbatim} - tipo:qualificatore:permessi -\end{Verbatim} -dove il tipo può essere uno fra \texttt{user}, \texttt{group}, \texttt{other} -e \texttt{mask}. Il qualificatore è presente solo per \texttt{user} e -\texttt{group} e indica l'utente o il gruppo a cui la voce si riferisce; i -permessi sono espressi con una tripletta di lettere analoga a quella usata per -i permessi dei file.\footnote{vale a dire \texttt{r} per il permesso di - lettura, \texttt{w} per il permesso di scrittura, \texttt{x} per il permesso - di esecuzione (scritti in quest'ordine) e \texttt{-} per l'assenza del - permesso.} - -Va precisato che i due tipi \texttt{user} e \texttt{group} sono usati -rispettivamente per indicare delle voci relative ad utenti e -gruppi,\footnote{cioè per voci di tipo \const{ACL\_USER\_OBJ} e - \const{ACL\_USER} per \texttt{user} e \const{ACL\_GROUP\_OBJ} e - \const{ACL\_GROUP} per \texttt{group}.} applicate sia a quelli proprietari -del file che a quelli generici; quelle dei proprietari si riconoscono per -l'assenza di un qualificatore, ed in genere si scrivono per prima delle altre. -Il significato delle voci di tipo \texttt{mask} e \texttt{mark} è evidente. In -questa forma si possono anche inserire dei commenti precedendoli con il -carattere ``\texttt{\#}''. - -La forma breve prevede invece la scrittura delle singole voci su una riga, -separate da virgole; come specificatori del tipo di voce si possono usare le -iniziali dei valori usati nella forma estesa (cioè ``\texttt{u}'', -``\texttt{g}'', ``\texttt{o}'' e ``\texttt{m}''), mentre le altri parte della -voce sono le stesse. In questo caso non sono consentiti permessi. +La funzione richiede che si indichi quale degli insiemi si intente cancellare +con l'argomento \param{flag}. Questo deve essere specificato con una variabile +di tipo \type{cap\_flag\_t} che può assumere esclusivamente\footnote{si tratta + in effetti di un tipo enumerato, come si può verificare dalla sua + definizione che si trova in \texttt{/usr/include/sys/capability.h}.} uno dei +valori illustrati in tab.~\ref{tab:cap_set_identifier}. -Per la conversione inversa, che consente di ottenere la rappresentazione -testuale di una ACL, sono invece disponibili due funzioni, la prima delle due, -di uso più immediato, è \funcd{acl\_to\_text}, il cui prototipo è: +Si possono inoltre confrontare in maniera diretta due diversi +\textit{capability state} con la funzione \funcd{cap\_compare}; il suo +prototipo è: \begin{functions} - \headdecl{sys/types.h} - \headdecl{sys/acl.h} - - \funcdecl{char * acl\_to\_text(acl\_t acl, ssize\_t *len\_p)} + \headdecl{sys/capability.h} + \funcdecl{int cap\_compare(cap\_t cap\_a, cap\_t cap\_b)} - Produce la rappresentazione testuale di una ACL. + Confronta due \textit{capability state}. - \bodydesc{La funzione restituisce il puntatore ad una stringa con la - rappresentazione testuale della ACL in caso di successo e - \code(acl\_t){NULL} in caso di errore, nel qual caso \var{errno} assumerà - uno dei valori: - \begin{errlist} - \item[\errcode{ENOMEM}] non c'è memoria sufficiente per allocare i dati. - \item[\errcode{EINVAL}] la ACL indicata da \param{acl} non è valida. - \end{errlist} + \bodydesc{La funzione ritorna 0 se i \textit{capability state} sono identici + ed un valore positivo se differiscono, non sono previsti errori.} +\end{functions} -} +La funzione esegue un confronto fra i due \textit{capability state} passati +come argomenti e ritorna in un valore intero il risultato, questo è nullo se +sono identici o positivo se vi sono delle differenze. Il valore di ritorno +della funzione consente inoltre di per ottenere ulteriori informazioni su +quali sono gli insiemi di \textit{capabilities} che risultano differenti. Per +questo si può infatti usare la apposita macro \macro{CAP\_DIFFERS}: +\begin{functions} + \funcdecl{int CAP\_DIFFERS(value, flag)} Controlla lo stato di eventuali + differenze delle \textit{capabilities} nell'insieme \texttt{flag}. \end{functions} -La funzione restituisce il puntatore ad una stringa terminata da NUL -contenente la rappresentazione in forma estesa della ACL passata come -argomento, ed alloca automaticamente la memoria necessaria. Questa dovrà poi -essere liberata, quando non più necessaria, con \func{acl\_free}. Se -nell'argomento \param{len\_p} si passa un valore puntatore ad una variabile -intera in questa verrà restituita la dimensione della stringa con la -rappresentazione testuale (non comprendente il carattere nullo finale). +La macro che richiede si passi nell'argomento \texttt{value} il risultato +della funzione \func{cap\_compare} e in \texttt{flag} l'indicazione (coi +valori di tab.~\ref{tab:cap_set_identifier}) dell'insieme che si intende +controllare; restituirà un valore diverso da zero se le differenze rilevate da +\func{cap\_compare} sono presenti nell'insieme indicato. -La seconda funzione, \funcd{acl\_to\_any\_text}, permette di controllare con -dovizia di dettagli la generazione della stringa contenente la -rappresentazione testuale della ACL, il suo prototipo è: +Per la gestione dei singoli valori delle \textit{capabilities} presenti in un +\textit{capability state} l'interfaccia prevede due funzioni specifiche, +\funcd{cap\_get\_flag} e \funcd{cap\_set\_flag}, che permettono +rispettivamente di leggere o impostare il valore di una capacità all'interno +in uno dei tre insiemi già citati; i rispettivi prototipi sono: \begin{functions} - \headdecl{sys/types.h} - \headdecl{sys/acl.h} - - \funcdecl{char * acl\_to\_any\_text(acl\_t acl, const char *prefix, char - separator, int options)} - - Produce la rappresentazione testuale di una ACL. + \headdecl{sys/capability.h} - \bodydesc{La funzione restituisce il puntatore ad una stringa con la - rappresentazione testuale della ACL in caso di successo e \code{NULL} in - caso di errore, nel qual caso \var{errno} assumerà uno dei valori: - \begin{errlist} - \item[\errcode{ENOMEM}] non c'è memoria sufficiente per allocare i dati. - \item[\errcode{EINVAL}] la ACL indicata da \param{acl} non è valida. - \end{errlist} + \funcdecl{int cap\_get\_flag(cap\_t cap\_p, cap\_value\_t cap, cap\_flag\_t + flag, cap\_flag\_value\_t *value\_p)} + Legge il valore di una \textit{capability}. + \funcdecl{int cap\_set\_flag(cap\_t cap\_p, cap\_flag\_t flag, int ncap, + cap\_value\_t *caps, cap\_flag\_value\_t value)} + Imposta il valore di una \textit{capability}. + + \bodydesc{Le funzioni ritornano 0 in caso di successo e $-1$ in caso di + errore, nel qual caso \var{errno} assumerà il valore \errval{EINVAL}. } \end{functions} -La funzione converte in formato testo la ACL indicata dall'argomento -\param{acl}, usando il carattere \param{separator} come separatore delle -singole voci; se l'argomento \param{prefix} non è nullo la stringa da esso -indicata viene utilizzata come prefisso per le singole voci. +In entrambe le funzioni l'argomento \param{cap\_p} indica il puntatore al +\textit{capability state} su cui operare, mentre l'argomento \param{flag} +indica su quale dei tre insiemi si intende operare, sempre con i valori di +tab.~\ref{tab:cap_set_identifier}. -L'ultimo argomento, \param{options}, consente di controllare la modalità con -cui viene generata la rappresentazione testuale. Un valore nullo fa si che -vengano usati gli identificatori standard \texttt{user}, \texttt{group}, -\texttt{other} e \texttt{mask} con i nomi di utenti e gruppi risolti rispetto -ai loro valori numerici. Altrimenti si può specificare un valore in forma di -maschera binaria, da ottenere con un OR aritmetico dei valori riportati in -tab.~\ref{tab:acl_to_text_options}. +La capacità che si intende controllare o impostare invece deve essere +specificata attraverso una variabile di tipo \type{cap\_value\_t}, che può +prendere come valore uno qualunque di quelli riportati in +tab.~\ref{tab:proc_capabilities}, in questo caso però non è possibile +combinare diversi valori in una maschera binaria, una variabile di tipo +\type{cap\_value\_t} può indicare una sola capacità.\footnote{in + \texttt{sys/capability.h} il tipo \type{cap\_value\_t} è definito come + \ctyp{int}, ma i valori validi sono soltanto quelli di + tab.~\ref{tab:proc_capabilities}.} + +Infine lo stato di una capacità è descritto ad una variabile di tipo +\type{cap\_flag\_value\_t}, che a sua volta può assumere soltanto +uno\footnote{anche questo è un tipo enumerato.} dei valori di +tab.~\ref{tab:cap_value_type}. \begin{table}[htb] \centering \footnotesize - \begin{tabular}{|l|p{8cm}|} + \begin{tabular}[c]{|l|l|} \hline - \textbf{Tipo} & \textbf{Descrizione} \\ + \textbf{Valore} & \textbf{Significato} \\ \hline \hline - \const{TEXT\_ABBREVIATE} & stampa le voci in forma abbreviata.\\ - \const{TEXT\_NUMERIC\_IDS} & non effettua la risoluzione numerica di - user-ID e group-ID.\\ - \const{TEXT\_SOME\_EFFECTIVE}& per ciascuna voce che contiene permessi che - vengono eliminati dalla \const{ACL\_MASK} - viene generato un commento con i permessi - effettivamente risultanti; il commento è - separato con un tabulatore.\\ - \const{TEXT\_ALL\_EFFECTIVE} & viene generato un commento con i permessi - effettivi per ciascuna voce che contiene - permessi citati nella \const{ACL\_MASK}, - anche quando questi non vengono modificati - da essa; il commento è separato con un - tabulatore.\\ - \const{TEXT\_SMART\_INDENT} & da usare in combinazione con le precedenti - \const{TEXT\_SOME\_EFFECTIVE} e - \const{TEXT\_ALL\_EFFECTIVE} aumenta - automaticamente il numero di spaziatori - prima degli eventuali commenti in modo da - mantenerli allineati.\\ + \const{CAP\_CLEAR}& La capacità non è impostata.\\ + \const{CAP\_SET} & La capacità è impostata.\\ \hline \end{tabular} - \caption{Possibili valori per l'argomento \param{options} di - \func{acl\_to\_any\_text}.} - \label{tab:acl_to_text_options} + \caption{Valori possibili per il tipo di dato \type{cap\_flag\_value\_t} che + indica lo stato di una capacità.} + \label{tab:cap_value_type} \end{table} -Come per \func{acl\_to\_text} anche in questo caso il buffer contenente la -rappresentazione testuale dell'ACL, di cui la funzione restituisce -l'indirizzo, viene allocato automaticamente, e dovrà essere esplicitamente -disallocato con una chiamata ad \func{acl\_free}. Si tenga presente infine che -questa funzione è una estensione specifica di Linux, e non è presente nella -bozza dello standard POSIX.1e. - -Per quanto utile per la visualizzazione o l'impostazione da comando delle ACL, -la forma testuale non è la più efficiente per poter memorizzare i dati -relativi ad una ACL, ad esempio quando si vuole eseguirne una copia a scopo di -archiviazione. Per questo è stata prevista la possibilità di utilizzare una -rappresentazione delle ACL in una apposita forma binaria contigua e -persistente. È così possibile copiare il valore di una ACL in un buffer e da -questa rappresentazione tornare indietro e generare una ACL. - -Lo standard POSIX.1e prevede a tale scopo tre funzioni, la prima e più -semplice è \funcd{acl\_size}, che consente di ottenere la dimensione che avrà -la citata rappresentazione binaria, in modo da poter allocare per essa un -buffer di dimensione sufficiente, il suo prototipo è: -\begin{functions} - \headdecl{sys/types.h} - \headdecl{sys/acl.h} - - \funcdecl{ssize\_t acl\_size(acl\_t acl)} - - Determina la dimensione della rappresentazione binaria di una ACL. - - \bodydesc{La funzione restituisce in caso di successo la dimensione in byte - della rappresentazione binaria della ACL indicata da \param{acl} e $-1$ in - caso di errore, nel qual caso \var{errno} assumerà uno dei valori: - \begin{errlist} - \item[\errcode{EINVAL}] la ACL indicata da \param{acl} non è valida. - \end{errlist} - -} -\end{functions} +La funzione \func{cap\_get\_flag} legge lo stato della capacità indicata +dall'argomento \param{cap} all'interno dell'insieme indicato dall'argomento +\param{flag} lo restituisce nella variabile puntata +dall'argomento \param{value\_p}. Questa deve essere di tipo +\type{cap\_flag\_value\_t} ed assumerà uno dei valori di +tab.~\ref{tab:cap_value_type}. La funzione consente pertanto di leggere solo +lo stato di una capacità alla volta. -Prima di effettuare la lettura della rappresentazione binaria è sempre -necessario allocare un buffer di dimensione sufficiente a contenerla, pertanto -prima si dovrà far ricorso a \funcd{acl\_size} per ottenere tale dimensione e -poi allocare il buffer con una delle funzioni di -sez.~\ref{sec:proc_mem_alloc}. Una volta terminato l'uso della -rappresentazione binaria, il buffer dovrà essere esplicitamente disallocato. +La funzione \func{cap\_set\_flag} può invece impostare in una sola chiamata +più \textit{capabilities}, anche se solo all'interno dello stesso insieme ed +allo stesso valore. Per questo motivo essa prende un vettore di valori di tipo +\type{cap\_value\_t} nell'argomento \param{caps}, la cui dimensione viene +specificata dall'argomento \param{ncap}. Il tipo di impostazione da eseguire +(cancellazione o impostazione) per le capacità elencate in \param{caps} viene +indicato dall'argomento \param{value} sempre con i valori di +tab.~\ref{tab:cap_value_type}. -La funzione che consente di leggere la rappresentazione binaria di una ACL è -\funcd{acl\_copy\_ext}, il cui prototipo è: +Per semplificare la gestione delle \textit{capabilities} l'interfaccia prevede +che sia possibile utilizzare anche una rappresentazione testuale del contenuto +di un \textit{capability state} e fornisce le opportune funzioni di +gestione;\footnote{entrambe erano previste dalla bozza dello standard + POSIX.1e.} la prima di queste, che consente di ottenere la rappresentazione +testuale, è \funcd{cap\_to\_text}, il cui prototipo è: \begin{functions} - \headdecl{sys/types.h} - \headdecl{sys/acl.h} + \headdecl{sys/capability.h} + + \funcdecl{char * cap\_to\_text(cap\_t caps, ssize\_t * length\_p)} + + Genera una visualizzazione testuale delle \textit{capabilities}. - \funcdecl{ssize\_t acl\_copy\_ext(void *buf\_p, acl\_t acl, ssize\_t size)} + \bodydesc{La funzione ritorna un puntatore alla stringa con la descrizione + delle \textit{capabilities} in caso di successo e \val{NULL} in caso di + errore, nel qual caso \var{errno} può assumere i valori \errval{EINVAL} o + \errval{ENOMEM}. + } +\end{functions} - Ottiene la rappresentazione binaria di una ACL. +La funzione ritorna l'indirizzo di una stringa contente la descrizione +testuale del contenuto del \textit{capability state} \param{caps} passato come +argomento, e, qualora l'argomento \param{length\_p} sia diverso da \val{NULL}, +restituisce nella variabile intera da questo puntata la lunghezza della +stringa. La stringa restituita viene allocata automaticamente dalla funzione e +pertanto dovrà essere liberata con \func{cap\_free}. + +La rappresentazione testuale, che viene usata anche di programmi di gestione a +riga di comando, prevede che lo stato venga rappresentato con una stringa di +testo composta da una serie di proposizioni separate da spazi, ciascuna delle +quali specifica una operazione da eseguire per creare lo stato finale. Nella +rappresentazione si fa sempre conto di partire da uno stato in cui tutti gli +insiemi sono vuoti e si provvede a impostarne i contenuti. + +Ciascuna proposizione è nella forma di un elenco di capacità, espresso con i +nomi di tab.~\ref{tab:proc_capabilities} separati da virgole, seguito da un +operatore, e dall'indicazione degli insiemi a cui l'operazione si applica. I +nomi delle capacità possono essere scritti sia maiuscoli che minuscoli, viene +inoltre riconosciuto il nome speciale \texttt{all} che è equivalente a +scrivere la lista completa. Gli insiemi sono identificati dalle tre lettere +iniziali: ``\texttt{p}'' per il \textit{permitted}, ``\texttt{i}'' per +l'\textit{inheritable} ed ``\texttt{e}'' per l'\textit{effective} che devono +essere sempre minuscole e se ne può indicare più di uno. + +Gli operatori possibili sono solo tre: ``\texttt{+}'' che aggiunge le capacità +elencate agli insiemi indicati, ``\texttt{-}'' che le toglie e ``\texttt{=}'' +che le assegna esattamente. I primi due richiedono che sia sempre indicato sia +un elenco di capacità che gli insiemi a cui esse devono applicarsi, e +rispettivamente attiveranno o disattiveranno le capacità elencate nell'insieme +o negli insiemi specificati, ignorando tutto il resto. I due operatori possono +anche essere combinati nella stessa proposizione, per aggiungere e togliere le +capacità dell'elenco da insiemi diversi. + +L'assegnazione si applica invece su tutti gli insiemi allo stesso tempo, +pertanto l'uso di ``\texttt{=}'' è equivalente alla cancellazione preventiva +di tutte le capacità ed alla impostazione di quelle elencate negli insiemi +specificati, questo significa che in genere lo si usa una sola volta +all'inizio della stringa. In tal caso l'elenco delle capacità può non essere +indicato e viene assunto che si stia facendo riferimento a tutte quante senza +doverlo scrivere esplicitamente. + +Come esempi avremo allora che un processo non privilegiato di un utente, che +non ha nessuna capacità attiva, avrà una rappresentazione nella forma +``\texttt{=}'' che corrisponde al fatto che nessuna capacità viene assegnata a +nessun insieme (vale la cancellazione preventiva), mentre un processo con +privilegi di amministratore avrà una rappresentazione nella forma +``\texttt{=ep}'' in cui tutte le capacità vengono assegnate agli insiemi +\textit{permitted} ed \textit{effective} (e l'\textit{inheritable} è ignorato +in quanto per le regole viste a pag.~\ref{sec:capability-uid-transition} le +capacità verranno comunque attivate attraverso una \func{exec}). Infine, come +esempio meno banale dei precedenti, otterremo per \texttt{init} una +rappresentazione nella forma ``\texttt{=ep cap\_setpcap-e}'' dato che come +accennato tradizionalmente \const{CAP\_SETPCAP} è sempre stata rimossa da +detto processo. + +Viceversa per passare ottenere un \textit{capability state} dalla sua +rappresentazione testuale si può usare \funcd{cap\_from\_text}, il cui +prototipo è: +\begin{functions} + \headdecl{sys/capability.h} - \bodydesc{La funzione restituisce in caso di successo la dimensione in byte - della rappresentazione binaria della ACL indicata da \param{acl} e $-1$ in - caso di errore, nel qual caso \var{errno} assumerà uno dei valori: - \begin{errlist} - \item[\errcode{EINVAL}] la ACL indicata da \param{acl} non è valida o - \param{size} è negativo o nullo. - \item[\errcode{ERANGE}] il valore di \param{size} è più piccolo della - dimensione della rappresentazione della ACL. - \end{errlist} + \funcdecl{cap\_t cap\_from\_text(const char *string)} -} -\end{functions} + Crea un \textit{capability state} dalla sua rappresentazione testuale. -La funzione salverà la rappresentazione binaria della ACL indicata da -\param{acl} sul buffer posto all'indirizzo \param{buf\_p} e lungo \param{size} -byte, restituendo la dimensione della stessa come valore di ritorno. Qualora -la dimensione della rappresentazione ecceda il valore di \param{size} la -funzione fallirà con un errore di \errcode{ERANGE}. La funzione non ha nessun -effetto sulla ACL indicata da \param{acl}. + \bodydesc{La funzione ritorna un puntatore valido in caso di successo e + \val{NULL} in caso di errore, nel qual caso \var{errno} può assumere i + valori \errval{EINVAL} o \errval{ENOMEM}.} +\end{functions} -Viceversa se si vuole ripristinare una ACL a partire dalla rappresentazione -binaria della stessa disponibile in un buffer si potrà usare la funzione -\funcd{acl\_copy\_int}, il cui prototipo è: +La funzione restituisce il puntatore ad un \textit{capability state} +inizializzato con i valori indicati nella stringa \param{string} che ne +contiene la rappresentazione testuale. La memoria per il \textit{capability + state} viene allocata automaticamente dalla funzione e dovrà essere liberata +con \func{cap\_free}. + +Alle due funzioni citate se ne aggiungono altre due che consentono di +convertire i valori delle costanti di tab.~\ref{tab:proc_capabilities} nelle +stringhe usate nelle rispettive rappresentazioni e viceversa. Le due funzioni, +\func{cap\_to\_name} e \func{cap\_from\_name}, sono estensioni specifiche di +Linux ed i rispettivi prototipi sono: \begin{functions} - \headdecl{sys/types.h} - \headdecl{sys/acl.h} + \headdecl{sys/capability.h} + + \funcdecl{char * cap\_to\_name(cap\_value\_t cap)} + \funcdecl{int cap\_from\_name(const char *name, cap\_value\_t *cap\_p)} + Convertono le \textit{capabilities} dalle costanti alla rappresentazione + testuale e viceversa. - \funcdecl{ssize\_t acl\_copy\_int(const void *buf\_p)} + \bodydesc{La funzione \func{cap\_to\_name} ritorna un valore diverso da + \val{NULL} in caso di successo e \val{NULL} in caso di errore, mentre + \func{cap\_to\_name} ritorna rispettivamente 0 e $-1$; per entrambe in + caso di errore \var{errno} può assumere i valori \errval{EINVAL} o + \errval{ENOMEM}. } +\end{functions} - Ripristina la rappresentazione binaria di una ACL. +La prima funzione restituisce la stringa (allocata automaticamente e che dovrà +essere liberata con \func{cap\_free}) che corrisponde al valore della +capacità \param{cap}, mentre la seconda restituisce nella variabile puntata +da \param{cap\_p} il valore della capacità rappresentata dalla +stringa \param{name}. - \bodydesc{La funzione restituisce un oggetto di tipo \type{acl\_t} in caso - di successo e \code{(acl\_t)NULL} in caso di errore, nel qual caso - \var{errno} assumerà uno dei valori: - \begin{errlist} - \item[\errcode{EINVAL}] il buffer all'indirizzo \param{buf\_p} non contiene - una rappresentazione corretta di una ACL. - \item[\errcode{ENOMEM}] non c'è memoria sufficiente per allocare un oggetto - \type{acl\_t} per la ACL richiesta. - \end{errlist} +Fin quei abbiamo trattato solo le funzioni di servizio relative alla +manipolazione dei \textit{capability state} come strutture di dati; +l'interfaccia di gestione prevede però anche le funzioni per trattare le +\textit{capabilities} presenti nei processi. La prima di queste funzioni è +\funcd{cap\_get\_proc} che consente la lettura delle \textit{capabilities} del +processo corrente, il suo prototipo è: +\begin{functions} + \headdecl{sys/capability.h} -} + \funcdecl{cap\_t cap\_get\_proc(void)} + Legge le \textit{capabilities} del processo corrente. + + \bodydesc{La funzione ritorna un valore diverso da \val{NULL} in caso di + successo e \val{NULL} in caso di errore, nel qual caso \var{errno} può + assumere i valori \errval{EINVAL}, \errval{EPERM} o \errval{ENOMEM}. } \end{functions} -La funzione in caso di successo alloca autonomamente un oggetto di tipo -\type{acl\_t} che viene restituito come valore di ritorno con il contenuto -della ACL rappresentata dai dati contenuti nel buffer puntato da -\param{buf\_p}. Si ricordi che come per le precedenti funzioni l'oggetto -\type{acl\_t} dovrà essere disallocato esplicitamente al termine del suo -utilizzo. +La funzione legge il valore delle \textit{capabilities} associate al processo +da cui viene invocata, restituendo il risultato tramite il puntatore ad un +\textit{capability state} contenente tutti i dati che provvede ad allocare +autonomamente e che di nuovo occorrerà liberare con \func{cap\_free} quando +non sarà più utilizzato. -Una volta che si disponga della ACL desiderata, questa potrà essere impostata -su un file o una directory. Per impostare una ACL sono disponibili due -funzioni; la prima è \funcd{acl\_set\_file}, che opera sia su file che su -directory, ed il cui prototipo è: +Se invece si vogliono leggere le \textit{capabilities} di un processo +specifico occorre usare la funzione \funcd{capgetp}, il cui +prototipo\footnote{su alcune pagine di manuale la funzione è descritta con un + prototipo sbagliato, che prevede un valore di ritorno di tipo \type{cap\_t}, + ma il valore di ritorno è intero, come si può verificare anche dalla + dichiarazione della stessa in \texttt{sys/capability.h}.} è: \begin{functions} - \headdecl{sys/types.h} - \headdecl{sys/acl.h} - - \funcdecl{int acl\_set\_file(const char *path, acl\_type\_t type, acl\_t - acl)} - - Imposta una ACL su un file o una directory. + \headdecl{sys/capability.h} - \bodydesc{La funzione restituisce $0$ in caso di successo e $-1$ in caso di - errore, nel qual caso \var{errno} assumerà uno dei valori: - \begin{errlist} - \item[\errcode{EACCES}] o un generico errore di accesso a \param{path} o il - valore di \param{type} specifica una ACL il cui tipo non può essere - assegnato a \param{path}. - \item[\errcode{EINVAL}] o \param{acl} non è una ACL valida, o \param{type} - ha in valore non corretto. - \item[\errcode{ENOSPC}] non c'è spazio disco sufficiente per contenere i - dati aggiuntivi della ACL. - \item[\errcode{ENOTSUP}] si è cercato di impostare una ACL su un file - contenuto in un filesystem che non supporta le ACL. - \end{errlist} - ed inoltre \errval{ENOENT}, \errval{ENOTDIR}, \errval{ENAMETOOLONG}, - \errval{EROFS}, \errval{EPERM}. -} + \funcdecl{int capgetp(pid\_t pid, cap\_t cap\_d)} + Legge le \textit{capabilities} del processo indicato da \param{pid}. + + \bodydesc{La funzione ritorna 0 in caso di successo e $-1$ in caso di + errore, nel qual caso \var{errno} può assumere i valori \errval{EINVAL}, + \errval{EPERM} o \errval{ENOMEM}. + } \end{functions} +%TODO controllare e correggere i codici di errore!!! -La funzione consente di assegnare la ACL contenuta in \param{acl} al file o -alla directory indicate dal pathname \param{path}, mentre con \param{type} si -indica il tipo di ACL utilizzando le costanti di tab.~\ref{tab:acl_type}, ma -si tenga presente che le ACL di default possono essere solo impostate -qualora \param{path} indichi una directory. Inoltre perché la funzione abbia -successo la ACL dovrà essere valida, e contenere tutti le voci necessarie, -unica eccezione è quella in cui si specifica una ACL vuota per cancellare la -ACL di default associata a \func{path}.\footnote{questo però è una estensione - della implementazione delle ACL di Linux, la bozza di standard POSIX.1e - prevedeva l'uso della apposita funzione \funcd{acl\_delete\_def\_file}, che - prende come unico argomento il pathname della directory di cui si vuole - cancellare l'ACL di default, per i dettagli si ricorra alla pagina di - manuale.} La seconda funzione che consente di impostare una ACL è -\funcd{acl\_set\_fd}, ed il suo prototipo è: +La funzione legge il valore delle \textit{capabilities} del processo indicato +con l'argomento \param{pid}, e restituisce il risultato nel \textit{capability + state} posto all'indirizzo indicato con l'argomento +\param{cap\_d}; a differenza della precedente in questo caso il +\textit{capability state} deve essere stato creato in precedenza. Qualora il +processo indicato non esista si avrà un errore di \errval{ESRCH}. Gli stessi +valori possono essere letti direttamente nel filesystem \textit{proc}, nei +file \texttt{/proc//status}; ad esempio per \texttt{init} si otterrà +qualcosa del tipo: +\begin{Verbatim} +... +CapInh: 0000000000000000 +CapPrm: 00000000fffffeff +CapEff: 00000000fffffeff +... +\end{Verbatim} + +Infine per impostare le \textit{capabilities} del processo corrente (non +esiste una funzione che permetta di cambiare le \textit{capabilities} di un +altro processo) si deve usare la funzione \funcd{cap\_set\_proc}, il cui +prototipo è: \begin{functions} - \headdecl{sys/types.h} - \headdecl{sys/acl.h} + \headdecl{sys/capability.h} + + \funcdecl{int cap\_set\_proc(cap\_t cap\_p)} + Imposta le \textit{capabilities} del processo corrente. - \funcdecl{int acl\_set\_fd(int fd, acl\_t acl)} + \bodydesc{La funzione ritorna 0 in caso di successo e $-1$ in caso di + errore, nel qual caso \var{errno} può assumere i valori \errval{EINVAL}, + \errval{EPERM} o \errval{ENOMEM}. + } +\end{functions} - Imposta una ACL su un file descriptor. +La funzione modifica le \textit{capabilities} del processo corrente secondo +quanto specificato con l'argomento \param{cap\_p}, posto che questo sia +possibile nei termini spiegati in precedenza (non sarà ad esempio possibile +impostare capacità non presenti nell'insieme di quelle permesse). In caso di +successo i nuovi valori saranno effettivi al ritorno della funzione, in caso +di fallimento invece lo stato delle capacità resterà invariato. Si tenga +presente che \textsl{tutte} le capacità specificate tramite \param{cap\_p} +devono essere permesse; se anche una sola non lo è la funzione fallirà, e per +quanto appena detto, lo stato delle \textit{capabilities} non verrà modificato +(neanche per le parti eventualmente permesse). - \bodydesc{La funzione restituisce $0$ in caso di successo e $-1$ in caso di - errore, nel qual caso \var{errno} assumerà uno dei valori: - \begin{errlist} - \item[\errcode{EBADF}]. - \item[\errcode{EINVAL}] o \param{acl} non è una ACL valida, o \param{type} - ha in valore non corretto. - \item[\errcode{ENOSPC}] non c'è spazio disco sufficiente per contenere i - dati aggiuntivi della ACL. - \item[\errcode{ENOTSUP}] si è cercato di impostare una ACL su un file - contenuto in un filesystem che non supporta le ACL. - \end{errlist} - ed inoltre \errval{EBADF}, \errval{EROFS}, \errval{EPERM}. -} -\end{functions} +Come esempio di utilizzo di queste funzioni nei sorgenti allegati alla guida +si è distribuito il programma \texttt{getcap.c}, che consente di leggere le +\textit{capabilities} del processo corrente\footnote{vale a dire di sé stesso, + quando lo si lancia, il che può sembrare inutile, ma serve a mostrarci quali + sono le \textit{capabilities} standard che ottiene un processo lanciato + dalla riga di comando.} o tramite l'opzione \texttt{-p}, quelle di un +processo qualunque il cui pid viene passato come parametro dell'opzione. -La funzione è del tutto è analoga a \funcd{acl\_set\_file} ma opera -esclusivamente sui file identificati tramite un file descriptor. Non dovendo -avere a che fare con directory (e con la conseguente possibilità di avere una -ACL di default) la funzione non necessita che si specifichi il tipo di ACL, -che sarà sempre di accesso, e prende come unico argomento, a parte il file -descriptor, la ACL da impostare. +\begin{figure}[!htbp] + \footnotesize \centering + \begin{minipage}[c]{\codesamplewidth} + \includecodesample{listati/getcap.c} + \end{minipage} + \normalsize + \caption{Corpo principale del programma \texttt{getcap.c}.} + \label{fig:proc_getcap} +\end{figure} -Le funzioni viste finora operano a livello di una intera ACL, eseguendo in una -sola volta tutte le operazioni relative a tutte le voci in essa contenuta. In -generale è possibile modificare un singolo valore all'interno di una singola -voce direttamente con le funzioni previste dallo standard POSIX.1e. Queste -funzioni però sono alquanto macchinose da utilizzare per cui è molto più -semplice operare direttamente sulla rappresentazione testuale. Questo è il -motivo per non tratteremo nei dettagli dette funzioni, fornendone solo una -descrizione sommaria; chi fosse interessato potrà ricorrere alle pagina di -manuale. +La sezione principale del programma è riportata in fig.~\ref{fig:proc_getcap}, +e si basa su una condizione sulla variabile \var{pid} che se si è usato +l'opzione \texttt{-p} è impostata (nella sezione di gestione delle opzioni, +che si è tralasciata) al valore del \textsl{pid} del processo di cui si vuole +leggere le \textit{capabilities} e nulla altrimenti. Nel primo caso +(\texttt{\small 1--6}) si utilizza direttamente (\texttt{\small 2}) +\func{cap\_get\_proc} per ottenere lo stato delle capacità del processo, nel +secondo (\texttt{\small 7--14}) prima si inizializza (\texttt{\small 8}) uno +stato vuoto e poi (\texttt{\small 9}) si legge il valore delle capacità del +processo indicato. -Se si vuole operare direttamente sui contenuti di un oggetto di tipo -\type{acl\_t} infatti occorre fare riferimento alle singole voci tramite gli -opportuni puntatori di tipo \type{acl\_entry\_t}, che possono essere ottenuti -dalla funzione \funcd{acl\_get\_entry} (per una voce esistente) o dalla -funzione \funcd{acl\_create\_entry} per una voce da aggiungere. Nel caso della -prima funzione si potrà poi ripetere la lettura per ottenere i puntatori alle -singole voci successive alla prima. +Il passo successivo è utilizzare (\texttt{\small 16}) \func{cap\_to\_text} per +tradurre in una stringa lo stato, e poi (\texttt{\small 17}) stamparlo; infine +(\texttt{\small 19--20}) si libera la memoria allocata dalle precedenti +funzioni con \func{cap\_free} per poi ritornare dal ciclo principale della +funzione. -Una volta ottenuti detti puntatori si potrà operare sui contenuti delle singole -voci; con le funzioni \funcd{acl\_get\_tag\_type}, \funcd{acl\_get\_qualifier}, -\funcd{acl\_get\_permset} si potranno leggere rispettivamente tipo, -qualificatore e permessi mentre con le corrispondente funzioni -\funcd{acl\_set\_tag\_type}, \funcd{acl\_set\_qualifier}, -\funcd{acl\_set\_permset} si possono impostare i valori; in entrambi i casi -vengono utilizzati tipi di dato ad hoc.\footnote{descritti nelle singole - pagine di manuale.} Si possono poi copiare i valori di una voce da una ACL -ad un altra con \funcd{acl\_copy\_entry} o eliminare una voce da una ACL con -\funcd{acl\_delete\_entry}. +\itindend{capabilities} -\itindend{Access~Control~List} +% TODO vedi http://lwn.net/Articles/198557/ e +% http://www.madore.org/~david/linux/newcaps/ @@ -4887,7 +5793,10 @@ ad un altra con \funcd{acl\_copy\_entry} o eliminare una voce da una ACL con \label{sec:file_chroot} % TODO introdurre nuova sezione sulle funzionalità di sicurezza avanzate, con -% dentro chroot SELinux e AppArmor ??? +% dentro chroot SELinux e AppArmor, Tomoyo, Smack, cgroup o che altro ??? + +% inserire setns (introdotta con il 3.0, vedi http://lwn.net/Articles/407495/) +% e le funzionalità di isolamento dei container Benché non abbia niente a che fare con permessi, utenti e gruppi, la funzione \func{chroot} viene usata spesso per restringere le capacità di accesso di un @@ -4983,15 +5892,15 @@ programmi e librerie) di cui il server potrebbe avere bisogno. % LocalWords: int const char oldpath newpath errno EXDEV EPERM st Smack SysV % LocalWords: EEXIST EMLINK EACCES ENAMETOOLONG ENOTDIR EFAULT ENOMEM EROFS ls % LocalWords: ELOOP ENOSPC EIO pathname nlink stat vfat fsck EISDIR ENOENT cap -% LocalWords: POSIX socket fifo sticky root system call count crash nell' init +% LocalWords: POSIX socket fifo sticky root system call count crash init linux % LocalWords: descriptor remove rename rmdir stdio glibc libc NFS DT obj dup % LocalWords: ENOTEMPTY EBUSY mount point EINVAL soft symbolic tab symlink fig % LocalWords: dangling access chdir chmod chown creat exec lchown lstat mkdir % LocalWords: mkfifo mknod opendir pathconf readlink truncate path buff size -% LocalWords: grub bootloader grep linux MAXSYMLINKS cat VFS sys dirname fcntl +% LocalWords: grub bootloader grep MAXSYMLINKS cat VFS sys dirname fcntl tv Py % LocalWords: dev umask IFREG IFBLK IFCHR IFIFO SVr sgid BSD SVID NULL from to % LocalWords: stream dirent EMFILE ENFILE dirfd SOURCE fchdir readdir struct -% LocalWords: EBADF namlen HAVE thread entry result value argument fileno ino +% LocalWords: EBADF namlen HAVE thread entry result value argument fileno ext % LocalWords: name TYPE OFF RECLEN UNKNOWN REG SOCK CHR BLK type IFTODT DTTOIF % LocalWords: DTYPE off reclen seekdir telldir void rewinddir closedir select % LocalWords: namelist compar malloc qsort alphasort versionsort strcoll myls @@ -5001,35 +5910,45 @@ programmi e librerie) di cui il server potrebbe avere bisogno. % LocalWords: EINTR mktemp mkstemp stlib template filename XXXXXX OpenBSD buf % LocalWords: mkdtemp fstat filedes nell'header padding ISREG ISDIR ISCHR IFMT % LocalWords: ISBLK ISFIFO ISLNK ISSOCK IFSOCK IFLNK IFDIR ISUID UID ISGID GID -% LocalWords: ISVTX IRUSR IWUSR IXUSR IRGRP IWGRP IXGRP IROTH IWOTH IXOTH du -% LocalWords: blocks blksize holes lseek TRUNC ftruncate length lenght ETXTBSY +% LocalWords: ISVTX IRUSR IWUSR IXUSR IRGRP IWGRP IXGRP IROTH IWOTH IXOTH OLD +% LocalWords: blocks blksize holes lseek TRUNC ftruncate ETXTBSY length QCMD % LocalWords: hole atime read utime mtime write ctime modification leafnode cp % LocalWords: make fchmod fchown utimbuf times actime modtime Mac owner uid fs % LocalWords: gid Control List patch mandatory control execute group other all -% LocalWords: dell' effective passwd IGID locking swap saved text IRWXU IRWXG -% LocalWords: IRWXO ext reiser capability FSETID mask capabilities chroot jail -% LocalWords: FTP Di filter reiserfs Attributes Solaris FreeBSD libacl hash +% LocalWords: effective passwd IGID locking swap saved text IRWXU IRWXG subcmd +% LocalWords: IRWXO capability FSETID mask capabilities chroot jail QUOTAOFF +% LocalWords: FTP filter Attributes Solaris FreeBSD libacl hash at dqblk SYNC % LocalWords: XFS SELinux namespace attribute security trusted Draft Modules % LocalWords: attributes mime ADMIN FOWNER libattr lattr getxattr lgetxattr of % LocalWords: fgetxattr attr ssize ENOATTR ENOTSUP NUL setxattr lsetxattr list % LocalWords: fsetxattr flags XATTR REPLACE listxattr llistxattr flistxattr by -% LocalWords: removexattr lremovexattr fremovexattr attributename lacl acl tv +% LocalWords: removexattr lremovexattr fremovexattr attributename acl GETINFO % LocalWords: OBJ setfacl len any prefix separator options NUMERIC IDS SMART -% LocalWords: INDENT major number IDE Documentation makedev proc copy +% LocalWords: INDENT major number IDE Documentation makedev proc copy LNK long % LocalWords: euidaccess eaccess delete def tag qualifier permset calendar NOW % LocalWords: mutt noatime relatime strictatime atim nsec mtim ctim atimensec -% LocalWords: mtimensec utimes timeval futimes lutimes ENOSYS futimens OMIT +% LocalWords: mtimensec utimes timeval futimes lutimes ENOSYS futimens OMIT PR % LocalWords: utimensat timespec sec futimesat LIDS DAC OVERRIDE SEARCH chattr % LocalWords: Discrectionary KILL SETGID domain SETUID setuid setreuid SETPCAP % LocalWords: setresuid setfsuid IMMUTABLE immutable append only BIND SERVICE % LocalWords: BROADCAST broadcast multicast multicasting RAW PACKET IPC LOCK % LocalWords: memory mlock mlockall shmctl mmap MODULE RAWIO ioperm iopl PACCT -% LocalWords: PTRACE ptrace accounting NICE RESOURCE TTY CONFIG hangup vhangup -% LocalWords: LEASE lease SETFCAP AUDIT permitted inherited inheritable AND +% LocalWords: ptrace accounting NICE RESOURCE TTY CONFIG hangup vhangup dell' +% LocalWords: LEASE lease SETFCAP AUDIT permitted inherited inheritable AND nn % LocalWords: bounding execve fork capget capset header hdrp datap ESRCH undef -% LocalWords: version libcap lcap clear ncap caps pag capgetp CapInh CapPrm -% LocalWords: fffffeff CapEff getcap dell'IPC scheduling dell'I lookup dcookie +% LocalWords: version libcap lcap clear ncap caps pag capgetp CapInh CapPrm RT +% LocalWords: fffffeff CapEff getcap scheduling lookup dqinfo SETINFO GETFMT % LocalWords: NEWNS unshare nice NUMA ioctl journaling close XOPEN fdopendir +% LocalWords: btrfs mkostemp extN ReiserFS JFS Posix usrquota grpquota EDQUOT +% LocalWords: aquota quotacheck limit grace period quotactl cmd caddr addr dqb +% LocalWords: QUOTAON ENODEV ENOPKG ENOTBLK GETQUOTA SETQUOTA SETUSE SETQLIM +% LocalWords: forced allowed sendmail SYSLOG WAKE ALARM CLOCK BOOTTIME dqstats +% LocalWords: REALTIME securebits GETSTATS QFMT curspace curinodes btime itime +% LocalWords: QIF BLIMITS bhardlimit bsoftlimit ILIMITS ihardlimit isoftlimit +% LocalWords: INODES LIMITS USAGE valid dqi IIF BGRACE bgrace IGRACE igrace +% LocalWords: Python Truelite Srl quotamodule Repository who nell' dall' KEEP +% LocalWords: SECURE KEEPCAPS prctl FIXUP NOROOT LOCKED dell'IPC dell'I IOPRIO +% LocalWords: CAPBSET CLASS IDLE dcookie overflow DIFFERS %%% Local Variables: %%% mode: latex