X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=blobdiff_plain;f=filedir.tex;h=ce6f6c026af79c4dc806b80c9533c4a4f75ec23c;hb=dcf2c2df897955ff3503a7c426025457ab456fd7;hp=3b13ce8cbf633e3191f5cfcf25e7ee2e72c68f6a;hpb=07e599dae430cb6c75fbdabd696be088ddeb3498;p=gapil.git diff --git a/filedir.tex b/filedir.tex index 3b13ce8..757bc13 100644 --- a/filedir.tex +++ b/filedir.tex @@ -1,91 +1,3535 @@ -\chapter{File e directory} +%% filedir.tex +%% +%% Copyright (C) 2000-2012 Simone Piccardi. Permission is granted to +%% copy, distribute and/or modify this document under the terms of the GNU Free +%% Documentation License, Version 1.1 or any later version published by the +%% Free Software Foundation; with the Invariant Sections being "Un preambolo", +%% with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the +%% license is included in the section entitled "GNU Free Documentation +%% License". +%% + +\chapter{La gestione di file e directory} \label{cha:files_and_dirs} -In questo capitolo tratteremo in dettaglio le modalità con cui si gestiscono -file e directory, ed in particolare esamineremo come è strutturato il sistema -base di protezioni e controllo di accesso ai file, e tutta l'interfaccia che -permette la manipolazione dei vari attributi di file e directory. Tutto quello -che riguarda invece la manipolazione del contenuto dei file è lasciato ai -capitoli successivi. +In questo capitolo tratteremo in dettaglio le modalità con cui si gestiscono +file e directory, iniziando da un approfondimento dell'architettura del +sistema illustrata a grandi linee in sez.~\ref{sec:file_arch_overview} ed +illustrando le principali caratteristiche di un filesystem e le interfacce +che consentono di controllarne il montaggio e lo smontaggio. + +Esamineremo poi le funzioni di libreria che si usano per copiare, spostare e +cambiare i nomi di file e directory e l'interfaccia che permette la +manipolazione dei loro attributi. Tratteremo inoltre 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 gestione dell'I/O +sui file è lasciato al capitolo successivo. + + + +\section{L'architettura della gestione dei file} +\label{sec:file_arch_func} + +In questa sezione tratteremo con maggiori dettagli rispetto a quanto visto in +sez.~\ref{sec:file_arch_overview} il \textit{Virtual File System} di Linux e +come il kernel può gestire diversi tipi di filesystem, descrivendo prima le +caratteristiche generali di un filesystem di un sistema unix-like, per poi +fare una panoramica sul filesystem più usato con Linux, l'\acr{ext2} ed i suoi +successori. + + +\subsection{Il funzionamento del \textit{Virtual File System} di Linux} +\label{sec:file_vfs_work} + +% NOTE articolo interessante: +% http://www.ibm.com/developerworks/linux/library/l-virtual-filesystem-switch/index.html?ca=dgr-lnxw97Linux-VFSdth-LXdW&S_TACT=105AGX59&S_CMP=GRlnxw97 + +\itindbeg{Virtual~File~System} + +Come illustrato brevemente in sez.~\ref{sec:file_arch_overview} in Linux il +concetto di \textit{everything is a file} è stato implementato attraverso il +\textit{Virtual File System}, la cui struttura generale è illustrata in +fig.~\ref{fig:file_VFS_scheme}. Il VFS definisce un insieme di funzioni che +tutti i filesystem devono implementare per l'accesso ai file che contengono e +l'interfaccia che consente di eseguire l'I/O sui file, che questi siano di +dati o dispositivi. + +\itindbeg{inode} + +L'interfaccia fornita dal VFS comprende in sostanza tutte le funzioni che +riguardano i file, le operazioni implementate dal VFS sono realizzate con una +astrazione che prevede quattro tipi di oggetti strettamente correlati: i +filesystem, le \textit{dentry}, gli \textit{inode} ed i file. A questi oggetti +corrispondono una serie di apposite strutture definite dal kernel che +contengono come campi le funzioni di gestione e realizzano l'infrastruttura +del VFS. L'interfaccia è molto complessa, ne faremo pertanto una trattazione +estremamente semplificata che consenta di comprenderne i principi +di funzionamento. + +Il VFS usa una tabella mantenuta dal kernel che contiene il nome di ciascun +filesystem supportato, quando si vuole inserire il supporto di un nuovo +filesystem tutto quello che occorre è chiamare la funzione +\code{register\_filesystem} passando come argomento la struttura +\kstruct{file\_system\_type} (la cui definizione è riportata in +fig.~\ref{fig:kstruct_file_system_type}) relativa a quel filesystem. Questa +verrà inserita nella tabella, ed il nuovo filesystem comparirà in +\procfile{/proc/filesystems}. +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{\textwidth} + \includestruct{listati/file_system_type.h} + \end{minipage} + \normalsize + \caption{Estratto della struttura \kstructd{file\_system\_type} usata dal + VFS (da \texttt{include/linux/fs.h}).} + \label{fig:kstruct_file_system_type} +\end{figure} + +La struttura \kstruct{file\_system\_type}, oltre ad una serie di dati interni, +come il nome del tipo di filesystem nel campo \var{name},\footnote{quello che + viene riportato in \procfile{/proc/filesystems} e che viene usato come + valore del parametro dell'opzione \texttt{-t} del comando \texttt{mount} che + indica il tipo di filesystem.} contiene i riferimenti alle funzioni di base +che consentono l'utilizzo di quel filesystem. In particolare la funzione +\code{mount} del quarto campo è quella che verrà invocata tutte le volte che +si dovrà effettuare il montaggio di un filesystem di quel tipo. Per ogni nuovo +filesystem si dovrà allocare una di queste strutture ed inizializzare i +relativi campi con i dati specifici di quel filesystem, ed in particolare si +dovrà creare anche la relativa versione della funzione \code{mount}. + +\itindbeg{pathname} +\itindbeg{pathname~resolution} + +Come illustrato in fig.~\ref{fig:kstruct_file_system_type} questa funzione +restituisce una \textit{dentry}, abbreviazione che sta per \textit{directory + entry}. Le \textit{dentry} sono gli oggetti che il kernel usa per eseguire +la \textit{pathname resolution}, ciascuna di esse corrisponde ad un +\textit{pathname} e contiene il riferimento ad un \textit{inode}, che come +vedremo a breve è l'oggetto usato dal kernel per identificare un un +file.\footnote{in questo caso si parla di file come di un qualunque oggetto + generico che sta sul filesystem e non dell'oggetto file del VFS cui + accennavamo prima.} La \textit{dentry} ottenuta dalla chiamata alla funzione +\code{mount} sarà inserita in corrispondenza al \textit{pathname} della +directory in cui il filesystem è stato montato. + +% NOTA: struct dentry è dichiarata in include/linux/dcache.h + +Le \textit{dentry} sono oggetti del VFS che vivono esclusivamente in memoria, +nella cosiddetta \textit{directory entry cache} (spesso chiamata in breve +\textit{dcache}). Ogni volta che una \textit{system call} specifica un +\textit{pathname} viene effettuata una ricerca nella \textit{dcache} per +ottenere immediatamente la \textit{dentry} corrispondente,\footnote{il buon + funzionamento della \textit{dcache} è in effetti di una delle parti più + critiche per le prestazioni del sistema.} che a sua volta ci darà, tramite +l'\textit{inode}, il riferimento al file. + +Dato che normalmente non è possibile mantenere nella \textit{dcache} le +informazioni relative a tutto l'albero dei file la procedura della +\textit{pathname resolution} richiede un meccanismo con cui riempire gli +eventuali vuoti. Il meccanismo prevede che tutte le volte che si arriva ad una +\textit{dentry} mancante venga invocata la funzione \texttt{lookup} +dell'\textit{inode} associato alla \textit{dentry} precedente nella +risoluzione del \textit{pathname},\footnote{che a questo punto è una + directory, per cui si può cercare al suo interno il nome di un file.} il cui +scopo è risolvere il nome mancante e fornire la sua \textit{dentry} che a +questo punto verrà inserita nella cache. + +Dato che tutte le volte che si monta un filesystem la funzione \texttt{mount} +della corrispondente \kstruct{file\_system\_type} inserisce la \textit{dentry} +iniziale nel \itindex{mount~point} \textit{mount point} dello stesso si avrà +comunque un punto di partenza. Inoltre essendo questa \textit{dentry} relativa +a quel tipo di filesystem essa farà riferimento ad un \textit{inode} di quel +filesystem, e come vedremo questo farà sì che venga eseguita una +\texttt{lookup} adatta per effettuare la risoluzione dei nomi per quel +filesystem. + +\itindend{pathname} +\itindend{pathname~resolution} + +% Un secondo effetto della chiamata funzione \texttt{mount} di +% \kstruct{file\_system\_type} è quello di allocare una struttura +% \kstruct{super\_block} per ciascuna istanza montata, che contiene le +% informazioni generali di un qualunque filesystem montato, come le opzioni di +% montaggio, le dimensioni dei blocchi, quando il filesystem è stato montato +% ecc. Fra queste però viene pure inserta, nel campo \var{s\_op}, una ulteriore +% struttura \kstruct{super\_operations}, il cui contenuto sono i puntatori +% alle funzioni di gestione di un filesystem, anche inizializzata in modo da +% utilizzare le versioni specifiche di quel filesystem. + +L'oggetto più importante per il funzionamento del VFS è probabilmente +l'\textit{inode}, ma con questo nome si può fare riferimento a due cose +diverse. La prima è la struttura su disco (su cui torneremo anche in +sez.~\ref{sec:file_filesystem}) che fa parte della organizzazione dei dati +realizzata dal filesystem e che contiene le informazioni relative alle +proprietà (i cosiddetti \textsl{metadati}) di ogni oggetto presente su di esso +(si intende al solito uno qualunque dei tipi di file di +tab.~\ref{tab:file_file_types}). + +La seconda è la corrispondente struttura \kstruct{inode}, della cui +definizione si è riportato un estratto in +fig.~\ref{fig:kstruct_inode}.\footnote{l'estratto fa riferimento alla versione + del kernel 2.6.37.} Questa struttura viene mantenuta in memoria ed è a +questa che facevamo riferimento quando parlavamo dell'\textit{inode} associato +a ciascuna \textit{dentry}. Nella struttura in memoria sono presenti gli +stessi \textsl{metadati} memorizzati su disco, che vengono letti quando questa +struttura viene allocata e trascritti all'indietro se modificati. + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{\textwidth} + \includestruct{listati/inode.h} + \end{minipage} + \normalsize + \caption{Estratto della struttura \kstructd{inode} del kernel (da + \texttt{include/linux/fs.h}).} + \label{fig:kstruct_inode} +\end{figure} + +Il fatto che la struttura \kstruct{inode} sia mantenuta in memoria, +direttamente associata ad una \textit{dentry}, rende sostanzialmente immediate +le operazioni che devono semplicemente effettuare un accesso ai dati in essa +contenuti: è così ad esempio che viene realizzata la \textit{system call} +\func{stat} che vedremo in sez.~\ref{sec:file_stat}. Rispetto ai dati salvati +sul disco questa struttura contiene però anche quanto necessario alla +implementazione del VFS, ed in particolare è importante il campo \var{i\_op} +che, come illustrato in fig.~\ref{fig:kstruct_inode}, contiene il puntatore ad +una struttura di tipo \kstruct{inode\_operation}, la cui definizione si può +trovare nel file \texttt{include/kernel/fs.h} dei sorgenti del kernel. + +Questa struttura non è altro che una tabella di funzioni, ogni suo membro cioè +è un puntatore ad una funzione e, come suggerisce il nome della struttura +stessa, queste funzioni sono quelle che definiscono le operazioni che il VFS +può compiere su un \textit{inode}. Si sono riportate in +tab.~\ref{tab:file_inode_operations} le più rilevanti. + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|l|} + \hline + \textbf{Funzione} & \textbf{Operazione} \\ + \hline + \hline + \textsl{\code{create}} & Chiamata per creare un nuovo file (vedi + sez.~\ref{sec:file_open}).\\ + \textsl{\code{link}} & Crea un \textit{hard link} (vedi + sez.~\ref{sec:file_link}).\\ + \textsl{\code{unlink}} & Cancella un \textit{hard link} (vedi + sez.~\ref{sec:file_link}).\\ + \textsl{\code{symlink}}& Crea un link simbolico (vedi + sez.~\ref{sec:file_symlink}).\\ + \textsl{\code{mkdir}} & Crea una directory (vedi + sez.~\ref{sec:file_dir_creat_rem}).\\ + \textsl{\code{rmdir}} & Rimuove una directory (vedi + sez.~\ref{sec:file_dir_creat_rem}).\\ + \textsl{\code{mknod}} & Crea un file speciale (vedi + sez.~\ref{sec:file_mknod}).\\ + \textsl{\code{rename}} & Cambia il nome di un file (vedi + sez.~\ref{sec:file_remove}).\\ + \textsl{\code{lookup}}& Risolve il nome di un file.\\ + \hline + \end{tabular} + \caption{Le principali operazioni sugli \textit{inode} definite tramite + \kstruct{inode\_operation}.} + \label{tab:file_inode_operations} +\end{table} + +Possiamo notare come molte di queste funzioni abbiano nomi sostanzialmente +identici alle varie \textit{system call} con le quali si gestiscono file e +directory, che tratteremo nel resto del capitolo. Quello che succede è che +tutte le volte che deve essere eseguita una \textit{system call}, o una +qualunque altra operazione su un \textit{inode} (come \texttt{lookup}) il VFS +andrà ad utilizzare la funzione corrispondente attraverso il puntatore +\var{i\_op}. + +Sarà allora sufficiente che nella realizzazione di un filesystem si crei una +implementazione di queste funzioni per quel filesystem e si allochi una +opportuna istanza di \kstruct{inode\_operation} contenente i puntatori a dette +funzioni. A quel punto le strutture \kstruct{inode} usate per gli oggetti di +quel filesystem otterranno il puntatore alla relativa istanza di +\kstruct{inode\_operation} e verranno automaticamente usate le funzioni +corrette. + +Si noti però come in tab.~\ref{tab:file_inode_operations} non sia presente la +funzione \texttt{open} che invece è citata in +tab.~\ref{tab:file_file_operations}.\footnote{essa può essere comunque + invocata dato che nella struttura \kstruct{inode} è presente anche il + puntatore \var{i\_fop} alla struttura \kstruct{file\_operation} che fornisce + detta funzione.} Questo avviene perché su Linux l'apertura di un file +richiede comunque un'altra operazione che mette in gioco l'omonimo oggetto del +VFS: l'allocazione di una struttura di tipo \kstruct{file} che viene associata +ad ogni file aperto nel sistema. + +I motivi per cui viene usata una struttura a parte sono diversi, anzitutto, +come illustrato in sez.~\ref{sec:file_fd}, questa è necessaria per le +operazioni eseguite dai processi con l'interfaccia dei file descriptor; ogni +processo infatti mantiene il riferimento ad una struttura \kstruct{file} per +ogni file che ha aperto, ed è tramite essa che esegue le operazioni di I/O. + +Inoltre se le operazioni relative agli \textit{inode} fanno riferimento ad +oggetti posti all'interno di un filesystem e vi si applicano quindi le +funzioni fornite nell'implementazione di quest'ultimo, quando si apre un file +questo può essere anche un file di dispositivo, ed in questo caso il VFS +invece di usare le operazioni fornite dal filesystem (come farebbe per un file +di dati) dovrà invece ricorrere a quelle fornite dal driver del dispositivo. + +\itindend{inode} + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{\textwidth} + \includestruct{listati/file.h} + \end{minipage} + \normalsize + \caption{Estratto della struttura \kstructd{file} del kernel (da + \texttt{include/linux/fs.h}).} + \label{fig:kstruct_file} +\end{figure} + +Come si può notare dall'estratto di fig.~\ref{fig:kstruct_file}, la struttura +\kstruct{file} contiene, oltre ad alcune informazioni usate dall'interfaccia +dei file descriptor il cui significato emergerà più avanti, il puntatore +\var{f\_op} ad una struttura \kstruct{file\_operation}. Questa è l'analoga per +i file di \kstruct{inode\_operation}, e definisce le operazioni generiche +fornite dal VFS per i file. Si sono riportate in +tab.~\ref{tab:file_file_operations} le più significative. + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|p{8cm}|} + \hline + \textbf{Funzione} & \textbf{Operazione} \\ + \hline + \hline + \textsl{\code{open}} & Apre il file (vedi sez.~\ref{sec:file_open}).\\ + \textsl{\code{read}} & Legge dal file (vedi sez.~\ref{sec:file_read}).\\ + \textsl{\code{write}} & Scrive sul file (vedi + sez.~\ref{sec:file_write}).\\ + \textsl{\code{llseek}} & Sposta la posizione corrente sul file (vedi + sez.~\ref{sec:file_lseek}).\\ + \textsl{\code{ioctl}} & Accede alle operazioni di controllo + (vedi sez.~\ref{sec:file_ioctl}).\\ + \textsl{\code{readdir}}& Legge il contenuto di una directory (vedi + sez.~\ref{sec:file_dir_read}).\\ + \textsl{\code{poll}} & Usata nell'I/O multiplexing (vedi + sez.~\ref{sec:file_multiplexing}).\\ + \textsl{\code{mmap}} & Mappa il file in memoria (vedi + sez.~\ref{sec:file_memory_map}).\\ + \textsl{\code{release}}& Chiamata quando l'ultimo riferimento a un file + aperto è chiuso.\\ + \textsl{\code{fsync}} & Sincronizza il contenuto del file (vedi + sez.~\ref{sec:file_sync}).\\ + \textsl{\code{fasync}} & Abilita l'I/O asincrono (vedi + sez.~\ref{sec:file_asyncronous_io}) sul file.\\ + \hline + \end{tabular} + \caption{Operazioni sui file definite tramite \kstruct{file\_operation}.} + \label{tab:file_file_operations} +\end{table} + +Anche in questo caso tutte le volte che deve essere eseguita una +\textit{system call} o una qualunque altra operazione sul file il VFS andrà ad +utilizzare la funzione corrispondente attraverso il puntatore +\var{f\_op}. Dato che è cura del VFS quando crea la struttura all'apertura del +file assegnare a \var{f\_op} il puntatore alla versione di +\kstruct{file\_operation} corretta per quel file, sarà possibile scrivere allo +stesso modo sulla porta seriale come su un normale file di dati, e lavorare +sui file allo stesso modo indipendentemente dal filesystem. + +Il VFS realizza la quasi totalità delle operazioni relative ai file grazie +alle funzioni presenti nelle due strutture \kstruct{inode\_operation} e +\kstruct{file\_operation}. Ovviamente non è detto che tutte le operazioni +possibili siano poi disponibili in tutti i casi, ad esempio \code{llseek} non +sarà presente per un dispositivo come la porta seriale o per una fifo, mentre +sui file del filesystem \texttt{vfat} non saranno disponibili i permessi, ma +resta il fatto che grazie al VFS le \textit{system call} per le operazioni sui +file possono restare sempre le stesse nonostante le enormi differenze che +possono esserci negli oggetti a cui si applicano. + + +\itindend{Virtual~File~System} + +% NOTE: documentazione interessante: +% * sorgenti del kernel: Documentation/filesystems/vfs.txt +% * http://thecoffeedesk.com/geocities/rkfs.html +% * http://www.linux.it/~rubini/docs/vfs/vfs.html + + + +\subsection{Il funzionamento di un filesystem Unix} +\label{sec:file_filesystem} + +Come già accennato in sez.~\ref{sec:file_arch_overview} Linux (ed ogni sistema +unix-like) organizza i dati che tiene su disco attraverso l'uso di un +filesystem. Una delle caratteristiche di Linux rispetto agli altri Unix è +quella di poter supportare, grazie al VFS, una enorme quantità di filesystem +diversi, ognuno dei quali avrà una sua particolare struttura e funzionalità +proprie. Per questo non entreremo nei dettagli di un filesystem specifico, ma +daremo una descrizione a grandi linee che si adatta alle caratteristiche +comuni di qualunque filesystem di un sistema unix-like. + +Una possibile strutturazione dell'informazione su un disco è riportata in +fig.~\ref{fig:file_disk_filesys}, dove si hanno tre filesystem su tre +partizioni. In essa per semplicità si è fatto riferimento alla struttura del +filesystem \acr{ext2}, che prevede una suddivisione dei dati in \textit{block + group}. All'interno di ciascun \textit{block group} viene anzitutto +replicato il cosiddetto \itindex{superblock} \textit{superblock}, (la +struttura che contiene l'indice iniziale del filesystem e che consente di +accedere a tutti i dati sottostanti) e creata una opportuna suddivisione dei +dati e delle informazioni per accedere agli stessi. Sulle caratteristiche di +\acr{ext2} e derivati torneremo in sez.~\ref{sec:file_ext2}. + +\itindbeg{inode} + +È comunque caratteristica comune di tutti i filesystem per Unix, +indipendentemente da come poi viene strutturata nei dettagli questa +informazione, prevedere la presenza di due tipi di risorse: gli +\textit{inode}, cui abbiamo già accennato in sez.~\ref{sec:file_vfs_work}, che +sono le strutture che identificano i singoli oggetti sul filesystem, e i +blocchi, che invece attengono allo spazio disco che viene messo a disposizione +per i dati in essi contenuti. + +\begin{figure}[!htb] + \centering + \includegraphics[width=12cm]{img/disk_struct} + \caption{Organizzazione dello spazio su un disco in partizioni e + filesystem.} + \label{fig:file_disk_filesys} +\end{figure} + +Se si va ad esaminare con maggiore dettaglio la strutturazione +dell'informazione all'interno del filesystem \textsl{ext2}, tralasciando i +dettagli relativi al funzionamento del filesystem stesso come la +strutturazione in gruppi dei blocchi, il \itindex{superblock} +\textit{superblock} e tutti i dati di gestione possiamo esemplificare la +situazione con uno schema come quello esposto in +fig.~\ref{fig:file_filesys_detail}. + +\begin{figure}[!htb] + \centering + \includegraphics[width=12cm]{img/filesys_struct} + \caption{Strutturazione dei dati all'interno di un filesystem.} + \label{fig:file_filesys_detail} +\end{figure} + +Da fig.~\ref{fig:file_filesys_detail} si evidenziano alcune delle +caratteristiche di base di un filesystem, che restano le stesse anche su +filesystem la cui organizzazione dei dati è totalmente diversa da quella +illustrata, e sulle quali è bene porre attenzione visto che sono fondamentali +per capire il funzionamento delle funzioni che manipolano i file e le +directory che tratteremo nel prosieguo del capitolo. In particolare è +opportuno tenere sempre presente che: + + +\begin{enumerate} + +\item L'\textit{inode} contiene i cosiddetti \textsl{metadati}, vale dire le + informazioni riguardanti le proprietà del file come oggetto del filesystem: + il tipo di file, i permessi di accesso, le dimensioni, i puntatori ai + blocchi fisici che contengono i dati e così via. Le informazioni che la + funzione \func{stat} (vedi sez.~\ref{sec:file_stat}) fornisce provengono + dall'\textit{inode}. Dentro una directory si troverà solo il nome del file + e il numero dell'\textit{inode} ad esso associato; il nome non è una + proprietà del file e non viene mantenuto nell'\textit{inode}. Da da qui in + poi chiameremo il nome del file contenuto in una directory + ``\textsl{voce}'', come traduzione della nomenclatura inglese + \textit{directory entry} che non useremo per evitare confusione con le + \textit{dentry} del kernel viste in sez.~\ref{sec:file_vfs_work}. + +\item Come mostrato in fig.~\ref{fig:file_filesys_detail} per i file + \texttt{macro.tex} e \texttt{gapil\_macro.tex}, ci possono avere più voci + che fanno riferimento allo stesso \textit{inode}. Fra le proprietà di un + file mantenute nell'\textit{inode} c'è anche il contatore con il numero di + riferimenti che sono stati fatti ad esso, il cosiddetto \textit{link + count}.\footnote{mantenuto anche nel campo \var{i\_nlink} della struttura + \kstruct{inode} di fig.~\ref{fig:kstruct_inode}.} Solo quando questo + contatore si annulla i dati del file possono essere effettivamente rimossi + dal disco. Per questo la funzione per cancellare un file si chiama + \func{unlink} (vedi sez.~\ref{sec:file_link}), ed in realtà non cancella + affatto i dati del file, ma si limita ad eliminare la relativa voce da una + directory e decrementare il numero di riferimenti nell'\textit{inode}. + +\item All'interno di ogni filesystem ogni \textit{inode} è identificato da un + numero univoco. Il numero di \textit{inode} associato ad una voce in una + directory si riferisce ad questo numero e non ci può essere una directory + che contiene riferimenti ad \textit{inode} relativi ad altri filesystem. + Questa è la ragione che limita l'uso del comando \cmd{ln}, che crea una + nuova voce per un file esistente con la funzione \func{link} (vedi + sez.~\ref{sec:file_link}) a file nel filesystem corrente. + +\item Quando si cambia nome ad un file senza cambiare filesystem il contenuto + del file non viene spostato fisicamente, viene semplicemente creata una + nuova voce per l'\textit{inode} in questione e rimossa la precedente, questa + è la modalità in cui opera normalmente il comando \cmd{mv} attraverso la + funzione \func{rename} (vedi sez.~\ref{sec:file_remove}). Questa operazione + non modifica minimamente neanche l'\textit{inode} del file, dato che non si + opera sul file ma sulla directory che lo contiene. + +\item Gli \textit{inode} dei file, che contengono i \textsl{metadati}, ed i + blocchi di spazio disco, che contengono i dati, sono risorse indipendenti ed + in genere vengono gestite come tali anche dai diversi filesystem; è pertanto + possibile esaurire sia lo spazio disco (il caso più comune) che lo spazio + per gli \textit{inode}. Nel primo caso non sarà possibile allocare ulteriore + spazio, ma si potranno creare file (vuoti), nel secondo non si potranno + creare nuovi file, ma si potranno estendere quelli che ci + sono.\footnote{questo comportamento non è generale, alcuni filesystem + evoluti possono evitare il problema dell'esaurimento degli \textit{inode} + riallocando lo spazio disco libero per i blocchi.} + +\end{enumerate} + +\begin{figure}[!htb] + \centering + \includegraphics[width=12cm]{img/dir_links} + \caption{Organizzazione dei \textit{link} per le directory.} + \label{fig:file_dirs_link} +\end{figure} + +Infine tenga presente che, essendo file pure loro, il numero di riferimenti +esiste anche per le directory. Per questo se a partire dalla situazione +mostrata in fig.~\ref{fig:file_filesys_detail} creiamo una nuova directory +\file{img} nella directory \file{gapil}, avremo una situazione come quella +illustrata in fig.~\ref{fig:file_dirs_link}. + +La nuova directory avrà un numero di riferimenti pari a due, in quanto è +referenziata dalla directory da cui si era partiti (in cui è inserita la nuova +voce che fa riferimento a \texttt{img}) e dalla voce interna ``\texttt{.}'' +che è presente in ogni directory. Questo è il valore che si troverà sempre +per ogni directory che non contenga a sua volta altre directory. Al contempo, +la directory da cui si era partiti avrà un numero di riferimenti di almeno +tre, in quanto adesso sarà referenziata anche dalla voce ``\texttt{..}'' di +\texttt{img}. L'aggiunta di una sottodirectory fa cioè crescere di uno il +\textit{link count} della directory genitrice. + +\itindend{inode} + + +\subsection{Alcuni dettagli sul filesystem \textsl{ext2} e successori} +\label{sec:file_ext2} + + +Benché non esista ``il'' filesystem di Linux, dato che esiste un supporto +nativo di diversi filesystem che sono in uso da anni, quello che gli avvicina +di più è la famiglia di filesystem evolutasi a partire dal \textit{second + extended filesystem}, o \acr{ext2}. Il filesystem \acr{ext2} ha subito un +grande sviluppo e diverse evoluzioni, fra cui l'aggiunta del +\textit{journaling} con \acr{ext3}, probabilmente ancora il filesystem più +diffuso, ed una serie di ulteriori miglioramento con il successivo \acr{ext4}, +che sta iniziando a sostituirlo gradualmente. In futuro è previsto che questo +debba essere sostituito da un filesystem completamente diverso, \acr{btrfs}, +che dovrebbe diventare il filesystem standard di Linux, ma questo al momento è +ancora in fase di sviluppo.\footnote{si fa riferimento al momento dell'ultima + revisione di di questo paragrafo, l'inizio del 2012.} + +Il filesystem \acr{ext2} nasce come filesystem nativo per Linux a partire +dalle prime versioni del kernel e supporta tutte le caratteristiche di un +filesystem standard Unix: è in grado di gestire nomi di file lunghi (256 +caratteri, estensibili a 1012) e supporta una dimensione massima dei file fino +a 4~Tb. I successivi filesystem \acr{ext3} ed \acr{ext4} sono evoluzioni di +questo filesystem, e sia pure con molti miglioramenti ed estensioni +significative ne mantengono le caratteristiche fondamentali. + +Oltre alle caratteristiche standard, \acr{ext2} fornisce alcune estensioni che +non sono presenti su un classico filesystem di tipo Unix; le principali sono +le seguenti: +\begin{itemize} +\item i \textit{file attributes} consentono di modificare il comportamento del + kernel quando agisce su gruppi di file. Possono essere impostati su file e + directory e in quest'ultimo caso i nuovi file creati nella directory + ereditano i suoi attributi. +\item sono supportate entrambe le semantiche di BSD e SVr4 come opzioni di + montaggio. La semantica BSD comporta che i file in una directory sono creati + con lo stesso identificatore di gruppo della directory che li contiene. La + semantica SVr4 comporta che i file vengono creati con l'identificatore del + gruppo primario del processo, eccetto il caso in cui la directory ha il bit + di \acr{sgid} impostato (per una descrizione dettagliata del significato di + questi termini si veda sez.~\ref{sec:file_access_control}), nel qual caso + file e subdirectory ereditano sia il \ids{GID} che lo \acr{sgid}. +\item l'amministratore può scegliere la dimensione dei blocchi del filesystem + in fase di creazione, a seconda delle sue esigenze: blocchi più grandi + permettono un accesso più veloce, ma sprecano più spazio disco. +\item il filesystem implementa link simbolici veloci, in cui il nome del file + non è salvato su un blocco, ma tenuto all'interno \itindex{inode} + dell'\textit{inode} (evitando letture multiple e spreco di spazio), non + tutti i nomi però possono essere gestiti così per limiti di spazio (il + limite è 60 caratteri). +\item vengono supportati i file immutabili (che possono solo essere letti) per + la protezione di file di configurazione sensibili, o file + \textit{append-only} che possono essere aperti in scrittura solo per + aggiungere dati (caratteristica utilizzabile per la protezione dei file di + log). +\end{itemize} + +La struttura di \acr{ext2} è stata ispirata a quella del filesystem di BSD: un +filesystem è composto da un insieme di blocchi, la struttura generale è quella +riportata in fig.~\ref{fig:file_filesys_detail}, in cui la partizione è divisa +in gruppi di blocchi. + +Ciascun gruppo di blocchi contiene una copia delle informazioni essenziali del +filesystem (i \itindex{superblock} \textit{superblock} sono quindi ridondati) +per una maggiore affidabilità e possibilità di recupero in caso di corruzione +del \itindex{superblock} \textit{superblock} principale. L'utilizzo di +raggruppamenti di blocchi ha inoltre degli effetti positivi nelle prestazioni +dato che viene ridotta la distanza fra i dati e la tabella degli +\itindex{inode} inode. + +\begin{figure}[!htb] + \centering + \includegraphics[width=9cm]{img/dir_struct} + \caption{Struttura delle directory nel \textit{second extended filesystem}.} + \label{fig:file_ext2_dirs} +\end{figure} + +Le directory sono implementate come una \itindex{linked~list} \textit{linked + list} con voci di dimensione variabile. Ciascuna voce della lista contiene +il numero di inode \itindex{inode}, la sua lunghezza, il nome del file e la sua +lunghezza, secondo lo schema in fig.~\ref{fig:file_ext2_dirs}; in questo modo +è possibile implementare nomi per i file anche molto lunghi (fino a 1024 +caratteri) senza sprecare spazio disco. + +Con l'introduzione del filesystem \textit{ext3} sono state introdotte diverse +modifiche strutturali, la principale di queste è quella che \textit{ext3} è un +filesystem \textit{journaled}, è cioè in grado di eseguire una registrazione +delle operazioni di scrittura su un giornale (uno speciale file interno) in +modo da poter garantire il ripristino della coerenza dei dati del +filesystem\footnote{si noti bene che si è parlato di dati \textsl{del} + filesystem, non di dati \textsl{nel} filesystem, quello di cui viene + garantito un veloce ripristino è relativo ai dati della struttura interna + del filesystem, non di eventuali dati contenuti nei file che potrebbero + essere stati persi.} in brevissimo tempo in caso di interruzione improvvisa +della corrente o di crollo del sistema che abbia causato una interruzione +della scrittura dei dati sul disco. + +Oltre a questo \textit{ext3} introduce ulteriori modifiche volte a migliorare +sia le prestazioni che la semplicità di gestione del filesystem, in +particolare per le directory si è passato all'uso di alberi binari con +indicizzazione tramite hash al posto delle \textit{linked list} che abbiamo +illustrato, ottenendo un forte guadagno di prestazioni in caso di directory +contenenti un gran numero di file. + +% TODO (bassa priorità) portare a ext3, ext4 e btrfs ed illustrare le +% problematiche che si possono incontrare (in particolare quelle relative alla +% perdita di contenuti in caso di crash del sistema) +% TODO (media priorità) trattare btrfs quando sarà usato come stabile + + +\subsection{La gestione dell'uso dei filesystem} +\label{sec:sys_file_config} + +Come accennato in sez.~\ref{sec:file_arch_overview} per poter accedere ai file +occorre prima rendere disponibile al sistema il filesystem su cui essi sono +memorizzati; l'operazione di attivazione del filesystem è chiamata +\textsl{montaggio}, per far questo in Linux si usa la funzione \funcd{mount}, +il cui prototipo è:\footnote{la funzione è una versione specifica di Linux che + usa la omonima \textit{system call} e non è portabile.} + +\begin{funcproto}{ +\fhead{sys/mount.h} +\fdecl{mount(const char *source, const char *target, const char + *filesystemtype, \\ +\phantom{mount(}unsigned long mountflags, const void *data)} +\fdesc{Monta un filesystem.} +} + +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual + caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{EACCES}] non si ha il permesso di accesso su uno dei + componenti del \textit{pathname}, o si è cercato di montare un filesystem + disponibile in sola lettura senza aver specificato \const{MS\_RDONLY} o il + device \param{source} è su un filesystem montato con l'opzione + \const{MS\_NODEV}. + \item[\errcode{EBUSY}] \param{source} è già montato, o non può essere + rimontato in sola lettura perché ci sono ancora file aperti in scrittura, + o non può essere montato su \param{target} perché la directory è ancora in + uso. + \item[\errcode{EINVAL}] il dispositivo \param{source} presenta un + \itindex{superblock} \textit{superblock} non valido, o si è cercato di + rimontare un filesystem non ancora montato, o di montarlo senza + che \param{target} sia un \itindex{mount~point} \textit{mount point} o di + spostarlo quando \param{target} non è un \itindex{mount~point} + \textit{mount point} o è la radice. + \item[\errcode{ELOOP}] si è cercato di spostare un \itindex{mount~point} + \textit{mount point} su una sottodirectory di \param{source} o si sono + incontrati troppi link simbolici nella risoluzione di un nome. + \item[\errcode{EMFILE}] in caso di filesystem virtuale, la tabella dei + dispositivi fittizi (chiamati \textit{dummy} nella documentazione inglese) + è piena. + \item[\errcode{ENODEV}] il tipo \param{filesystemtype} non esiste o non è + configurato nel kernel. + \item[\errcode{ENOTBLK}] non si è usato un \textit{block device} per + \param{source} quando era richiesto. + \item[\errcode{ENXIO}] il \itindex{major~number} \textit{major number} del + dispositivo \param{source} è sbagliato. + \item[\errcode{EPERM}] il processo non ha i privilegi di amministratore. + \end{errlist} + ed inoltre \errval{EFAULT}, \errval{ENOMEM}, \errval{ENAMETOOLONG}, + \errval{ENOENT}, \errval{ENOTDIR} nel loro significato generico.} +\end{funcproto} + +La funzione monta sulla directory indicata da \param{target}, detta +\itindex{mount~point} \textit{mount point}, il filesystem contenuto nel file +di dispositivo indicato da \param{source}. In entrambi i casi, come daremo per +assunto da qui in avanti tutte le volte che si parla di directory o file nel +passaggio di un argomento di una funzione, si intende che questi devono essere +indicati con la stringa contenente il loro \textit{pathname}. + +Normalmente un filesystem è contenuto su un disco o una partizione, ma come +illustrato in sez.~\ref{sec:file_vfs_work} la struttura del +\itindex{Virtual~File~System} \textit{Virtual File System} è estremamente +flessibile e può essere usata anche per oggetti diversi da un disco. Ad +esempio usando il \textit{loop device} si può montare un file qualunque (come +l'immagine di un CD-ROM o di un floppy) che contiene l'immagine di un +filesystem, inoltre alcuni tipi di filesystem, come \texttt{proc} o +\texttt{sysfs} sono virtuali e non hanno un supporto che ne contenga i dati, +che invece sono generati al volo ad ogni lettura, e passati indietro al kernel +ad ogni scrittura.\footnote{costituiscono quindi un meccanismo di + comunicazione, attraverso l'ordinaria interfaccia dei file, con il kernel.} + +Il tipo di filesystem che si vuole montare è specificato +dall'argomento \param{filesystemtype}, che deve essere una delle stringhe +riportate nel file \procfile{/proc/filesystems} che, come accennato in +sez.~\ref{sec:file_vfs_work}, contiene l'elenco dei filesystem supportati dal +kernel. Nel caso si sia indicato un filesystem virtuale, che non è associato a +nessun file di dispositivo, il contenuto di \param{source} viene ignorato. + +L'argomento \param{data} viene usato per passare le impostazioni relative alle +caratteristiche specifiche di ciascun filesystem. Si tratta di una stringa di +parole chiave (separate da virgole e senza spazi) che indicano le cosiddette +``\textsl{opzioni}'' del filesystem che devono essere impostate; in genere +viene usato direttamente il contenuto del parametro dell'opzione \texttt{-o} +del comando \texttt{mount}. I valori utilizzabili dipendono dal tipo di +filesystem e ciascuno ha i suoi, pertanto si rimanda alla documentazione della +pagina di manuale di questo comando e dei singoli filesystem. + +Dopo l'esecuzione della funzione il contenuto del filesystem viene resto +disponibile nella directory specificata come \itindex{mount~point} +\textit{mount point}, il precedente contenuto di detta directory viene +mascherato dal contenuto della directory radice del filesystem montato. Fino +ai kernel della serie 2.2.x non era possibile montare un filesystem se un +\textit{mount point} era già in uso. + +A partire dal kernel 2.4.x inoltre è divenuto possibile sia spostare +atomicamente un \itindex{mount~point} \textit{mount point} da una directory ad +un'altra, sia montare lo stesso filesystem in diversi \itindex{mount~point} +\textit{mount point}, sia montare più filesystem sullo stesso +\itindex{mount~point} \textit{mount point} impilandoli l'uno sull'altro, nel +qual caso vale comunque quanto detto in precedenza, e cioè che solo il +contenuto dell'ultimo filesystem montato sarà visibile. + +Oltre alle opzioni specifiche di ciascun filesystem, che si passano nella +forma della lista di parole chiave indicata con l'argomento \param{data}, +esistono pure alcune opzioni che si possono applicare in generale, anche se +non è detto che tutti i filesystem le supportino, che si specificano tramite +l'argomento \param{mountflags}. L'argomento inoltre può essere utilizzato per +modificare il comportamento della funzione, facendole compiere una operazione +diversa (ad esempio un rimontaggio, invece che un montaggio). + +In Linux \param{mountflags} deve essere un intero a 32 bit; fino ai kernel +della serie 2.2.x i 16 più significativi avevano un valore riservato che +doveva essere specificato obbligatoriamente,\footnote{il valore era il + \itindex{magic~number} \textit{magic number} \code{0xC0ED}, si può usare la + costante \const{MS\_MGC\_MSK} per ottenere la parte di \param{mountflags} + riservata al \textit{magic number}, mentre per specificarlo si può dare un + OR aritmetico con la costante \const{MS\_MGC\_VAL}.} e si potevano usare +solo i 16 meno significativi. Oggi invece, con un numero di opzioni superiore, +sono utilizzati tutti e 32 i bit, ma qualora nei 16 più significativi sia +presente detto valore, che non esprime una combinazione valida, esso viene +ignorato. Il valore dell'argomento deve essere espresso come maschera binaria +e i vari bit devono essere impostati con un OR aritmetico dei rispettivi flag, +identificati dalle costanti riportate nell'elenco seguente: + +\begin{basedescript}{\desclabelwidth{2.cm}\desclabelstyle{\nextlinelabel}} +\itindbeg{bind~mount} +\item[\const{MS\_BIND}] Effettua un cosiddetto \textit{bind mount}, in cui è + possibile montare una directory di un filesystem in un'altra directory, + l'opzione è disponibile a partire dai kernel della serie 2.4. In questo caso + verranno presi in considerazione solo gli argomenti \param{source}, che + stavolta indicherà la directory che si vuole montare (e non un file di + dispositivo) e \param{target} che indicherà la directory su cui verrà + effettuato il \textit{bind mount}. Gli argomenti \param{filesystemtype} + e \param{data} vengono ignorati. + + In sostanza quello che avviene è che in corrispondenza del \textit{pathname} + indicato da \param{target} viene montato l'\textit{inode} di \param{source}, + così che la porzione di albero dei file presente sotto + \param{source} diventi visibile allo stesso modo sotto + \param{target}. Trattandosi esattamente dei dati dello stesso filesystem, + ogni modifica fatta in uno qualunque dei due rami di albero sarà visibile + nell'altro, visto che entrambi faranno riferimento agli stessi + \textit{inode}. + + Dal punto di vista del \itindex{Virtual~File~System} VFS l'operazione è + analoga al montaggio di un filesystem proprio nel fatto che anche in questo + caso si inserisce in corrispondenza della \textit{dentry} di \texttt{target} + un diverso \textit{inode}, che stavolta, invece di essere quello della + radice del filesystem indicato da un file di dispositivo, è quello di una + directory già montata. + + Si tenga presente che proprio per questo sotto \param{target} comparirà il + contenuto che è presente sotto \param{source} all'interno del filesystem in + cui quest'ultima è contenuta. Questo potrebbe non corrispondere alla + porzione di albero che sta sotto \param{source} qualora in una + sottodirectory di quest'ultima si fosse effettuato un altro montaggio. In + tal caso infatti nella porzione di albero sotto \param{source} si troverebbe + il contenuto del nuovo filesystem (o di un altro \textit{bind mount}) mentre + sotto \param{target} ci sarebbe il contenuto presente nel filesystem + originale.\footnote{questo evita anche il problema dei \textit{loop} di + fig.~\ref{fig:file_link_loop}, dato che se anche si montasse su + \param{target} una directory in cui essa è contenuta, il cerchio non + potrebbe chiudersi perché ritornati a \param{target} dentro il + \textit{bind mount} vi si troverebbe solo il contenuto originale e non si + potrebbe tornare indietro.} + + Fino al kernel 2.6.26 questo flag doveva essere usato da solo, in quanto il + \textit{bind mount} continuava ad utilizzare le stesse opzioni del montaggio + originale, dal 2.6.26 è stato introdotto il supporto per il cosiddetto + \textit{read-only bind mount} e viene onorata la presenza del flag + \const{MS\_RDONLY}. In questo modo si ottiene che l'accesso ai file sotto + \param{target} sia effettuabile esclusivamente in sola lettura. + + Il supporto per il \textit{bind mount} consente di superare i limiti + presenti per gli \textit{hard link} (di cui parleremo in + sez.~\ref{sec:file_link}) ottenendo un qualcosa di analogo in cui si può + fare riferimento alla porzione dell'albero dei file di un filesystem + presente a partire da una certa directory utilizzando una qualunque altra + directory, anche se questa sta su un filesystem diverso. Si può così fornire + una alternativa all'uso dei link simbolici (di cui parleremo in + sez.~\ref{sec:file_symlink}) che funziona correttamente anche all'intero di + un \textit{chroot} (argomento su cui torneremo in + sez.~\ref{sec:file_chroot}. +\itindend{bind~mount} + +\item[\const{MS\_DIRSYNC}] Richiede che ogni modifica al contenuto di una + directory venga immediatamente registrata su disco in maniera sincrona + (introdotta a partire dai kernel della serie 2.6). L'opzione si applica a + tutte le directory del filesystem, ma su alcuni filesystem è possibile + impostarla a livello di singole directory o per i sottorami di una directory + con il comando \cmd{lsattr}.\footnote{questo avviene tramite delle opportune + \texttt{ioctl} (vedi sez.~\ref{sec:file_ioctl}).} + + Questo consente di ridurre al minimo il rischio di perdita dei dati delle + directory in caso di crollo improvviso del sistema, al costo di una certa + perdita di prestazioni dato che le funzioni di scrittura relative ad + operazioni sulle directory non saranno più bufferizzate e si bloccheranno + fino all'arrivo dei dati sul disco prima che un programma possa proseguire. + +\item[\const{MS\_MANDLOCK}] Consente l'uso del \textit{mandatory locking} + \itindex{mandatory~locking} (vedi sez.~\ref{sec:file_mand_locking}) sui file + del filesystem. Per poterlo utilizzare effettivamente però esso dovrà essere + comunque attivato esplicitamente per i singoli file impostando i permessi + come illustrato in sez.~\ref{sec:file_mand_locking}. + +\item[\const{MS\_MOVE}] Effettua uno del spostamento del \itindex{mount~point} + \textit{mount point} di un filesystem. La directory del + \itindex{mount~point} \textit{mount point} originale deve essere indicata + nell'argomento \param{source}, e la sua nuova posizione + nell'argomento \param{target}. Tutti gli altri argomenti della funzione + vengono ignorati. + + Lo spostamento avviene atomicamente, ed il ramo di albero presente + sotto \param{source} sarà immediatamente visibile sotto \param{target}. Non + esiste cioè nessun momento in cui il filesystem non risulti montato in una o + nell'altra directory e pertanto è garantito che la risoluzione di + \itindsub{pathname}{relativo} \textit{pathname} relativi all'interno del + filesystem non possa fallire. + +\item[\const{MS\_NOATIME}] Viene disabilitato sul filesystem l'aggiornamento + degli \textit{access time} (vedi sez.~\ref{sec:file_file_times}) per + qualunque tipo di file. Dato che l'aggiornamento degli \textit{access time} + è una funzionalità la cui utilità è spesso irrilevante ma comporta un costo + elevato visto che una qualunque lettura comporta comunque una scrittura su + disco,\footnote{e questo ad esempio ha conseguenze molto pesanti nell'uso + della batteria sui portatili.} questa opzione consente di disabilitarla + completamente. La soluzione può risultare troppo drastica dato che + l'informazione viene comunque utilizzata da alcuni programmi, per cui nello + sviluppo del kernel sono state introdotte altre opzioni che forniscono + soluzioni più appropriate e meno radicali. + +\item[\const{MS\_NODEV}] Viene disabilitato sul filesystem l'accesso ai file + di dispositivo eventualmente presenti su di esso. L'opzione viene usata come + misura di precauzione per rendere inutile la presenza di eventuali file di + dispositivo su filesystem che non dovrebbero contenerne.\footnote{si ricordi + che le convenzioni del \itindex{Filesystem~Hierarchy~Standard~(FHS)} + \textit{Linux Filesystem Hierarchy Standard} richiedono che questi siano + mantenuti esclusivamente sotto \texttt{/dev}.} + + Viene utilizzata, assieme a \const{MS\_NOEXEC} e \const{MS\_NOSUID}, per + fornire un accesso più controllato a quei filesystem di cui gli utenti hanno + il controllo dei contenuti, in particolar modo quelli posti su dispositivi + rimuovibili. In questo modo si evitano alla radice possibili situazioni in + cui un utente malizioso inserisce su uno di questi filesystem dei file di + dispositivo con permessi ``opportunamente'' ampliati che gli consentano di + accedere anche a risorse cui non dovrebbe. + +\item[\const{MS\_NODIRATIME}] Viene disabilitato sul filesystem + l'aggiornamento degli \textit{access time} (vedi + sez.~\ref{sec:file_file_times}), ma soltanto per le directory. Costituisce + una alternativa per \const{MS\_NOATIME}, che elimina l'informazione per le + directory, che in pratica che non viene mai utilizzata, mantenendola per i + file in cui invece ha un impiego, sia pur limitato. + +\item[\const{MS\_NOEXEC}] Viene disabilitata sul filesystem l'esecuzione di un + qualunque file eseguibile eventualmente presente su di esso. L'opzione viene + usata come misura di precauzione per rendere impossibile l'uso di programmi + posti su filesystem che non dovrebbero contenerne. + + Anche in questo caso viene utilizzata per fornire un accesso più controllato + a quei filesystem di cui gli utenti hanno il controllo dei contenuti. Da + questo punto di vista l'opzione è meno importante delle analoghe + \const{MS\_NODEV} e \const{MS\_NOSUID} in quanto l'esecuzione di un + programma creato dall'utente pone un livello di rischio nettamente + inferiore, ed è in genere consentita per i file contenuti nella sua home + directory.\footnote{cosa che renderebbe superfluo l'attivazione di questa + opzione, il cui uso ha senso solo per ambienti molto controllati in cui si + vuole che gli utenti eseguano solo i programmi forniti + dall'amministratore.} + +\item[\const{MS\_NOSUID}] Viene disabilitato sul filesystem l'effetto dei bit + dei permessi \itindex{suid~bit} \acr{suid} e \itindex{sgid~bit} \acr{sgid} + (vedi sez.~\ref{sec:file_special_perm}) eventualmente presenti sui file in + esso contenuti. L'opzione viene usata come misura di precauzione per rendere + inefficace l'effetto di questi bit per filesystem in cui non ci dovrebbero + essere file dotati di questi permessi. + + Di nuovo viene utilizzata, analogamente a \const{MS\_NOEXEC} e + \const{MS\_NODEV}, per fornire un accesso più controllato a quei filesystem + di cui gli utenti hanno il controllo dei contenuti. In questo caso si evita + che un utente malizioso possa inserire su uno di questi filesystem un + eseguibile con il bit \itindex{suid~bit} \acr{suid} attivo e di proprietà + dell'amministratore o di un altro utente, che gli consentirebbe di eseguirlo + per conto di quest'ultimo. + +\item[\const{MS\_PRIVATE}] Marca un \itindex{mount~point} \textit{mount point} + come privato. Si tratta di una delle nuove opzioni (insieme a + \const{MS\_SHARED}, \const{MS\_SLAVE} e \const{MS\_UNBINDABLE}) facenti + parte dell'infrastruttura degli \itindex{shared~subtree} \textit{shared + subtree} introdotta a partire dal kernel 2.6.15, che estendono le + funzionalità dei \itindex{bind~mount} \textit{bind mount}. In questo caso + \param{target} dovrà fare riferimento al \textit{mount point} che si intende + marcare, e tutti gli altri argomenti verranno ignorati. + + Di default, finché non lo si marca altrimenti con una delle altre opzioni + dell'interfaccia \itindex{shared~subtree} \textit{shared subtree}, ogni + \textit{mount point} è privato. Ogni \textit{bind mount} ottenuto da un + \itindex{mount~point} \textit{mount point} di tipo \textit{private} si + comporta come descritto nella trattazione di \const{MS\_BIND}. Si usa questo + flag principalmente per revocare gli effetti delle altre opzioni e riportare + il comportamento a quello ordinario. + +\item[\const{MS\_RDONLY}] Esegue il montaggio del filesystem in sola lettura, + non sarà possibile nessuna modifica ai suoi contenuti. Viene usato tutte le + volte che si deve accedere ai contenuti di un filesystem con la certezza che + questo non venga modificato (ad esempio per ispezionare un filesystem + corrotto). All'avvio di default il kernel monta la radice in questa + modalità. + +\item[\const{MS\_REC}] Applica ricorsivamente a tutti i \itindex{mount~point} + \textit{mount point} presenti al di sotto del \textit{mount point} indicato + gli effetti della opzione degli \itindex{shared~subtree} \textit{shared + subtree} associata. Anche questo caso l'argomento \param{target} deve fare + riferimento ad un \itindex{mount~point} \textit{mount point} e tutti gli + altri argomenti sono ignorati, ed il flag deve essere indicato assieme ad + una fra \const{MS\_PRIVATE}, \const{MS\_SHARED}, \const{MS\_SLAVE} e + \const{MS\_UNBINDABLE}. + +\item[\const{MS\_RELATIME}] Indica di effettuare l'aggiornamento degli + \textit{access time} sul filesystem soltanto quando questo risulti + antecedente il valore corrente del \textit{modification time} o del + \textit{change time} (per i tempi dei file si veda + sez.~\ref{sec:file_file_times}). L'opzione è disponibile a partire dal + kernel 2.6.20, mentre dal 2.6.30 questo è diventato il comportamento di + default del sistema, che può essere riportato a quello tradizionale con + l'uso di \const{MS\_STRICTATIME}. Sempre dal 2.6.30 il comportamento è stato + anche modificato e l'\textit{access time} viene comunque aggiornato se è più + vecchio di un giorno. + + L'opzione consente di evitare i problemi di prestazioni relativi + all'aggiornamento dell'\textit{access time} senza avere impatti negativi + riguardo le funzionalità, il comportamento adottato infatti consente di + rendere evidente che vi è stato un accesso dopo la scrittura, ed evitando al + contempo ulteriori operazioni su disco negli accessi successivi. In questo + modo l'informazione relativa al fatto che un file sia stato letto resta + disponibile, ed i programmi che ne fanno uso continuano a funzionare. Con + l'introduzione di questo comportamento l'uso delle alternative + \const{MS\_NOATIME} e \const{MS\_NODIRATIME} è sostanzialmente inutile. + +\item[\const{MS\_REMOUNT}] Consente di rimontare un filesystem già montato + cambiandone le opzioni di montaggio in maniera atomica. In questo modo si + possono modificare le opzioni del filesystem anche se questo è in uso. Gli + argomenti \param{source} e \param{target} devono essere gli stessi usati per + il montaggio originale, mentre \param{data} che \param{mountflags} + conterranno le nuove opzioni, \param{filesystemtype} viene ignorato. + + Qualunque opzione specifica del filesystem indicata con \param{data} può + essere modificata, mentre con \param{mountflags} possono essere modificate + solo alcune opzioni generiche. Con i kernel più recenti queste sono soltanto + \const{MS\_MANDLOCK}, \const{MS\_RDONLY} e \const{MS\_SYNCHRONOUS}, prima + del kernel 2.6.16 potevano essere modificate anche le ulteriori + \const{MS\_NOATIME} e \const{MS\_NODIRATIME}, ed infine prima del kernel + 2.4.10 anche \const{MS\_NODEV}, \const{MS\_NOEXEC} e \const{MS\_NOSUID}. + +\item[\const{MS\_SHARED}] Marca un \itindex{mount~point} \textit{mount point} + come \textit{shared mount}. Si tratta di una delle nuove opzioni (insieme a + \const{MS\_PRIVATE}, \const{MS\_SLAVE} e \const{MS\_UNBINDABLE}) facenti + parte dell'infrastruttura degli \itindex{shared~subtree} \textit{shared + subtree} introdotta a partire dal kernel 2.6.15, che estendono le + funzionalità dei \itindex{bind~mount} \textit{bind mount}. In questo caso + \param{target} dovrà fare riferimento al \itindex{mount~point} \textit{mount + point} che si intende marcare, e tutti gli altri argomenti verranno + ignorati. + + Lo scopo dell'opzione è ottenere che tutti i successivi \textit{bind mount} + effettuati da un \textit{mount point} marcato da essa siano di tipo + \textit{shared}, cioè ``\textsl{condividano}'' con l'originale e fra di loro + ogni ulteriore operazione di montaggio o smontaggio che avviene su una + directory al di sotto di uno qualunque di essi. Le operazioni di montaggio e + smontaggio cioè vengono ``\textsl{propagate}'' a tutti i \textit{mount + point} della stessa condivisione, e la sezione di albero di file vista al + di sotto di ciascuno di essi sarà sempre identica. + +\item[\const{MS\_SILENT}] Richiede la soppressione di alcuni messaggi di + avvertimento nei log del kernel (vedi sez.~\ref{sec:sess_daemon}). L'opzione + è presente a partire dal kernel 2.6.17 e sostituisce, utilizzando un nome + non fuorviante, la precedente \const{MS\_VERBOSE}, introdotta nel kernel + 2.6.12, che aveva lo stesso effetto. + +\item[\const{MS\_SLAVE}] Marca un \itindex{mount~point} \textit{mount point} + come \textit{slave mount}. Si tratta di una delle nuove opzioni (insieme a + \const{MS\_PRIVATE}, \const{MS\_SHARED} e \const{MS\_UNBINDABLE}) facenti + parte dell'infrastruttura degli \itindex{shared~subtree} \textit{shared + subtree} introdotta a partire dal kernel 2.6.15, che estendono le + funzionalità dei \itindex{bind~mount} \textit{bind mount}. In questo caso + \param{target} dovrà fare riferimento al \textit{mount point} che si intende + marcare, e tutti gli altri argomenti verranno ignorati. + + Lo scopo dell'opzione è ottenere che tutti i successivi \textit{bind mount} + effettuati da un \textit{mount point} marcato da essa siano di tipo + \textit{slave}, cioè ``\textsl{condividano}'' ogni ulteriore operazione di + montaggio o smontaggio che avviene su una directory al di sotto del + \textit{mount point} originale. Le operazioni di montaggio e smontaggio in + questo caso vengono ``\textsl{propagate}'' soltanto dal \textit{mount point} + originale (detto anche \textit{master}) verso gli \textit{slave}, mentre + essi potranno eseguire al loro interno ulteriori montaggi che non saranno + propagati né negli altri né nel \itindex{mount~point} \textit{mount point} + originale. + +\item[\const{MS\_STRICTATIME}] Ripristina il comportamento tradizionale per + cui l'\textit{access time} viene aggiornato ad ogni accesso al + file. L'opzione è disponibile solo a partire dal kernel 2.6.30 quando il + comportamento di default del kernel è diventato quello fornito da + \const{MS\_RELATIME}. + +\item[\const{MS\_SYNCHRONOUS}] Abilita la scrittura sincrona richiedendo che + ogni modifica al contenuto del filesystem venga immediatamente registrata su + disco. Lo stesso comportamento può essere ottenuto con il flag + \const{O\_SYNC} di \func{open} (vedi sez.~\ref{sec:file_open}). + + Questa opzione consente di ridurre al minimo il rischio di perdita dei dati + in caso di crollo improvviso del sistema, al costo di una pesante perdita di + prestazioni dato che tutte le funzioni di scrittura non saranno più + bufferizzate e si bloccheranno fino all'arrivo dei dati sul disco. Per un + compromesso in cui questo comportamento avviene solo per le directory, ed ha + quindi una incidenza nettamente minore, si può usare \const{MS\_DIRSYNC}. + +\item[\const{MS\_UNBINDABLE}] Marca un \itindex{mount~point} \textit{mount + point} come \textit{unbindable mount}. Si tratta di una delle nuove + opzioni (insieme a \const{MS\_PRIVATE}, \const{MS\_SHARED} e + \const{MS\_SLAVE}) facenti parte dell'infrastruttura degli + \itindex{shared~subtree} \textit{shared subtree} introdotta a partire dal + kernel 2.6.15, che estendono le funzionalità dei \itindex{bind~mount} + \textit{bind mount}. In questo caso + \param{target} dovrà fare riferimento al \textit{mount point} che si intende + marcare, e tutti gli altri argomenti verranno ignorati. + + Un \textit{mount point} marcato in questo modo disabilità la capacità di + eseguire dei \itindex{bind~mount} \textit{bind mount}. Si comporta cioè come + allo stesso modo di un \itindex{mount~point} \textit{mount point} ordinario + di tipo \textit{private} con in più la restrizione che nessuna sua + sottodirectory (anche se relativa ad un ulteriore montaggio) possa essere + utilizzata per un come sorgente di un \itindex{bind~mount} \textit{bind + mount}. + +\end{basedescript} + +% NOTE per \const{MS\_SLAVE},\const{MS\_SHARE}, \const{MS\_PRIVATE} e +% \const{MS\_UNBINDABLE} dal 2.6.15 vedi shared subtrees, in particolare +% * http://lwn.net/Articles/159077/ e +% * Documentation/filesystems/sharedsubtree.txt + +% TODO: (bassa priorità) non documentati ma presenti in sys/mount.h: +% * MS_POSIXACL +% * MS_KERNMOUNT +% * MS_I_VERSION +% * MS_ACTIVE +% * MS_NOUSER + + +Una volta che non si voglia più utilizzare un certo filesystem è possibile +``\textsl{smontarlo}'' usando la funzione \funcd{umount}, il cui prototipo è: + +\begin{funcproto}{ +\fhead{sys/mount.h} +\fdecl{umount(const char *target)} +\fdesc{Smonta un filesystem.} +} +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, + nel qual caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{EBUSY}] il filesystem è occupato. + \item[\errcode{EINVAL}] \param{target} non è un \textit{mount point}. + \item[\errcode{EPERM}] il processo non ha i privilegi di + amministratore.\footnotemark + \end{errlist} + ed inoltre \errval{EFAULT}, \errval{ELOOP}, \errval{ENAMETOOLONG}, + \errval{ENOENT}, \errval{ENOMEM} nel loro significato generico. } +\end{funcproto} + +\footnotetext{più precisamente la \itindex{capabilities} capacità + \texttt{CAP\_SYS\_ADMIN}.} + +La funzione prende il nome della directory su cui il filesystem è montato e +non il file o il dispositivo che è stato montato,\footnote{questo è vero a + partire dal kernel 2.3.99-pre7, prima esistevano due chiamate separate e la + funzione poteva essere usata anche specificando il file di dispositivo.} in +quanto a partire dai kernel della serie 2.4.x è possibile montare lo stesso +dispositivo in più punti. Nel caso più di un filesystem sia stato montato +sullo stesso \itindex{mount~point} \textit{mount point} viene smontato quello +che è stato montato per ultimo. Si tenga presente che la funzione fallisce se +il filesystem è ``\textsl{occupato}'', cioè quando ci sono ancora dei file +aperti sul filesystem, se questo contiene la \index{directory~di~lavoro} +directory di lavoro di un qualunque processo o il \itindex{mount~point} +\textit{mount point} di un altro filesystem. + +Linux provvede inoltre una seconda funzione, \funcd{umount2}, che consente un +maggior controllo delle operazioni, come forzare lo smontaggio di un +filesystem anche quando questo risulti occupato; il suo prototipo è: + +\begin{funcproto}{ +\fhead{sys/mount.h} +\fdecl{umount2(const char *target, int flags)} +\fdesc{Smonta un filesystem.} +} +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, + nel qual caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{BUSY}] \param{target} è la \index{directory~di~lavoro} + directory di lavoro di qualche processo, o contiene dei file aperti, o un + altro mount point. + \item[\errcode{EAGAIN}] si è chiamata la funzione con \const{MNT\_EXPIRE} + ed il filesystem non era occupato. + \item[\errcode{EINVAL}] \param{target} non è un \itindex{mount~point} + \textit{mount point} o si è usato \const{MNT\_EXPIRE} con + \const{MNT\_FORCE} o \const{MNT\_DETACH} o si è specificato un flag non + esistente. + \end{errlist} + e tutti gli altri valori visti per \func{umount} con lo stesso significato.} +\end{funcproto} + +Il valore di \param{flags} è una maschera binaria dei flag che controllano le +modalità di smontaggio, che deve essere specificato con un OR aritmetico delle +costanti illustrate in tab.~\ref{tab:umount2_flags}. Specificando +\const{MNT\_FORCE} la funzione cercherà di liberare il filesystem anche se è +occupato per via di una delle condizioni descritte in precedenza. A seconda +del tipo di filesystem alcune (o tutte) possono essere superate, evitando +l'errore di \errcode{EBUSY}. In tutti i casi prima dello smontaggio viene +eseguita una sincronizzazione dei dati. + +\begin{table}[!htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|p{8cm}|} + \hline + \textbf{Costante} & \textbf{Descrizione}\\ + \hline + \hline + \const{MNT\_FORCE} & forza lo smontaggio del filesystem anche se questo è + occupato (presente dai kernel della serie 2.2).\\ + \const{MNT\_DETACH} & esegue uno smontaggio ``\textsl{pigro}'', in cui si + blocca l'accesso ma si aspetta che il filesystem si + liberi (presente dal kernel 2.4.11 e dalla + \acr{glibc} 2.11).\\ + \const{MNT\_EXPIRE} & se non occupato marca un \itindex{mount~point} + \textit{mount point} come ``\textsl{in scadenza}'' in + modo che ad una successiva chiamata senza utilizzo + del filesystem questo venga smontato (presente dal + kernel 2.6.8 e dalla \acr{glibc} 2.11).\\ + \const{UMOUNT\_NOFOLLOW}& non dereferenzia \param{target} se questo è un + link simbolico (vedi sez.~\ref{sec:file_symlink}) + evitando problemi di sicurezza (presente dal kernel + 2.6.34).\\ + \hline + \end{tabular} + \caption{Costanti che identificano i bit dell'argomento \param{flags} + della funzione \func{umount2}.} + \label{tab:umount2_flags} +\end{table} + +Con l'opzione \const{MNT\_DETACH} si richiede invece uno smontaggio +``\textsl{pigro}'' (o \textit{lazy umount}) in cui il filesystem diventa +inaccessibile per i nuovi processi subito dopo la chiamata della funzione, ma +resta accessibile per quelli che lo hanno ancora in uso e non viene smontato +fintanto che resta occupato. + +Con \const{MNT\_EXPIRE}, che non può essere specificato insieme agli altri +due, si marca il \itindex{mount~point} \textit{mount point} di un filesystem +non occupato come ``\textsl{in scadenza}'', in tal caso \func{umount2} ritorna +con un errore di \errcode{EAGAIN}, mentre in caso di filesystem occupato si +sarebbe ricevuto \errcode{BUSY}. Una volta marcato, se nel frattempo non +viene fatto nessun uso del filesystem, ad una successiva chiamata con +\const{MNT\_EXPIRE} questo verrà smontato. Questo flag consente di realizzare +un meccanismo che smonti automaticamente i filesystem che restano inutilizzato +per un certo periodo di tempo. + +% Infine il flag \const{UMOUNT\_NOFOLLOW} impedisce l'uso di un link simbolico +% per \param{target} evitando così che si possano passare ai programmi che +% effettuano lo smontaggio dei filesystem per i quali è previsto la possibilità +% di gestione da parte degli utenti con uno programma \acr{sgid} + +Altre due funzioni specifiche di Linux,\footnote{esse si trovano anche su BSD, + ma con una struttura diversa.} utili per ottenere in maniera diretta +informazioni riguardo al filesystem su cui si trova un certo file, sono +\funcd{statfs} e \funcd{fstatfs}, i cui prototipi sono: + +\begin{funcproto}{ +\fhead{sys/vfs.h} +\fdecl{int statfs(const char *path, struct statfs *buf)} +\fdecl{int fstatfs(int fd, struct statfs *buf)} +\fdesc{Restituiscono informazioni relative ad un filesystem.} +} +{Le funzioni ritornano $0$ in caso di successo e $-1$ per un errore, + nel qual caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{ENOSYS}] il filesystem su cui si trova il file specificato + non supporta la funzione. + \end{errlist} ed inoltre \errval{EFAULT} ed \errval{EIO} per entrambe, + \errval{EBADF} per \func{fstatfs}, \errval{ENOTDIR}, \errval{ENAMETOOLONG}, + \errval{ENOENT}, \errval{EACCES}, \errval{ELOOP} per \func{statfs} nel loro + significato generico.} +\end{funcproto} + +Queste funzioni permettono di ottenere una serie di informazioni generali +riguardo al filesystem su cui si trova il file specificato con un ; queste vengono +restituite all'indirizzo \param{buf} di una struttura \struct{statfs} definita +come in fig.~\ref{fig:sys_statfs}, ed i campi che sono indefiniti per il +filesystem in esame sono impostati a zero. I valori del campo \var{f\_type} +sono definiti per i vari filesystem nei relativi file di header dei sorgenti +del kernel da costanti del tipo \var{XXX\_SUPER\_MAGIC}, dove \var{XXX} in +genere è il nome del filesystem stesso. + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{\textwidth} + \includestruct{listati/statfs.h} + \end{minipage} + \normalsize + \caption{La struttura \structd{statfs}.} + \label{fig:sys_statfs} +\end{figure} + +Le \acr{glibc} provvedono infine una serie di funzioni per la gestione dei due +file \conffile{/etc/fstab} ed \conffile{/etc/mtab}, che convenzionalmente sono +usati in quasi tutti i sistemi unix-like per mantenere rispettivamente le +informazioni riguardo ai filesystem da montare e a quelli correntemente +montati. Le funzioni servono a leggere il contenuto di questi file in +opportune strutture \struct{fstab} e \struct{mntent}, e, per +\conffile{/etc/mtab} per inserire e rimuovere le voci presenti nel file. + +In generale si dovrebbero usare queste funzioni (in particolare quelle +relative a \conffile{/etc/mtab}), quando si debba scrivere un programma che +effettua il montaggio di un filesystem; in realtà in questi casi è molto più +semplice invocare direttamente il programma \cmd{mount}, per cui ne +tralasceremo la trattazione, rimandando al manuale delle \acr{glibc} +\cite{glibc} per la documentazione completa. + +% TODO (bassa priorità) scrivere delle funzioni (getfsent e getmntent &C) +% TODO (bassa priorità) documentare ? swapon e swapoff (man 2 ...) + +\section{La gestione di file e directory} +\label{sec:file_dir} + +Come già accennato in sez.~\ref{sec:file_filesystem} in un sistema unix-like +la gestione dei file ha delle caratteristiche specifiche che derivano +direttamente dall'architettura del sistema. In questa sezione esamineremo le +funzioni usate per la manipolazione di file e directory, per la creazione di +link simbolici e diretti, per la gestione e la lettura delle directory. + +In particolare ci soffermeremo sulle conseguenze che derivano +dall'architettura dei filesystem illustrata nel capitolo precedente per quanto +riguarda il comportamento e gli effetti delle varie funzioni. + + +\subsection{Le funzioni \func{link} e \func{unlink}} +\label{sec:file_link} + +Una caratteristica comune a diversi sistemi operativi è quella di poter creare +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 +usualmente chiamati \textit{link}; ma data l'architettura del sistema riguardo +la gestione dei file ci sono due metodi sostanzialmente diversi per fare +questa operazione. + +Come spiegato in sez.~\ref{sec:file_filesystem} l'accesso al contenuto di un +file su disco avviene passando attraverso il suo \itindex{inode} +\textit{inode}, che è la struttura usata dal kernel che lo identifica +univocamente all'interno di un singolo filesystem. Il nome del file che si +trova nella voce di una directory è solo un'etichetta, mantenuta all'interno +della directory, che viene associata ad un puntatore che fa riferimento al +suddetto \textit{inode}. + +Questo significa che, fintanto che si resta sullo stesso filesystem, la +realizzazione di un link è immediata, ed uno stesso file può avere tanti nomi +diversi, dati da altrettante associazioni diverse allo stesso \itindex{inode} +\textit{inode} effettuate tramite ``etichette'' diverse in directory +diverse. Si noti anche che nessuno di questi nomi viene ad assumere una +particolare preferenza o originalità rispetto agli altri, in quanto tutti +fanno comunque riferimento allo stesso \itindex{inode} \textit{inode}. + +Per aggiungere ad una directory una voce che faccia riferimento ad un +\itindex{inode} \textit{inode} già esistente si utilizza la funzione +\funcd{link}; si suole chiamare questo tipo di associazione un collegamento +diretto, o \textit{hard link}. Il prototipo della funzione è il seguente: + +\begin{funcproto}{ +\fhead{unistd.h} +\fdecl{int link(const char *oldpath, const char *newpath)} +\fdesc{Crea un nuovo collegamento diretto (\textit{hard link}).} +} +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, + nel qual caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{EXDEV}] i file \param{oldpath} e \param{newpath} non fanno + riferimento ad un filesystem montato sullo stesso \itindex{mount~point} + \textit{mount point}. + \item[\errcode{EPERM}] il filesystem che contiene \param{oldpath} e + \param{newpath} non supporta i link diretti o è una directory. + \item[\errcode{EEXIST}] un file (o una directory) di nome \param{newpath} + esiste già. + \item[\errcode{EMLINK}] ci sono troppi link al file \param{oldpath} (il + numero massimo è specificato dalla variabile \const{LINK\_MAX}, vedi + sez.~\ref{sec:sys_limits}). + \end{errlist} ed inoltre \errval{EACCES}, \errval{ENAMETOOLONG}, + \errval{ENOTDIR}, \errval{EFAULT}, \errval{ENOMEM}, \errval{EROFS}, + \errval{ELOOP}, \errval{ENOSPC}, \errval{EIO} nel loro significato + generico.} +\end{funcproto} + + +La funzione crea sul \textit{pathname} \param{newpath} un collegamento diretto +al file indicato da \param{oldpath}. Per quanto detto la creazione di un +nuovo collegamento diretto non copia il contenuto del file, ma si limita a +creare una voce nella directory specificata da \param{newpath} e ad aumentare +di uno il numero di riferimenti al file (riportato nel campo \var{st\_nlink} +della struttura \struct{stat}, vedi sez.~\ref{sec:file_stat}) aggiungendo il +nuovo nome ai precedenti. Si noti che uno stesso file può essere così chiamato +con vari nomi in diverse directory. + +Per quanto dicevamo in sez.~\ref{sec:file_filesystem} la creazione di un +collegamento diretto è possibile solo se entrambi i \textit{pathname} sono +nello stesso filesystem; inoltre il filesystem deve supportare i collegamenti +diretti (il meccanismo non è disponibile ad esempio con il filesystem +\acr{vfat} di Windows). In realtà la funzione ha un ulteriore requisito, e +cioè che non solo che i due file siano sullo stesso filesystem, ma anche che +si faccia riferimento ad essi sullo stesso \itindex{mount~point} \textit{mount + point}.\footnote{si tenga presente infatti (vedi + sez.~\ref{sec:sys_file_config}) che a partire dal kernel 2.4 uno stesso + filesystem può essere montato più volte su directory diverse.} + +La funzione inoltre opera sia sui file ordinari che sugli altri oggetti del +filesystem, con l'eccezione delle directory. In alcune versioni di Unix solo +l'amministratore è in grado di creare un collegamento diretto ad un'altra +directory: questo viene fatto perché con una tale operazione è possibile +creare dei \textit{loop} nel filesystem (vedi l'esempio mostrato in +sez.~\ref{sec:file_symlink}, dove riprenderemo il discorso) che molti programmi +non sono in grado di gestire e la cui rimozione diventerebbe estremamente +complicata (in genere per questo tipo di errori occorre far girare il +programma \cmd{fsck} per riparare il filesystem). + +Data la pericolosità di questa operazione e la disponibilità dei link +simbolici (che vedremo in sez.~\ref{sec:file_symlink}) e dei +\itindex{bind~mount} \textit{bind mount} (già visti in +sez.~\ref{sec:sys_file_config}) che possono fornire la stessa funzionalità +senza questi problemi, nel caso di Linux questa capacità è stata completamente +disabilitata, e al tentativo di creare un link diretto ad una directory la +funzione \func{link} restituisce l'errore \errcode{EPERM}. + +Un ulteriore comportamento peculiare di Linux è quello in cui si crea un +\textit{hard link} ad un link simbolico. In questo caso lo standard POSIX +prevederebbe che quest'ultimo venga risolto e che il collegamento sia +effettuato rispetto al file cui esso punta, e che venga riportato un errore +qualora questo non esista o non sia un file. Questo era anche il comportamento +iniziale di Linux ma a partire dai kernel della serie 2.0.x\footnote{per la + precisione il comportamento era quello previsto dallo standard POSIX fino al + kernel di sviluppo 1.3.56, ed è stato temporaneamente ripristinato anche + durante lo sviluppo della serie 2.1.x, per poi tornare al comportamento + attuale fino ad oggi (per riferimento si veda + \url{http://lwn.net/Articles/293902}).} è stato adottato un comportamento +che non segue più lo standard per cui l'\textit{hard link} viene creato +rispetto al link simbolico, e non al file cui questo punta. + +La ragione di questa differenza rispetto allo standard, presente anche in +altri sistemi unix-like, sono dovute al fatto che un link simbolico può fare +riferimento anche ad un file non esistente o a una directory, per i quali +l'\textit{hard link} non può essere creato, per cui la scelta di seguire il +link simbolico è stata ritenuta una scelta scorretta nella progettazione +dell'interfaccia. Infatti se non ci fosse il comportamento adottato da Linux +sarebbe impossibile creare un \textit{hard link} ad un link simbolico, perché +la funzione lo risolverebbe e l'\textit{hard link} verrebbe creato verso la +destinazione. Invece evitando di seguire lo standard l'operazione diventa +possibile, ed anche il comportamento della funzione risulta molto più +comprensibile. Tanto più che se proprio se si vuole creare un \textit{hard + link} rispetto alla destinazione di un link simbolico è sempre possibile +farlo direttamente.\footnote{ciò non toglie che questo comportamento fuori + standard possa causare problemi, come nell'esempio descritto nell'articolo + citato nella nota precedente, a programmi che non si aspettano questa + differenza rispetto allo standard POSIX.} + +La rimozione di un file (o più precisamente della voce che lo referenzia +all'interno di una directory) si effettua con la funzione \funcd{unlink}; il +suo prototipo è il seguente: + +\begin{funcproto}{ +\fhead{unistd.h} +\fdecl{int unlink(const char *pathname)} +\fdesc{Cancella un file.} +} +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, + nel qual caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{EISDIR}] \param{pathname} si riferisce ad una + directory.\footnotemark + \item[\errcode{EROFS}] \param{pathname} è su un filesystem montato in sola + lettura. + \item[\errcode{EISDIR}] \param{pathname} fa riferimento a una directory. + \end{errlist} ed inoltre \errval{EACCES}, \errval{EFAULT}, \errval{ENOENT}, + \errval{ENOTDIR}, \errval{ENOMEM}, \errval{EROFS}, \errval{ELOOP}, + \errval{EIO} nel loro significato generico.} +\end{funcproto} + +\footnotetext{questo è un valore specifico ritornato da Linux che non consente + l'uso di \func{unlink} con le directory (vedi sez.~\ref{sec:file_remove}). + Non è conforme allo standard POSIX, che prescrive invece l'uso di + \errcode{EPERM} in caso l'operazione non sia consentita o il processo non + abbia privilegi sufficienti.} + +La funzione cancella il nome specificato da \param{pathname} nella relativa +directory e decrementa il numero di riferimenti nel relativo \itindex{inode} +\textit{inode}. Nel caso di link simbolico cancella il link simbolico; nel +caso di socket, fifo o file di dispositivo \index{file!di~dispositivo} rimuove +il nome, ma come per i file i processi che hanno aperto uno di questi oggetti +possono continuare ad utilizzarlo. + +Per cancellare una voce in una directory è necessario avere il permesso di +scrittura su di essa, dato che si va a rimuovere una voce dal suo contenuto, e +il diritto di esecuzione sulla directory che la contiene (affronteremo in +dettaglio l'argomento dei permessi di file e directory in +sez.~\ref{sec:file_access_control}). Se inoltre lo \itindex{sticky~bit} +\textit{sticky bit} (vedi sez.~\ref{sec:file_special_perm}) è impostato +occorrerà anche essere proprietari del file o proprietari della directory (o +root, per cui nessuna delle restrizioni è applicata). + +Una delle caratteristiche di queste funzioni è che la creazione/rimozione del +nome dalla directory e l'incremento/decremento del numero di riferimenti +\itindex{inode} nell'\textit{inode} devono essere effettuati in maniera +atomica (si veda sez.~\ref{sec:proc_atom_oper}) senza possibili interruzioni +fra le due operazioni. Per questo entrambe queste funzioni sono realizzate +tramite una singola system call. + +Si ricordi infine che un file non viene eliminato dal disco fintanto che tutti +i riferimenti ad esso sono stati cancellati: solo quando il \textit{link + count} mantenuto \itindex{inode} nell'\textit{inode} diventa zero lo spazio +occupato su disco viene rimosso (si ricordi comunque che a questo si aggiunge +sempre un'ulteriore condizione,\footnote{come vedremo in + cap.~\ref{cha:file_unix_interface} il kernel mantiene anche una tabella dei + file aperti nei vari processi, che a sua volta contiene i riferimenti agli + \itindex{inode} \textit{inode} ad essi relativi. Prima di procedere alla + cancellazione dello spazio occupato su disco dal contenuto di un file il + kernel controlla anche questa tabella, per verificare che anche in essa non + ci sia più nessun riferimento all'\textit{inode} in questione.} e cioè che +non ci siano processi che abbiano il suddetto file aperto). + +Questa proprietà viene spesso usata per essere sicuri di non lasciare file +temporanei su disco in caso di crash dei programmi; la tecnica è quella di +aprire il file e chiamare \func{unlink} subito dopo, in questo modo il +contenuto del file è sempre disponibile all'interno del processo attraverso il +suo file descriptor (vedi sez.~\ref{sec:file_fd}) fintanto che il processo non +chiude il file, ma non ne resta traccia in nessuna directory, e lo spazio +occupato su disco viene immediatamente rilasciato alla conclusione del +processo (quando tutti i file vengono chiusi). + + +\subsection{Le funzioni \func{remove} e \func{rename}} +\label{sec:file_remove} + +Al contrario di quanto avviene con altri Unix, in Linux non è possibile usare +\func{unlink} sulle directory; per cancellare una directory si può usare la +funzione \func{rmdir} (vedi sez.~\ref{sec:file_dir_creat_rem}), oppure la +funzione \funcd{remove}. + +Questa è la funzione prevista dallo standard ANSI C per cancellare un file o +una directory (e funziona anche per i sistemi che non supportano i link +diretti). Per i file è identica a \func{unlink} e per le directory è identica +a \func{rmdir}; il suo prototipo è: + +\begin{funcproto}{ +\fhead{stdio.h} +\fdecl{int remove(const char *pathname)} +\fdesc{Cancella un nome dal filesystem.} +} +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual + caso \var{errno} assumerà uno dei valori relativi alla chiamata utilizzata, + pertanto si può fare riferimento a quanto illustrato nelle descrizioni di + \func{unlink} e \func{rmdir}.} +\end{funcproto} + +La funzione utilizza la funzione \func{unlink}\footnote{questo vale usando le + \acr{glibc}; nelle libc4 e nelle libc5 la funzione \func{remove} è un + semplice alias alla funzione \func{unlink} e quindi non può essere usata per + le directory.} per cancellare i file e la funzione \func{rmdir} per +cancellare le directory; si tenga presente che per alcune implementazioni del +protocollo NFS utilizzare questa funzione può comportare la scomparsa di file +ancora in uso. + +Per cambiare nome ad un file o a una directory (che devono comunque essere +nello stesso filesystem) si usa invece la funzione \funcd{rename},\footnote{la + funzione è definita dallo standard ANSI C, ma si applica solo per i file, lo + standard POSIX estende la funzione anche alle directory.} il cui prototipo +è: + +\begin{funcproto}{ +\fhead{stdio.h} +\fdecl{int rename(const char *oldpath, const char *newpath)} +\fdesc{Rinomina un file.} +} +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, + nel qual caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{EISDIR}] \param{newpath} è una directory mentre + \param{oldpath} non è una directory. + \item[\errcode{EXDEV}] \param{oldpath} e \param{newpath} non sono sullo + stesso filesystem. + \item[\errcode{ENOTEMPTY}] \param{newpath} è una directory già esistente e + non vuota. + \item[\errcode{EBUSY}] o \param{oldpath} o \param{newpath} sono in uso da + parte di qualche processo (come \index{directory~di~lavoro} directory di + lavoro o come radice) o del sistema (come \itindex{mount~point} + \textit{mount point}). + \item[\errcode{EINVAL}] \param{newpath} contiene un prefisso di + \param{oldpath} o più in generale si è cercato di creare una directory come + sotto-directory di se stessa. + \item[\errcode{ENOTDIR}] uno dei componenti dei \textit{pathname} non è una + directory o \param{oldpath} è una directory e + \param{newpath} esiste e non è una directory. + \end{errlist} ed inoltre \errval{EACCES}, \errval{EPERM}, \errval{EMLINK}, + \errval{ENOENT}, \errval{ENOMEM}, \errval{EROFS}, \errval{ELOOP} e + \errval{ENOSPC} nel loro significato generico.} +\end{funcproto} + +La funzione rinomina il file \param{oldpath} in \param{newpath}, eseguendo se +necessario lo spostamento di un file fra directory diverse. Eventuali altri +link diretti allo stesso file non vengono influenzati. + +Il comportamento della funzione è diverso a seconda che si voglia rinominare +un file o una directory; se ci riferisce ad un file allora \param{newpath}, se +esiste, non deve essere una directory (altrimenti si ha l'errore +\errcode{EISDIR}). Nel caso \param{newpath} indichi un file esistente questo +viene cancellato e rimpiazzato (atomicamente). + +Se \param{oldpath} è una directory allora \param{newpath}, se esiste, deve +essere una directory vuota, altrimenti si avranno gli errori \errcode{ENOTDIR} +(se non è una directory) o \errcode{ENOTEMPTY} (se non è vuota). Chiaramente +\param{newpath} non può contenere \param{oldpath} altrimenti si avrà un errore +\errcode{EINVAL}. + +Se \param{oldpath} si riferisce ad un link simbolico questo sarà rinominato; se +\param{newpath} è un link simbolico verrà cancellato come qualunque altro +file. Infine qualora \param{oldpath} e \param{newpath} siano due nomi dello +stesso file lo standard POSIX prevede che la funzione non dia errore, e non +faccia nulla, lasciando entrambi i nomi; Linux segue questo standard, anche +se, come fatto notare dal manuale delle \textit{glibc}, il comportamento più +ragionevole sarebbe quello di cancellare \param{oldpath}. + +Il vantaggio nell'uso di questa funzione al posto della chiamata successiva di +\func{link} e \func{unlink} è che l'operazione è eseguita atomicamente, non +può esistere cioè nessun istante in cui un altro processo può trovare attivi +entrambi i nomi dello stesso file, o, in caso di sostituzione di un file +esistente, non trovare quest'ultimo prima che la sostituzione sia stata +eseguita. + +In ogni caso se \param{newpath} esiste e l'operazione fallisce per un qualche +motivo (come un crash del kernel), \func{rename} garantisce di lasciare +presente un'istanza di \param{newpath}. Tuttavia nella sovrascrittura potrà +esistere una finestra in cui sia \param{oldpath} che \param{newpath} fanno +riferimento allo stesso file. + + +\subsection{I link simbolici} +\label{sec:file_symlink} + +Come abbiamo visto in sez.~\ref{sec:file_link} la funzione \func{link} crea +riferimenti agli \itindex{inode} \textit{inode}, pertanto può funzionare +soltanto per file che risiedono sullo stesso filesystem e solo per un +filesystem di tipo Unix. Inoltre abbiamo visto che in Linux non è consentito +eseguire un link diretto ad una directory. + +Per ovviare a queste limitazioni i sistemi Unix supportano un'altra forma di +link (i cosiddetti \textit{soft link} o \textit{symbolic link}), che sono, +come avviene in altri sistemi operativi, dei file speciali che contengono +semplicemente il riferimento ad un altro file (o directory). In questo modo è +possibile effettuare link anche attraverso filesystem diversi, a file posti in +filesystem che non supportano i link diretti, a delle directory, ed anche a +file che non esistono ancora. + +Il sistema funziona in quanto i link simbolici sono riconosciuti come tali dal +kernel\footnote{è uno dei diversi tipi di file visti in + tab.~\ref{tab:file_file_types}, contrassegnato come tale + nell'\textit{inode}, e riconoscibile dal valore del campo \var{st\_mode} + della struttura \struct{stat} (vedi sez.~\ref{sec:file_stat}).} per cui +alcune funzioni di libreria (come \func{open} o \func{stat}) quando ricevono +come argomento un link simbolico vengono automaticamente applicate al file da +esso specificato. La funzione che permette di creare un nuovo link simbolico +è \funcd{symlink}, ed il suo prototipo è: + + +\begin{funcproto}{ +\fhead{unistd.h} +\fdecl{int symlink(const char *oldpath, const char *newpath)} +\fdesc{Crea un nuovo link simbolico.} +} +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, + nel qual caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{EPERM}] il filesystem che contiene \param{newpath} non + supporta i link simbolici. + \item[\errcode{ENOENT}] una componente di \param{newpath} non esiste o + \param{oldpath} è una stringa vuota. + \item[\errcode{EEXIST}] esiste già un file \param{newpath}. + \item[\errcode{EROFS}] \param{newpath} è su un filesystem montato in sola + lettura. + \end{errlist} ed inoltre \errval{EFAULT}, \errval{EACCES}, + \errval{ENAMETOOLONG}, \errval{ENOTDIR}, \errval{ENOMEM}, \errval{ELOOP}, + \errval{ENOSPC} e \errval{EIO} nel loro significato generico.} +\end{funcproto} + +La funzione crea un nuovo link simbolico con \textit{pathname} \param{newpath} +che fa riferimento ad \param{oldpath}. Si tenga presente che la funzione non +effettua nessun controllo sull'esistenza di un file di nome \param{oldpath}, +ma si limita ad inserire il \textit{pathname} nel link simbolico. Pertanto un +link simbolico può anche riferirsi ad un file che non esiste: in questo caso +si ha quello che viene chiamato un \textit{dangling link}, letteralmente un +\textsl{link ciondolante}. + +Come accennato i link simbolici sono risolti automaticamente dal kernel +all'invocazione delle varie system call; in tab.~\ref{tab:file_symb_effect} si +è riportato un elenco dei comportamenti delle varie funzioni di libreria che +operano sui file nei confronti della risoluzione dei link simbolici, +specificando quali seguono il link simbolico e quali invece possono operare +direttamente sul suo contenuto. +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|c|c|} + \hline + \textbf{Funzione} & \textbf{Segue il link} & \textbf{Non segue il link} \\ + \hline + \hline + \func{access} & $\bullet$ & -- \\ + \func{chdir} & $\bullet$ & -- \\ + \func{chmod} & $\bullet$ & -- \\ + \func{chown} & -- & $\bullet$ \\ + \func{creat} & $\bullet$ & -- \\ + \func{exec} & $\bullet$ & -- \\ + \func{lchown} & $\bullet$ & -- \\ + \func{link}\footnotemark & -- & $\bullet$ \\ + \func{lstat} & -- & $\bullet$ \\ + \func{mkdir} & $\bullet$ & -- \\ + \func{mkfifo} & $\bullet$ & -- \\ + \func{mknod} & $\bullet$ & -- \\ + \func{open} & $\bullet$ & -- \\ + \func{opendir} & $\bullet$ & -- \\ + \func{pathconf} & $\bullet$ & -- \\ + \func{readlink} & -- & $\bullet$ \\ + \func{remove} & -- & $\bullet$ \\ + \func{rename} & -- & $\bullet$ \\ + \func{stat} & $\bullet$ & -- \\ + \func{truncate} & $\bullet$ & -- \\ + \func{unlink} & -- & $\bullet$ \\ + \hline + \end{tabular} + \caption{Uso dei link simbolici da parte di alcune funzioni.} + \label{tab:file_symb_effect} +\end{table} + +\footnotetext{a partire dalla serie 2.0, e contrariamente a quanto indicato + dallo standard POSIX, si veda quanto detto in sez.~\ref{sec:file_link}.} + +Si noti che non si è specificato il comportamento delle funzioni che operano +con i file descriptor, in quanto la risoluzione del link simbolico viene in +genere effettuata dalla funzione che restituisce il file descriptor +(normalmente la \func{open}, vedi sez.~\ref{sec:file_open}) e tutte le +operazioni seguenti fanno riferimento solo a quest'ultimo. + +Dato che, come indicato in tab.~\ref{tab:file_symb_effect}, funzioni come la +\func{open} seguono i link simbolici, occorrono funzioni apposite per accedere +alle informazioni del link invece che a quelle del file a cui esso fa +riferimento. Quando si vuole leggere il contenuto di un link simbolico si usa +la funzione \funcd{readlink}, il cui prototipo è: +\begin{prototype}{unistd.h} +{int readlink(const char *path, char *buff, size\_t size)} + Legge il contenuto del link simbolico indicato da \param{path} nel buffer + \param{buff} di dimensione \param{size}. + + \bodydesc{La funzione restituisce il numero di caratteri letti dentro + \param{buff} o -1 per un errore, nel qual caso la variabile + \var{errno} assumerà i valori: + \begin{errlist} + \item[\errcode{EINVAL}] \param{path} non è un link simbolico o \param{size} + non è positiva. + \end{errlist} + ed inoltre \errval{ENOTDIR}, \errval{ENAMETOOLONG}, \errval{ENOENT}, + \errval{EACCES}, \errval{ELOOP}, \errval{EIO}, \errval{EFAULT} e + \errval{ENOMEM}.} +\end{prototype} + +La funzione apre il link simbolico, ne legge il contenuto, lo scrive nel +buffer, e lo richiude. Si tenga presente che la funzione non termina la +stringa con un carattere nullo e la tronca alla dimensione specificata da +\param{size} per evitare di sovrascrivere oltre le dimensioni del buffer. + +\begin{figure}[htb] + \centering + \includegraphics[width=8.5cm]{img/link_loop} + \caption{Esempio di loop nel filesystem creato con un link simbolico.} + \label{fig:file_link_loop} +\end{figure} + +Un caso comune che si può avere con i link simbolici è la creazione dei +cosiddetti \textit{loop}. La situazione è illustrata in +fig.~\ref{fig:file_link_loop}, che riporta la struttura della directory +\file{/boot}. Come si vede si è creato al suo interno un link simbolico che +punta di nuovo a \file{/boot}.\footnote{il loop mostrato in + fig.~\ref{fig:file_link_loop} è un usato per poter permettere a \cmd{grub} + (un bootloader in grado di leggere direttamente da vari filesystem il file + da lanciare come sistema operativo) di vedere i file contenuti nella + directory \file{/boot} con lo stesso \textit{pathname} con cui verrebbero + visti dal sistema operativo, anche se essi si trovano, come accade spesso, + su una partizione separata (che \cmd{grub}, all'avvio, vede come radice).} + +Questo può causare problemi per tutti quei programmi che effettuano la +scansione di una directory senza tener conto dei link simbolici, ad esempio se +lanciassimo un comando del tipo \code{grep -r linux *}, il loop nella +directory porterebbe il comando ad esaminare \file{/boot}, \file{/boot/boot}, +\file{/boot/boot/boot} e così via. + +Per questo motivo il kernel e le librerie prevedono che nella risoluzione di +un \textit{pathname} possano essere seguiti un numero limitato di link +simbolici, il cui valore limite è specificato dalla costante +\const{MAXSYMLINKS}. Qualora questo limite venga superato viene generato un +errore ed \var{errno} viene impostata al valore \errcode{ELOOP}. + +Un punto da tenere sempre presente è che, come abbiamo accennato, un link +simbolico può fare riferimento anche ad un file che non esiste; ad esempio +possiamo creare un file temporaneo nella nostra directory con un link del +tipo: +\begin{verbatim} +$ ln -s /tmp/tmp_file temporaneo +\end{verbatim}%$ +anche se \file{/tmp/tmp\_file} non esiste. Questo può generare confusione, in +quanto aprendo in scrittura \file{temporaneo} verrà creato +\file{/tmp/tmp\_file} e scritto; ma accedendo in sola lettura a +\file{temporaneo}, ad esempio con \cmd{cat}, otterremmo: +\begin{verbatim} +$ cat temporaneo +cat: temporaneo: No such file or directory +\end{verbatim}%$ +con un errore che può sembrare sbagliato, dato che un'ispezione con \cmd{ls} +ci mostrerebbe invece l'esistenza di \file{temporaneo}. + + +\subsection{La creazione e la cancellazione delle directory} +\label{sec:file_dir_creat_rem} + +Benché in sostanza le directory non siano altro che dei file contenenti +elenchi di nomi ed \itindex{inode} \textit{inode}, non è possibile trattarle +come file ordinari e devono essere create direttamente dal kernel attraverso +una opportuna system call.\footnote{questo è quello che permette anche, + attraverso l'uso del VFS, l'utilizzo di diversi formati per la gestione dei + suddetti elenchi, dalle semplici liste a strutture complesse come alberi + binari, hash, ecc. che consentono una ricerca veloce quando il numero di + file è molto grande.} La funzione usata per creare una directory è +\funcd{mkdir}, ed il suo prototipo è: +\begin{functions} + \headdecl{sys/stat.h} + \headdecl{sys/types.h} + \funcdecl{int mkdir(const char *dirname, mode\_t mode)} + + Crea una nuova directory. + + \bodydesc{La funzione restituisce zero in caso di successo e -1 per un + errore, nel qual caso \var{errno} assumerà i valori: + \begin{errlist} + \item[\errcode{EEXIST}] un file (o una directory) con quel nome esiste di + già. + \item[\errcode{EACCES}] non c'è il permesso di scrittura per la directory in + cui si vuole inserire la nuova directory. + \item[\errcode{EMLINK}] la directory in cui si vuole creare la nuova + directory contiene troppi file; sotto Linux questo normalmente non avviene + perché il filesystem standard consente la creazione di un numero di file + maggiore di quelli che possono essere contenuti nel disco, ma potendo + avere a che fare anche con filesystem di altri sistemi questo errore può + presentarsi. + \item[\errcode{ENOSPC}] non c'è abbastanza spazio sul file system per creare + la nuova directory o si è esaurita la quota disco dell'utente. + \end{errlist} + ed inoltre anche \errval{EPERM}, \errval{EFAULT}, \errval{ENAMETOOLONG}, + \errval{ENOENT}, \errval{ENOTDIR}, \errval{ENOMEM}, \errval{ELOOP}, + \errval{EROFS}.} +\end{functions} + +La funzione crea una nuova directory vuota, che contiene cioè solo le due voci +standard presenti in ogni directory (cioè ``\file{.}'' e ``\file{..}''), con +il nome indicato dall'argomento \param{dirname}. Il nome può essere indicato +sia come \itindsub{pathname}{assoluto} \textit{pathname} assoluto che come +\itindsub{pathname}{relativo} \textit{pathname} relativo. + +I permessi di accesso (vedi sez.~\ref{sec:file_access_control}) con cui la +directory viene creata sono specificati dall'argomento \param{mode}, i cui +possibili valori sono riportati in tab.~\ref{tab:file_permission_const}; si +tenga presente che questi sono modificati dalla maschera di creazione dei file +(si veda sez.~\ref{sec:file_perm_management}). La titolarità della nuova +directory è impostata secondo quanto riportato in +sez.~\ref{sec:file_ownership_management}. + +La funzione che permette la cancellazione di una directory è invece +\funcd{rmdir}, ed il suo prototipo è: +\begin{prototype}{sys/stat.h}{int rmdir(const char *dirname)} + Cancella una directory. + + \bodydesc{La funzione restituisce zero in caso di successo e -1 per un + errore, nel qual caso \var{errno} assumerà i valori: + \begin{errlist} + \item[\errcode{EPERM}] il filesystem non supporta la cancellazione di + directory, oppure la directory che contiene \param{dirname} ha lo + \itindex{sticky~bit} \textit{sticky bit} impostato e l'\ids{UID} effettivo + del processo non corrisponde al proprietario della directory. + \item[\errcode{EACCES}] non c'è il permesso di scrittura per la directory + che contiene la directory che si vuole cancellare, o non c'è il permesso + di attraversare (esecuzione) una delle directory specificate in + \param{dirname}. + \item[\errcode{EBUSY}] la directory specificata è la + \index{directory~di~lavoro} directory di lavoro o la radice di qualche + processo. + \item[\errcode{ENOTEMPTY}] la directory non è vuota. + \end{errlist} + ed inoltre anche \errval{EFAULT}, \errval{ENAMETOOLONG}, \errval{ENOENT}, + \errval{ENOTDIR}, \errval{ENOMEM}, \errval{ELOOP}, \errval{EROFS}.} +\end{prototype} + +La funzione cancella la directory \param{dirname}, che deve essere vuota (la +directory deve cioè contenere soltanto le due voci standard ``\file{.}'' e +``\file{..}''). Il nome può essere indicato con il \textit{pathname} assoluto +o relativo. + +La modalità con cui avviene la cancellazione è analoga a quella di +\func{unlink}: fintanto che il numero di link \itindex{inode} +all'\textit{inode} della directory non diventa nullo e nessun processo ha la +directory aperta lo spazio occupato su disco non viene rilasciato. Se un +processo ha la directory aperta la funzione rimuove il link \itindex{inode} +all'\textit{inode} e nel caso sia l'ultimo, pure le voci standard ``\file{.}'' +e ``\file{..}'', a questo punto il kernel non consentirà di creare più nuovi +file nella directory. + + +\subsection{La creazione di file speciali} +\label{sec:file_mknod} + +\index{file!di~dispositivo|(} + +Finora abbiamo parlato esclusivamente di file, directory e link simbolici; in +sez.~\ref{sec:file_file_types} abbiamo visto però che il sistema prevede pure +degli altri tipi di file speciali, come i file di dispositivo, le fifo ed i +socket (questi ultimi sono un caso a parte, essendo associati anche alla +comunicazione via rete, per cui ci saranno trattati in dettaglio a partire da +cap.~\ref{cha:socket_intro}). + +La manipolazione delle caratteristiche di questi diversi tipi di file e la +loro cancellazione può essere effettuata con le stesse funzioni che operano +sui file regolari; ma quando li si devono creare sono necessarie delle +funzioni apposite. La prima di queste funzioni è \funcd{mknod}, il cui +prototipo è: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{sys/stat.h} + \headdecl{fcntl.h} + \headdecl{unistd.h} + \funcdecl{int mknod(const char *pathname, mode\_t mode, dev\_t dev)} + + Crea un \textit{inode} del tipo specificato sul filesystem. + + \bodydesc{La funzione restituisce zero in caso di successo e -1 per un + errore, nel qual caso \var{errno} assumerà i valori: + \begin{errlist} + \item[\errcode{EPERM}] non si hanno privilegi sufficienti a creare + l'\texttt{inode}, o il filesystem su cui si è cercato di + creare \param{pathname} non supporta l'operazione. + \item[\errcode{EINVAL}] il valore di \param{mode} non indica un file, una + fifo, un socket o un dispositivo. + \item[\errcode{EEXIST}] \param{pathname} esiste già o è un link simbolico. + \end{errlist} + ed inoltre anche \errval{EFAULT}, \errval{EACCES}, \errval{ENAMETOOLONG}, + \errval{ENOENT}, \errval{ENOTDIR}, \errval{ENOMEM}, \errval{ELOOP}, + \errval{ENOSPC}, \errval{EROFS}.} +\end{functions} + +La funzione, come suggerisce il nome, permette di creare un ``\textsl{nodo}'' +sul filesystem, e viene in genere utilizzata per creare i file di dispositivo, +ma si può usare anche per creare file regolari. L'argomento +\param{mode} specifica sia il tipo di file che si vuole creare che i relativi +permessi, secondo i valori riportati in tab.~\ref{tab:file_mode_flags}, che +vanno combinati con un OR binario. I permessi sono comunque modificati nella +maniera usuale dal valore di \itindex{umask} \textit{umask} (si veda +sez.~\ref{sec:file_perm_management}). + +Per il tipo di file può essere specificato solo uno fra i seguenti valori: +\const{S\_IFREG} per un file regolare (che sarà creato vuoto), +\const{S\_IFBLK} per un dispositivo a blocchi, \const{S\_IFCHR} per un +dispositivo a caratteri, \const{S\_IFSOCK} per un socket e \const{S\_IFIFO} +per una fifo;\footnote{con Linux la funzione non può essere usata per creare + directory o link simbolici, si dovranno usare le funzioni \func{mkdir} e + \func{symlink} a questo dedicate.} un valore diverso comporterà l'errore +\errcode{EINVAL}. + +Qualora si sia specificato in \param{mode} un file di dispositivo (vale a dire +o \const{S\_IFBLK} o \const{S\_IFCHR}), il valore di \param{dev} dovrà essere +usato per indicare a quale dispositivo si fa riferimento, altrimenti il suo +valore verrà ignorato. Solo l'amministratore può creare un file di +dispositivo usando questa funzione (il processo deve avere la +\itindex{capabilities} \textit{capability} \const{CAP\_MKNOD}), ma in +Linux\footnote{questo è un comportamento specifico di Linux, la funzione non è + prevista dallo standard POSIX.1 originale, mentre è presente in SVr4 e + 4.4BSD, ma esistono differenze nei comportamenti e nei codici di errore, + tanto che questa è stata introdotta in POSIX.1-2001 con una nota che la + definisce portabile solo quando viene usata per creare delle fifo, ma + comunque deprecata essendo utilizzabile a tale scopo la specifica + \func{mkfifo}.} l'uso per la creazione di un file ordinario, di una fifo o +di un socket è consentito anche agli utenti normali. + +I nuovi \itindex{inode} \textit{inode} creati con \func{mknod} apparterranno +al proprietario e al gruppo del processo che li ha creati, a meno che non si +sia attivato il bit \acr{sgid} per la directory o sia stata attivata la +semantica BSD per il filesystem (si veda +sez.~\ref{sec:file_ownership_management}) in cui si va a creare +\itindex{inode} l'\textit{inode}. + +Nella creazione di un file di dispositivo occorre poi specificare +correttamente il valore di \param{dev}; questo infatti è di tipo +\type{dev\_t}, che è un tipo primitivo (vedi +tab.~\ref{tab:intro_primitive_types}) riservato per indicare un +\textsl{numero} di dispositivo; il kernel infatti identifica ciascun +dispositivo con un valore numerico. Originariamente questo era un intero a 16 +bit diviso in due parti di 8 bit chiamate rispettivamente +\itindex{major~number} \textit{major number} e \itindex{minor~number} +\textit{minor number}, che sono poi i due numeri mostrati dal comando +\texttt{ls -l} al posto della dimensione quando lo si esegue su un file di +dispositivo. + +Il \itindex{major~number} \textit{major number} identifica una classe di +dispositivi (ad esempio la seriale, o i dischi IDE) e serve in sostanza per +indicare al kernel quale è il modulo che gestisce quella classe di +dispositivi; per identificare uno specifico dispositivo di quella classe (ad +esempio una singola porta seriale, o una partizione di un disco) si usa invece +il \itindex{minor~number} \textit{minor number}. L'elenco aggiornato di questi +numeri con le relative corrispondenze ai vari dispositivi può essere trovato +nel file \texttt{Documentation/devices.txt} allegato alla documentazione dei +sorgenti del kernel. + +Data la crescita nel numero di dispositivi supportati, ben presto il limite +massimo di 256 si è rivelato troppo basso, e nel passaggio dai kernel della +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 \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 \headfile{sys/sysmacros.h}, che viene +automaticamente incluso quando si include \headfile{sys/types.h}; si possono +pertanto ottenere i valori del \itindex{major~number} \textit{major number} e +\itindex{minor~number} \textit{minor number} di un dispositivo rispettivamente +con le macro \macro{major} e \macro{minor}: +\begin{functions} + \headdecl{sys/types.h} + \funcdecl{int \macro{major}(dev\_t dev)} + Restituisce il \itindex{major~number} \textit{major number} del dispositivo + \param{dev}. + + \funcdecl{int \macro{minor}(dev\_t dev)} + Restituisce il \itindex{minor~number} \textit{minor number} del dispositivo + \param{dev}. +\end{functions} +\noindent mentre una volta che siano noti \itindex{major~number} \textit{major + number} e \itindex{minor~number} \textit{minor number} si potrà costruire il +relativo identificativo con la macro \macro{makedev}: +\begin{functions} + \headdecl{sys/types.h} + \funcdecl{dev\_t \macro{minor}(int major, int minor)} + + Restituisce l'identificativo di un dispositivo dati \itindex{major~number} + \textit{major number} e \itindex{minor~number} \textit{minor number}. +\end{functions} + +\index{file!di~dispositivo|)} + +Infine con lo standard POSIX.1-2001 è stata introdotta una funzione specifica +per creare una fifo (tratteremo le fifo in in sez.~\ref{sec:ipc_named_pipe}); +la funzione è \funcd{mkfifo} ed il suo prototipo è: +\begin{functions} + \headdecl{sys/types.h} \headdecl{sys/stat.h} + + \funcdecl{int mkfifo(const char *pathname, mode\_t mode)} + + Crea una fifo. + + \bodydesc{La funzione restituisce zero in caso di successo e -1 per un + errore, nel qual caso \var{errno} assumerà i valori \errval{EACCES}, + \errval{EEXIST}, \errval{ENAMETOOLONG}, \errval{ENOENT}, \errval{ENOSPC}, + \errval{ENOTDIR} e \errval{EROFS}.} +\end{functions} + +La funzione crea la fifo \param{pathname} con i permessi \param{mode}. Come +per \func{mknod} il file \param{pathname} non deve esistere (neanche come link +simbolico); al solito i permessi specificati da \param{mode} vengono +modificati dal valore di \itindex{umask} \textit{umask}. + + + +\subsection{Accesso alle directory} +\label{sec:file_dir_read} + +Benché le directory alla fine non siano altro che dei file che contengono +delle liste di nomi ed \itindex{inode} \textit{inode}, per il ruolo che +rivestono nella struttura del sistema, non possono essere trattate come dei +normali file di dati. Ad esempio, onde evitare inconsistenze all'interno del +filesystem, solo il kernel può scrivere il contenuto di una directory, e non +può essere un processo a inserirvi direttamente delle voci con le usuali +funzioni di scrittura. + +Ma se la scrittura e l'aggiornamento dei dati delle directory è compito del +kernel, sono molte le situazioni in cui i processi necessitano di poterne +leggere il contenuto. Benché questo possa essere fatto direttamente (vedremo +in sez.~\ref{sec:file_open} che è possibile aprire una directory come se fosse +un file, anche se solo in sola lettura) in generale il formato con cui esse +sono scritte può dipendere dal tipo di filesystem, tanto che, come riportato +in tab.~\ref{tab:file_file_operations}, il VFS del kernel prevede una apposita +funzione per la lettura delle directory. + +Tutto questo si riflette nello standard POSIX\footnote{le funzioni erano + presenti in SVr4 e 4.3BSD, la loro specifica è riportata in POSIX.1-2001.} +che ha introdotto una apposita interfaccia per la lettura delle directory, +basata sui cosiddetti \textit{directory stream} (chiamati così per l'analogia +con i file stream dell'interfaccia standard ANSI C di +cap.~\ref{cha:files_std_interface}). La prima funzione di questa interfaccia è +\funcd{opendir}, il cui prototipo è: +\begin{functions} + \headdecl{sys/types.h} \headdecl{dirent.h} + + \funcdecl{DIR * opendir(const char *dirname)} + + Apre un \textit{directory stream}. + + \bodydesc{La funzione restituisce un puntatore al \textit{directory stream} + in caso di successo e \val{NULL} per un errore, nel qual caso \var{errno} + assumerà i valori \errval{EACCES}, \errval{EMFILE}, \errval{ENFILE}, + \errval{ENOENT}, \errval{ENOMEM} e \errval{ENOTDIR}.} +\end{functions} + +La funzione apre un \textit{directory stream} per la directory +\param{dirname}, ritornando il puntatore ad un oggetto di tipo \type{DIR} (che +è il \index{tipo!opaco} tipo opaco usato dalle librerie per gestire i +\textit{directory stream}) da usare per tutte le operazioni successive, la +funzione inoltre posiziona lo stream sulla prima voce contenuta nella +directory. + +Si tenga presente che comunque la funzione opera associando il +\textit{directory stream} ad un opportuno file descriptor sottostante, sul +quale vengono compiute le operazioni. Questo viene sempre aperto impostando il +flag di \itindex{close-on-exec} \textit{close-on-exec}, così da evitare che +resti aperto in caso di esecuzione di un altro programma. + +Nel caso in cui sia necessario conoscere il \textit{file descriptor} associato +ad un \textit{directory stream} si può usare la funzione +\funcd{dirfd},\footnote{questa funzione è una estensione introdotta con BSD + 4.3-Reno ed è presente in Linux con le libc5 (a partire dalla versione + 5.1.2) e con le \acr{glibc} ma non presente in POSIX fino alla revisione + POSIX.1-2008, per questo per poterla utilizzare fino alla versione 2.10 + delle \acr{glibc} era necessario definire le macro \macro{\_BSD\_SOURCE} o + \macro{\_SVID\_SOURCE}, dalla versione 2.10 si possono usare anche + \texttt{\macro{\_POSIX\_C\_SOURCE} >= 200809L} o + \texttt{\macro{\_XOPEN\_SOURCE} >= 700}.} il cui prototipo è: +\begin{functions} + \headdecl{sys/types.h} \headdecl{dirent.h} + + \funcdecl{int dirfd(DIR * dir)} + + Restituisce il file descriptor associato ad un \textit{directory stream}. + + \bodydesc{La funzione restituisce il file descriptor (un valore positivo) in + caso di successo e -1 in caso di errore.} +\end{functions} + +La funzione restituisce il file descriptor associato al \textit{directory + stream} \param{dir}. Di solito si utilizza questa funzione in abbinamento a +funzioni che operano sui file descriptor, ad esempio si potrà usare +\func{fstat} per ottenere le proprietà della directory, o \func{fchdir} per +spostare su di essa la \index{directory~di~lavoro} directory di lavoro (vedi +sez.~\ref{sec:file_work_dir}). + +Viceversa se si è aperto un file descriptor corrispondente ad una directory è +possibile associarvi un \textit{directory stream} con la funzione +\funcd{fdopendir},\footnote{questa funzione è però disponibile solo a partire + dalla versione 2.4 delle \acr{glibc}, ed è stata introdotta nello standard + POSIX solo a partire dalla revisione POSIX.1-2008, prima della versione 2.10 + delle \acr{glibc} per poterla utilizzare era necessario definire la macro + \macro{\_GNU\_SOURCE}, dalla versione 2.10 si possono usare anche + \texttt{\macro{\_POSIX\_C\_SOURCE} >= 200809L} o \texttt{\_XOPEN\_SOURCE >= + 700} .} il cui prototipo è: +\begin{functions} + \headdecl{sys/types.h} \headdecl{dirent.h} + + \funcdecl{DIR * fdopendir(int fd)} + + Associa un \textit{directory stream} al file descriptor \param{fd}. + + \bodydesc{La funzione restituisce un puntatore al \textit{directory stream} + in caso di successo e \val{NULL} per un errore, nel qual caso \var{errno} + assumerà il valore \errval{EBADF}.} +\end{functions} + +La funzione è identica a \func{opendir}, ma ritorna un \textit{directory + stream} facendo riferimento ad un file descriptor \param{fd} che deve essere +stato aperto in precedenza; la funzione darà un errore qualora questo non +corrisponda ad una directory. L'uso di questa funzione permette di rispondere +agli stessi requisiti delle funzioni ``\textit{at}'' che vedremo in +sez.~\ref{sec:file_openat}. + +Una volta utilizzata il file descriptor verrà usato internamente dalle +funzioni che operano sul \textit{directory stream} e non dovrà essere più +utilizzato all'interno del proprio programma; in particolare dovrà essere +chiuso con \func{closedir} e non direttamente. Si tenga presente inoltre che +\func{fdopendir} non modifica lo stato di un eventuale flag di +\itindex{close-on-exec} \textit{close-on-exec}, che pertanto dovrà essere +impostato esplicitamente in fase di apertura del file descriptor. + +Una volta che si sia aperto un \textit{directory stream} la lettura del +contenuto della directory viene effettuata attraverso la funzione +\funcd{readdir}; il suo prototipo è: +\begin{functions} + \headdecl{sys/types.h} \headdecl{dirent.h} + + \funcdecl{struct dirent *readdir(DIR *dir)} + + Legge una voce dal \textit{directory stream}. + + \bodydesc{La funzione restituisce il puntatore alla struttura contenente i + dati in caso di successo e \val{NULL} altrimenti, in caso di + \textit{directory stream} non valido \var{errno} assumerà il valore + \errval{EBADF}, il valore \val{NULL} viene restituito anche quando si + raggiunge la fine dello stream.} +\end{functions} + +La funzione legge la voce corrente nella directory, posizionandosi sulla voce +successiva. Pertanto se si vuole leggere l'intero contenuto di una directory +occorrerà ripetere l'esecuzione della funzione fintanto che non si siano +esaurite tutte le voci in essa presenti. + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{\textwidth} + \includestruct{listati/dirent.c} + \end{minipage} + \normalsize + \caption{La struttura \structd{dirent} per la lettura delle informazioni dei + file.} + \label{fig:file_dirent_struct} +\end{figure} + +I dati vengono memorizzati in una struttura \struct{dirent}, la cui +definizione è riportata in fig.~\ref{fig:file_dirent_struct}.\footnote{la + definizione è quella usata da Linux, che si trova nel file + \file{/usr/include/bits/dirent.h}, essa non contempla la presenza del campo + \var{d\_namlen} che indica la lunghezza del nome del file.} La funzione +restituisce il puntatore alla struttura; si tenga presente però che +quest'ultima è allocata staticamente, per cui viene sovrascritta tutte le +volte che si ripete la lettura di una voce sullo stesso \textit{directory + stream}. + +Di questa funzione esiste anche una versione \index{funzioni!rientranti} +rientrante, \funcd{readdir\_r},\footnote{per usarla è necessario definire una + qualunque delle macro \texttt{\macro{\_POSIX\_C\_SOURCE} >= 1}, + \macro{\_XOPEN\_SOURCE}, \macro{\_BSD\_SOURCE}, \macro{\_SVID\_SOURCE}, + \macro{\_POSIX\_SOURCE}.} che non usa una struttura allocata staticamente, e +può essere utilizzata anche con i \itindex{thread} \textit{thread}, il suo +prototipo è: +\begin{functions} + \headdecl{sys/types.h} \headdecl{dirent.h} + + \funcdecl{int readdir\_r(DIR *dir, struct dirent *entry, + struct dirent **result)} + + Legge una voce dal \textit{directory stream}. + + \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di + errore, gli errori sono gli stessi di \func{readdir}.} +\end{functions} + +La funzione restituisce in \param{result} (come +\itindex{value~result~argument} \textit{value result argument}) l'indirizzo +dove sono stati salvati i dati, che di norma corrisponde a quello della +struttura precedentemente allocata e specificata dall'argomento \param{entry}, +anche se non è assicurato che la funzione usi lo spazio fornito dall'utente. + +I vari campi di \struct{dirent} contengono le informazioni relative alle voci +presenti nella directory; sia BSD che SVr4 prevedono che siano sempre presenti +il campo \var{d\_name},\footnote{lo standard POSIX prevede invece solo la + presenza del campo \var{d\_fileno}, identico \var{d\_ino}, che in Linux è + definito come alias di quest'ultimo; il campo \var{d\_name} è considerato + dipendente dall'implementazione.} che contiene il nome del file nella forma +di una stringa terminata da uno zero,\footnote{lo standard POSIX non specifica + una lunghezza, ma solo un limite \const{NAME\_MAX}; in SVr4 la lunghezza del + campo è definita come \code{NAME\_MAX+1} che di norma porta al valore di 256 + byte usato anche in Linux.} ed il campo \var{d\_ino}, che contiene il numero +di \textit{inode} cui il file è associato e corrisponde al campo \var{st\_ino} +di \struct{stat}. + +La presenza di ulteriori campi opzionali oltre i due citati è segnalata dalla +definizione di altrettante macro nella forma \code{\_DIRENT\_HAVE\_D\_XXX} +dove \code{XXX} è il nome del relativo campo; nel caso di Linux sono pertanto +definite le macro \macro{\_DIRENT\_HAVE\_D\_TYPE}, +\macro{\_DIRENT\_HAVE\_D\_OFF} e \macro{\_DIRENT\_HAVE\_D\_RECLEN}, mentre non +è definita la macro \macro{\_DIRENT\_HAVE\_D\_NAMLEN}. + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|l|} + \hline + \textbf{Valore} & \textbf{Tipo di file} \\ + \hline + \hline + \const{DT\_UNKNOWN} & Tipo sconosciuto.\\ + \const{DT\_REG} & File normale.\\ + \const{DT\_DIR} & Directory.\\ + \const{DT\_LNK} & Link simbolico.\\ + \const{DT\_FIFO} & Fifo.\\ + \const{DT\_SOCK} & Socket.\\ + \const{DT\_CHR} & Dispositivo a caratteri.\\ + \const{DT\_BLK} & Dispositivo a blocchi.\\ + \hline + \end{tabular} + \caption{Costanti che indicano i vari tipi di file nel campo \var{d\_type} + della struttura \struct{dirent}.} + \label{tab:file_dtype_macro} +\end{table} + +Per quanto riguarda il significato dei campi opzionali, il campo \var{d\_type} +indica il tipo di file (se fifo, directory, link simbolico, ecc.), e consente +di evitare una successiva chiamata a \func{lstat} per determinarlo. I suoi +possibili valori sono riportati in tab.~\ref{tab:file_dtype_macro}. Si tenga +presente che questo valore è disponibile solo per i filesystem che ne +supportano la restituzione (fra questi i più noti sono \textsl{btrfs}, +\textsl{ext2}, \textsl{ext3}, e \textsl{ext4}), per gli altri si otterrà +sempre il valore \const{DT\_UNKNOWN}.\footnote{inoltre fino alla versione 2.1 + delle \acr{glibc}, pur essendo il campo \var{d\_type} presente, il suo uso + non era implementato, e veniva restituito comunque il valore + \const{DT\_UNKNOWN}.} + +Per la conversione da e verso l'analogo valore mantenuto dentro il campo +\var{st\_mode} di \struct{stat} sono definite anche due macro di conversione, +\macro{IFTODT} e \macro{DTTOIF}: +\begin{functions} + \funcdecl{int IFTODT(mode\_t MODE)} Converte il tipo di file dal formato di + \var{st\_mode} a quello di \var{d\_type}. + + \funcdecl{mode\_t DTTOIF(int DTYPE)} Converte il tipo di file dal formato di + \var{d\_type} a quello di \var{st\_mode}. +\end{functions} + +Il campo \var{d\_off} contiene invece la posizione della voce successiva della +directory, mentre il campo \var{d\_reclen} la lunghezza totale della voce +letta. Con questi due campi diventa possibile, determinando la posizione delle +varie voci, spostarsi all'interno dello stream usando la funzione +\funcd{seekdir},\footnote{sia questa funzione che \func{telldir}, sono + estensioni prese da BSD, ed introdotte nello standard POSIX solo a partire + dalla revisione POSIX.1-2001, per poterle utilizzare deve essere definita + una delle macro \macro{\_XOPEN\_SOURCE}, \macro{\_BSD\_SOURCE} o + \macro{\_SVID\_SOURCE}.} il cui prototipo è: +\begin{prototype}{dirent.h}{void seekdir(DIR *dir, off\_t offset)} + Cambia la posizione all'interno di un \textit{directory stream}. +\end{prototype} + +La funzione non ritorna nulla e non segnala errori, è però necessario che il +valore dell'argomento \param{offset} sia valido per lo stream \param{dir}; +esso pertanto deve essere stato ottenuto o dal valore di \var{d\_off} di +\struct{dirent} o dal valore restituito dalla funzione \funcd{telldir}, che +legge la posizione corrente; il prototipo di quest'ultima è:\footnote{prima + delle \acr{glibc} 2.1.1 la funzione restituiva un valore di tipo + \type{off\_t}, sostituito a partire dalla versione 2.1.2 da \ctyp{long} per + conformità a POSIX.1-2001.} +\begin{prototype}{dirent.h}{long telldir(DIR *dir)} + Ritorna la posizione corrente in un \textit{directory stream}. + + \bodydesc{La funzione restituisce la posizione corrente nello stream (un + numero positivo) in caso di successo, e -1 altrimenti, nel qual caso + \var{errno} assume solo il valore di \errval{EBADF}, corrispondente ad un + valore errato per \param{dir}.} +\end{prototype} + +La sola funzione di posizionamento nello stream prevista originariamente dallo +standard POSIX è \funcd{rewinddir}, che riporta la posizione a quella +iniziale; il suo prototipo è: +\begin{functions} + \headdecl{sys/types.h} \headdecl{dirent.h} + + \funcdecl{void rewinddir(DIR *dir)} + + Si posiziona all'inizio di un \textit{directory stream}. +\end{functions} + +Una volta completate le operazioni si può chiudere il \textit{directory + stream}, ed il file descriptor ad esso associato, con la funzione +\funcd{closedir}, il cui prototipo è: +\begin{functions} + \headdecl{sys/types.h} \headdecl{dirent.h} + + \funcdecl{int closedir(DIR * dir)} + + Chiude un \textit{directory stream}. + + \bodydesc{La funzione restituisce 0 in caso di successo e -1 altrimenti, nel + qual caso \var{errno} assume il valore \errval{EBADF}.} +\end{functions} + +A parte queste funzioni di base in BSD 4.3 venne introdotta un'altra funzione +che permette di eseguire una scansione completa, con tanto di ricerca ed +ordinamento, del contenuto di una directory; la funzione è +\funcd{scandir}\footnote{in Linux questa funzione è stata introdotta fin dalle + \acr{libc4} e richiede siano definite le macro \macro{\_BSD\_SOURCE} o + \macro{\_SVID\_SOURCE}.} ed il suo prototipo è: +\begin{prototype}{dirent.h}{int scandir(const char *dir, + struct dirent ***namelist, int(*filter)(const struct dirent *), + int(*compar)(const struct dirent **, const struct dirent **))} + + Esegue una scansione di un \textit{directory stream}. + + \bodydesc{La funzione restituisce in caso di successo il numero di voci + trovate, e -1 altrimenti.} +\end{prototype} + +Al solito, per la presenza fra gli argomenti di due puntatori a funzione, il +prototipo non è molto comprensibile; queste funzioni però sono quelle che +controllano rispettivamente la selezione di una voce (quella passata con +l'argomento \param{filter}) e l'ordinamento di tutte le voci selezionate +(quella specificata dell'argomento \param{compar}). + +La funzione legge tutte le voci della directory indicata dall'argomento +\param{dir}, passando un puntatore a ciascuna di esse (una struttura +\struct{dirent}) come argomento della funzione di selezione specificata da +\param{filter}; se questa ritorna un valore diverso da zero il puntatore viene +inserito in un vettore che viene allocato dinamicamente con \func{malloc}. +Qualora si specifichi un valore \val{NULL} per l'argomento \param{filter} non +viene fatta nessuna selezione e si ottengono tutte le voci presenti. + +Le voci selezionate possono essere riordinate tramite \funcm{qsort}, le +modalità del riordinamento possono essere personalizzate usando la funzione +\param{compar} come criterio di ordinamento di \funcm{qsort}, la funzione +prende come argomenti le due strutture \struct{dirent} da confrontare +restituendo un valore positivo, nullo o negativo per indicarne l'ordinamento; +alla fine l'indirizzo della lista ordinata dei puntatori alle strutture +\struct{dirent} viene restituito nell'argomento +\param{namelist}.\footnote{la funzione alloca automaticamente la lista, e + restituisce, come \itindex{value~result~argument} \textit{value result + argument}, l'indirizzo della stessa; questo significa che \param{namelist} + deve essere dichiarato come \code{struct dirent **namelist} ed alla funzione + si deve passare il suo indirizzo.} + +Per l'ordinamento, vale a dire come valori possibili per l'argomento +\param{compar} sono disponibili due funzioni predefinite, \funcd{alphasort} e +\funcd{versionsort}, i cui prototipi sono: +\begin{functions} + \headdecl{dirent.h} + + \funcdecl{int alphasort(const void *a, const void *b)} + + \funcdecl{int versionsort(const void *a, const void *b)} + + Funzioni per l'ordinamento delle voci di \textit{directory stream}. + + \bodydesc{Le funzioni restituiscono un valore minore, uguale o maggiore di + zero qualora il primo argomento sia rispettivamente minore, uguale o + maggiore del secondo.} +\end{functions} + +La funzione \func{alphasort} deriva da BSD ed è presente in Linux fin dalle +\acr{libc4}\footnote{la versione delle \acr{libc4} e \acr{libc5} usa però come + argomenti dei puntatori a delle strutture \struct{dirent}; le glibc usano il + prototipo originario di BSD, mostrato anche nella definizione, che prevede + puntatori a \ctyp{void}.} e deve essere specificata come argomento +\param{compar} per ottenere un ordinamento alfabetico (secondo il valore del +campo \var{d\_name} delle varie voci). Le \acr{glibc} prevedono come +estensione\footnote{le glibc, a partire dalla versione 2.1, effettuano anche + l'ordinamento alfabetico tenendo conto delle varie localizzazioni, usando + \funcm{strcoll} al posto di \funcm{strcmp}.} anche \func{versionsort}, che +ordina i nomi tenendo conto del numero di versione (cioè qualcosa per cui +\texttt{file10} viene comunque dopo \texttt{file4}.) + +\begin{figure}[!htbp] + \footnotesize \centering + \begin{minipage}[c]{\codesamplewidth} + \includecodesample{listati/my_ls.c} + \end{minipage} + \caption{Esempio di codice per eseguire la lista dei file contenuti in una + directory.} + \label{fig:file_my_ls} +\end{figure} + +Un semplice esempio dell'uso di queste funzioni è riportato in +fig.~\ref{fig:file_my_ls}, dove si è riportata la sezione principale di un +programma che, usando la funzione di scansione illustrata in +fig.~\ref{fig:file_dirscan}, stampa i nomi dei file contenuti in una directory +e la relativa dimensione (in sostanza una versione semplificata del comando +\cmd{ls}). + +Il programma è estremamente semplice; in fig.~\ref{fig:file_my_ls} si è omessa +la parte di gestione delle opzioni (che prevede solo l'uso di una funzione per +la stampa della sintassi, anch'essa omessa) ma il codice completo potrà essere +trovato coi sorgenti allegati nel file \file{myls.c}. + +In sostanza tutto quello che fa il programma, dopo aver controllato +(\texttt{\small 12--15}) di avere almeno un argomento (che indicherà la +directory da esaminare) è chiamare (\texttt{\small 16}) la funzione +\func{DirScan} per eseguire la scansione, usando la funzione \code{do\_ls} +(\texttt{\small 22--29}) per fare tutto il lavoro. + +Quest'ultima si limita (\texttt{\small 26}) a chiamare \func{stat} sul file +indicato dalla directory entry passata come argomento (il cui nome è appunto +\var{direntry->d\_name}), memorizzando in una opportuna struttura \var{data} i +dati ad esso relativi, per poi provvedere (\texttt{\small 27}) a stampare il +nome del file e la dimensione riportata in \var{data}. + +Dato che la funzione verrà chiamata all'interno di \func{DirScan} per ogni +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}[!htbp] + \footnotesize \centering + \begin{minipage}[c]{\codesamplewidth} + \includecodesample{listati/DirScan.c} + \end{minipage} + \caption{Codice della funzione di scansione di una directory contenuta nel + file \file{DirScan.c}.} + \label{fig:file_dirscan} +\end{figure} + +Tutto il grosso del lavoro è svolto dalla funzione \func{DirScan}, riportata +in fig.~\ref{fig:file_dirscan}. La funzione è volutamente generica e permette +di eseguire una funzione, passata come secondo argomento, su tutte le voci di +una directory. La funzione inizia con l'aprire (\texttt{\small 18--22}) uno +stream sulla directory passata come primo argomento, stampando un messaggio in +caso di errore. + +Il passo successivo (\texttt{\small 23--24}) è cambiare +\index{directory~di~lavoro} directory di lavoro (vedi +sez.~\ref{sec:file_work_dir}), usando in sequenza le funzioni \func{dirfd} e +\func{fchdir} (in realtà si sarebbe potuto usare direttamente \func{chdir} su +\var{dirname}), in modo che durante il successivo ciclo (\texttt{\small + 26--30}) sulle singole voci dello stream ci si trovi all'interno della +directory.\footnote{questo è essenziale al funzionamento della funzione + \code{do\_ls}, e ad ogni funzione che debba usare il campo \var{d\_name}, in + quanto i nomi dei file memorizzati all'interno di una struttura + \struct{dirent} sono sempre relativi alla directory in questione, e senza + questo posizionamento non si sarebbe potuto usare \func{stat} per ottenere + le dimensioni.} + +Avendo usato lo stratagemma di fare eseguire tutte le manipolazioni necessarie +alla funzione passata come secondo argomento, il ciclo di scansione della +directory è molto semplice; si legge una voce alla volta (\texttt{\small 26}) +all'interno di una istruzione di \code{while} e fintanto che si riceve una +voce valida, cioè un puntatore diverso da \val{NULL}, si esegue +(\texttt{\small 27}) la funzione di elaborazione \var{compare} (che nel nostro +caso sarà \code{do\_ls}), ritornando con un codice di errore (\texttt{\small + 28}) qualora questa presenti una anomalia, identificata da un codice di +ritorno negativo. Una volta terminato il ciclo la funzione si conclude con la +chiusura (\texttt{\small 32}) dello stream\footnote{nel nostro caso, uscendo + subito dopo la chiamata, questo non servirebbe, in generale però + l'operazione è necessaria, dato che la funzione può essere invocata molte + volte all'interno dello stesso processo, per cui non chiudere i + \textit{directory stream} comporterebbe un consumo progressivo di risorse, + con conseguente rischio di esaurimento delle stesse.} e la restituzione +(\texttt{\small 32}) del codice di operazioni concluse con successo. + + +\subsection{La directory di lavoro} +\label{sec:file_work_dir} + +\index{directory~di~lavoro|(} + +Come accennato in sez.~\ref{sec:proc_fork} a ciascun processo è associata una +directory nel filesystem,\footnote{questa viene mantenuta all'interno dei dati + della sua \kstruct{task\_struct} (vedi fig.~\ref{fig:proc_task_struct}), più + precisamente nel campo \texttt{pwd} della sotto-struttura + \kstruct{fs\_struct}.} che è chiamata \textsl{directory corrente} o +\textsl{directory di lavoro} (in inglese \textit{current working directory}). +La directory di lavoro è quella da cui si parte quando un +\itindsub{pathname}{relativo} \textit{pathname} è espresso in forma relativa, +dove il ``\textsl{relativa}'' fa riferimento appunto a questa directory. + +Quando un utente effettua il login, questa directory viene impostata alla +\textit{home directory} del suo account. Il comando \cmd{cd} della shell +consente di cambiarla a piacere, spostandosi da una directory ad un'altra, il +comando \cmd{pwd} la stampa sul terminale. Siccome la directory corrente +resta la stessa quando viene creato un processo figlio (vedi +sez.~\ref{sec:proc_fork}), la directory corrente della shell diventa anche la +directory corrente di qualunque comando da essa lanciato. + +Dato che è il kernel che tiene traccia per ciascun processo \itindex{inode} +dell'\textit{inode} della directory di lavoro, per ottenerne il +\textit{pathname} occorre usare una apposita funzione di libreria, +\funcd{getcwd},\footnote{con Linux \func{getcwd} è una \textit{system call} + dalla versione 2.1.9, in precedenza il valore doveva essere ottenuto tramite + il filesystem \texttt{/proc} da \procfile{/proc/self/cwd}.} il cui prototipo +è: +\begin{prototype}{unistd.h}{char *getcwd(char *buffer, size\_t size)} + Legge il \textit{pathname} della directory di lavoro corrente. + + \bodydesc{La funzione restituisce il puntatore \param{buffer} se riesce, + \val{NULL} se fallisce, in quest'ultimo caso la variabile + \var{errno} è impostata con i seguenti codici di errore: + \begin{errlist} + \item[\errcode{EINVAL}] l'argomento \param{size} è zero e \param{buffer} non + è nullo. + \item[\errcode{ERANGE}] l'argomento \param{size} è più piccolo della + lunghezza del \textit{pathname}. + \item[\errcode{EACCES}] manca il permesso di lettura o di ricerca su uno dei + componenti del \textit{pathname} (cioè su una delle directory superiori + alla corrente). + \item[\errcode{ENOENT}] la directory di lavoro è stata eliminata. + \end{errlist}} +\end{prototype} + +La funzione restituisce il \textit{pathname} completo della directory di +lavoro corrente nella stringa puntata da \param{buffer}, che deve essere +precedentemente allocata, per una dimensione massima di \param{size}. Il +buffer deve essere sufficientemente largo da poter contenere il +\textit{pathname} completo più lo zero di terminazione della stringa. Qualora +esso ecceda le dimensioni specificate con \param{size} la funzione restituisce +un errore. + +Si può anche specificare un puntatore nullo come +\param{buffer},\footnote{questa è un'estensione allo standard POSIX.1, + supportata da Linux e dalla \acr{glibc}.} nel qual caso la stringa sarà +allocata automaticamente per una dimensione pari a \param{size} qualora questa +sia diversa da zero, o della lunghezza esatta del \textit{pathname} +altrimenti. In questo caso ci si deve ricordare di disallocare la stringa una +volta cessato il suo utilizzo. + +Di questa funzione esiste una versione \code{char *getwd(char *buffer)} fatta +per compatibilità all'indietro con BSD, che non consente di specificare la +dimensione del buffer; esso deve essere allocato in precedenza ed avere una +dimensione superiore a \const{PATH\_MAX} (di solito 256 byte, vedi +sez.~\ref{sec:sys_limits}); il problema è che in Linux non esiste una +dimensione superiore per un \textit{pathname}, per cui non è detto che il +buffer sia sufficiente a contenere il nome del file, e questa è la ragione +principale per cui questa funzione è deprecata. + +Un uso comune di \func{getcwd} è quello di salvare la directory di lavoro +iniziale per poi potervi tornare in un tempo successivo, un metodo alternativo +più veloce, se non si è a corto di file descriptor, è invece quello di aprire +la directory corrente (vale a dire ``\texttt{.}'') e tornarvi in seguito con +\func{fchdir}. + +Una seconda usata per ottenere la directory di lavoro è \code{char + *get\_current\_dir\_name(void)} che è sostanzialmente equivalente ad una +\code{getcwd(NULL, 0)}, con la sola differenza che essa ritorna il valore +della variabile di ambiente \envvar{PWD}, che essendo costruita dalla shell +può contenere un \textit{pathname} comprendente anche dei link +simbolici. Usando \func{getcwd} infatti, essendo il \textit{pathname} ricavato +risalendo all'indietro l'albero della directory, si perderebbe traccia di ogni +passaggio attraverso eventuali link simbolici. + +Per cambiare la directory di lavoro si può usare la funzione \funcd{chdir} +(equivalente del comando di shell \cmd{cd}) il cui nome sta appunto per +\textit{change directory}, il suo prototipo è: +\begin{prototype}{unistd.h}{int chdir(const char *pathname)} + Cambia la directory di lavoro in \param{pathname}. + + \bodydesc{La funzione restituisce 0 in caso di successo e -1 per un errore, + nel qual caso \var{errno} assumerà i valori: + \begin{errlist} + \item[\errcode{ENOTDIR}] non si è specificata una directory. + \item[\errcode{EACCES}] manca il permesso di ricerca su uno dei componenti + di \param{path}. + \end{errlist} + ed inoltre \errval{EFAULT}, \errval{ENAMETOOLONG}, \errval{ENOENT}, + \errval{ENOMEM}, \errval{ELOOP} e \errval{EIO}.} +\end{prototype} +\noindent ed ovviamente \param{pathname} deve indicare una directory per la +quale si hanno i permessi di accesso. + +Dato che anche le directory sono file, è possibile riferirsi ad esse anche +tramite il file descriptor, e non solo tramite il \textit{pathname}, per fare +questo si usa \funcd{fchdir}, il cui prototipo è: +\begin{prototype}{unistd.h}{int fchdir(int fd)} + Identica a \func{chdir}, ma usa il file descriptor \param{fd} invece del + \textit{pathname}. + + \bodydesc{La funzione restituisce zero in caso di successo e -1 per un + errore, in caso di errore \var{errno} assumerà i valori \errval{EBADF} o + \errval{EACCES}.} +\end{prototype} +\noindent anche in questo caso \param{fd} deve essere un file descriptor +valido che fa riferimento ad una directory. Inoltre l'unico errore di accesso +possibile (tutti gli altri sarebbero occorsi all'apertura di \param{fd}), è +quello in cui il processo non ha il permesso di accesso alla directory +specificata da \param{fd}. + +\index{directory~di~lavoro|)} + + +\subsection{I file temporanei} +\label{sec:file_temp_file} + +In molte occasioni è utile poter creare dei file temporanei; benché la cosa +sembri semplice, in realtà il problema è più sottile di quanto non appaia a +prima vista. Infatti anche se sembrerebbe banale generare un nome a caso e +creare il file dopo aver controllato che questo non esista, nel momento fra il +controllo e la creazione si ha giusto lo spazio per una possibile +\itindex{race~condition} \textit{race condition} (si ricordi quanto visto in +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; 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)} + 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} + +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, 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 + \headfile{stdio.h}.} + +Di questa funzione esiste una versione \index{funzioni!rientranti} rientrante, +\funcm{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)} + 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 + \errval{ENOMEM} qualora fallisca l'allocazione della stringa.} +\end{prototype} + +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 accessibile, la prima valida fra le seguenti: +\begin{itemize*} +\item La variabile di ambiente \envvar{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*} + +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 +avere creato, fra l'ottenimento del nome e l'apertura del file, un altro file +con lo stesso nome; per questo motivo quando si usa il nome ottenuto da una di +queste funzioni occorre sempre aprire il nuovo file in modalità di esclusione +(cioè con l'opzione \const{O\_EXCL} per i file descriptor o con il flag +\code{x} per gli stream) che fa fallire l'apertura in caso il file sia già +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)} + Restituisce un file temporaneo aperto in lettura/scrittura. + + \bodydesc{La funzione ritorna il puntatore allo stream associato al file + temporaneo in caso di successo e \val{NULL} in caso di errore, nel qual + caso \var{errno} assumerà i valori: + \begin{errlist} + \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale. + \item[\errcode{EEXIST}] non è stato possibile generare un nome univoco. + \end{errlist} + ed inoltre \errval{EFAULT}, \errval{EMFILE}, \errval{ENFILE}, + \errval{ENOSPC}, \errval{EROFS} e \errval{EACCES}.} +\end{prototype} + +La funzione restituisce direttamente uno stream già aperto (in modalità +\code{r+b}, si veda sez.~\ref{sec:file_fopen}) e pronto per l'uso, che viene +automaticamente cancellato alla sua chiusura o all'uscita dal programma. Lo +standard non specifica in quale directory verrà aperto il file, ma le +\acr{glibc} prima tentano con \const{P\_tmpdir} e poi con \file{/tmp}. Questa +funzione è \index{funzioni!rientranti} rientrante e non soffre di problemi di +\itindex{race~condition} \textit{race condition}. + +Alcune versioni meno recenti di Unix non supportano queste funzioni; in questo +caso si possono usare le vecchie funzioni \funcd{mktemp} e \func{mkstemp} che +modificano una stringa di input che serve da modello e che deve essere +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 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} + assumerà i valori: + \begin{errlist} + \item[\errcode{EINVAL}] \param{template} non termina con \code{XXXXXX}. + \end{errlist}} +\end{prototype} + +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 +il valore usato per sostituire le \code{XXXXXX} viene formato con il \ids{PID} +del processo più una lettera, il che mette a disposizione solo 26 possibilità +diverse per il nome del file, e rende il nome temporaneo facile da indovinare. +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 un nome; il suo +prototipo è: +\begin{prototype}{stlib.h}{int mkstemp(char *template)} + Genera un file temporaneo. + + \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}. + \item[\errcode{EEXIST}] non è riuscita a creare un file temporaneo, il + contenuto di \param{template} è indefinito. + \end{errlist}} +\end{prototype} + +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 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 + \macro{\_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 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} + assumerà i valori: + \begin{errlist} + \item[\errcode{EINVAL}] \param{template} non termina con \code{XXXXXX}. + \end{errlist} + più gli altri eventuali codici di errore di \func{mkdir}.} +\end{prototype} + +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. + + +\section{La manipolazione delle caratteristiche dei file} +\label{sec:file_infos} + +Come spiegato in sez.~\ref{sec:file_filesystem} tutte le informazioni generali +relative alle caratteristiche di ciascun file, a partire dalle informazioni +relative al controllo di accesso, sono mantenute \itindex{inode} +nell'\textit{inode}. + +Vedremo in questa sezione come sia possibile leggere tutte queste informazioni +usando la funzione \func{stat}, che permette l'accesso a tutti i dati +memorizzati \itindex{inode} nell'\textit{inode}; esamineremo poi le varie +funzioni usate per manipolare tutte queste informazioni (eccetto quelle che +riguardano la gestione del controllo di accesso, trattate in in +sez.~\ref{sec:file_access_control}). + + +\subsection{La lettura delle caratteristiche dei file} +\label{sec:file_stat} + +La lettura delle informazioni relative ai file è fatta attraverso la famiglia +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)} + \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} + +La funzione \func{stat} legge le informazioni del file il cui +\textit{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 +\headfile{sys/stat.h} e in generale dipende dall'implementazione; la versione +usata da Linux è mostrata in fig.~\ref{fig:file_stat_struct}, così come +riportata dalla pagina di manuale di \func{stat}; in realtà la definizione +effettivamente usata nel kernel dipende dall'architettura e ha altri campi +riservati per estensioni come tempi dei file più precisi (vedi +sez.~\ref{sec:file_file_times}), o per il padding dei campi. + +\begin{figure}[!htb] + \footnotesize + \centering + \begin{minipage}[c]{\textwidth} + \includestruct{listati/stat.h} + \end{minipage} + \normalsize + \caption{La struttura \structd{stat} per la lettura delle informazioni dei + file.} + \label{fig:file_stat_struct} +\end{figure} + +Si noti come i vari membri della struttura siano specificati come tipi +primitivi del sistema (di quelli definiti in +tab.~\ref{tab:intro_primitive_types}, e dichiarati in \headfile{sys/types.h}). + +\subsection{I tipi di file} +\label{sec:file_types} + +Come riportato in tab.~\ref{tab:file_file_types} in Linux oltre ai file e alle +directory esistono altri oggetti che possono stare su un filesystem. Il tipo +di file è ritornato dalla funzione \func{stat} come maschera binaria nel campo +\var{st\_mode} (che contiene anche le informazioni relative ai permessi) di +una struttura \struct{stat}. + +Dato che il valore numerico può variare a seconda delle implementazioni, lo +standard POSIX definisce un insieme di macro per verificare il tipo di file, +queste vengono usate anche da Linux che supporta pure le estensioni allo +standard per i link simbolici e i socket definite da BSD; l'elenco completo +delle macro con cui è possibile estrarre l'informazione da \var{st\_mode} è +riportato in tab.~\ref{tab:file_type_macro}. +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|l|} + \hline + \textbf{Macro} & \textbf{Tipo del file} \\ + \hline + \hline + \macro{S\_ISREG}\texttt{(m)} & file normale.\\ + \macro{S\_ISDIR}\texttt{(m)} & directory.\\ + \macro{S\_ISCHR}\texttt{(m)} & dispositivo a caratteri.\\ + \macro{S\_ISBLK}\texttt{(m)} & dispositivo a blocchi.\\ + \macro{S\_ISFIFO}\texttt{(m)} & fifo.\\ + \macro{S\_ISLNK}\texttt{(m)} & link simbolico.\\ + \macro{S\_ISSOCK}\texttt{(m)} & socket.\\ + \hline + \end{tabular} + \caption{Macro per i tipi di file (definite in \headfile{sys/stat.h}).} + \label{tab:file_type_macro} +\end{table} + +Oltre alle macro di tab.~\ref{tab:file_type_macro} è possibile usare +direttamente il valore di \var{st\_mode} per ricavare il tipo di file +controllando direttamente i vari bit in esso memorizzati. Per questo sempre in +\headfile{sys/stat.h} sono definite le costanti numeriche riportate in +tab.~\ref{tab:file_mode_flags}. + +Il primo valore dell'elenco di tab.~\ref{tab:file_mode_flags} è la maschera +binaria che permette di estrarre i bit nei quali viene memorizzato il tipo di +file, i valori successivi sono le costanti corrispondenti ai singoli bit, e +possono essere usati per effettuare la selezione sul tipo di file voluto, con +un'opportuna combinazione. + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|c|l|} + \hline + \textbf{Flag} & \textbf{Valore} & \textbf{Significato} \\ + \hline + \hline + \const{S\_IFMT} & 0170000 & Maschera per i bit del tipo di file.\\ + \const{S\_IFSOCK} & 0140000 & Socket.\\ + \const{S\_IFLNK} & 0120000 & Link simbolico.\\ + \const{S\_IFREG} & 0100000 & File regolare.\\ + \const{S\_IFBLK} & 0060000 & Dispositivo a blocchi.\\ + \const{S\_IFDIR} & 0040000 & Directory.\\ + \const{S\_IFCHR} & 0020000 & Dispositivo a caratteri.\\ + \const{S\_IFIFO} & 0010000 & Fifo.\\ + \hline + \const{S\_ISUID} & 0004000 & Set UID bit \itindex{suid~bit}.\\ + \const{S\_ISGID} & 0002000 & Set GID bit \itindex{sgid~bit}.\\ + \const{S\_ISVTX} & 0001000 & Sticky bit \itindex{sticky~bit}.\\ + \hline +% \const{S\_IRWXU} & 00700 & Bitmask per i permessi del proprietario.\\ + \const{S\_IRUSR} & 00400 & Il proprietario ha permesso di lettura.\\ + \const{S\_IWUSR} & 00200 & Il proprietario ha permesso di scrittura.\\ + \const{S\_IXUSR} & 00100 & Il proprietario ha permesso di esecuzione.\\ + \hline +% \const{S\_IRWXG} & 00070 & Bitmask per i permessi del gruppo.\\ + \const{S\_IRGRP} & 00040 & Il gruppo ha permesso di lettura.\\ + \const{S\_IWGRP} & 00020 & Il gruppo ha permesso di scrittura.\\ + \const{S\_IXGRP} & 00010 & Il gruppo ha permesso di esecuzione.\\ + \hline +% \const{S\_IRWXO} & 00007 & Bitmask per i permessi di tutti gli altri\\ + \const{S\_IROTH} & 00004 & Gli altri hanno permesso di lettura.\\ + \const{S\_IWOTH} & 00002 & Gli altri hanno permesso di esecuzione.\\ + \const{S\_IXOTH} & 00001 & Gli altri hanno permesso di esecuzione.\\ + \hline + \end{tabular} + \caption{Costanti per l'identificazione dei vari bit che compongono il campo + \var{st\_mode} (definite in \headfile{sys/stat.h}).} + \label{tab:file_mode_flags} +\end{table} + +Ad esempio se si volesse impostare una condizione che permetta di controllare +se un file è una directory o un file ordinario si potrebbe definire la macro +di preprocessore: +\includecodesnip{listati/is_file_dir.h} +in cui prima si estraggono da \var{st\_mode} i bit relativi al tipo di file e +poi si effettua il confronto con la combinazione di tipi scelta. + + +\subsection{Le dimensioni dei file} +\label{sec:file_file_size} + +Il campo \var{st\_size} di una struttura \struct{stat} contiene la dimensione +del file in byte, se si tratta di un file regolare. Nel caso di un link +simbolico la dimensione è quella del \textit{pathname} che il link stesso +contiene; per le fifo questo campo è sempre nullo. + +Il campo \var{st\_blocks} definisce la lunghezza del file in blocchi di 512 +byte. Il campo \var{st\_blksize} infine definisce la dimensione preferita per +i trasferimenti sui file (che è la dimensione usata anche dalle librerie del C +per l'interfaccia degli stream); scrivere sul file a blocchi di dati di +dimensione inferiore sarebbe inefficiente. + +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 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 +numero di blocchi occupati) potrà dare una dimensione inferiore, mentre se si +legge dal file (ad esempio usando il comando \cmd{wc -c}), dato che in tal +caso per le parti non scritte vengono restituiti degli zeri, si avrà lo stesso +risultato di \cmd{ls}. + +Se è sempre possibile allargare un file, scrivendoci sopra od usando la +funzione \func{lseek} per spostarsi oltre la sua fine, esistono anche casi in +cui si può avere bisogno di effettuare un troncamento, scartando i dati +presenti al di là della dimensione scelta come nuova fine del file. + +Un file può sempre essere troncato a zero aprendolo con il flag +\const{O\_TRUNC}, ma questo è un caso particolare; per qualunque altra +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)} + + \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: + \begin{errlist} + \item[\errcode{EBADF}] \param{fd} non è un file descriptor. + \item[\errcode{EINVAL}] \param{fd} è un riferimento ad un socket, non a un + file o non è aperto in scrittura. + \end{errlist} + per \func{truncate} si hanno: + \begin{errlist} + \item[\errcode{EACCES}] il file non ha permesso di scrittura o non si ha il + permesso di esecuzione una delle directory del \textit{pathname}. + \item[\errcode{ETXTBSY}] il file è un programma in esecuzione. + \end{errlist} + ed anche \errval{ENOTDIR}, \errval{ENAMETOOLONG}, \errval{ENOENT}, + \errval{EROFS}, \errval{EIO}, \errval{EFAULT}, \errval{ELOOP}.} +\end{functions} + +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 \textit{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 +\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 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 +valore è espresso nel cosiddetto \itindex{calendar~time} \textit{calendar + time}, su cui torneremo in dettaglio in sez.~\ref{sec:sys_time}. + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|c|l|l|c|} + \hline + \textbf{Membro} & \textbf{Significato} & \textbf{Funzione} + & \textbf{Opzione di \cmd{ls}} \\ + \hline + \hline + \var{st\_atime}& ultimo accesso ai dati del file & + \func{read}, \func{utime} & \cmd{-u}\\ + \var{st\_mtime}& ultima modifica ai dati del file & + \func{write}, \func{utime} & default\\ + \var{st\_ctime}& ultima modifica ai dati dell'\textit{inode} & + \func{chmod}, \func{utime} & \cmd{-c}\\ + \hline + \end{tabular} + \caption{I tre tempi associati a ciascun file.} + \label{tab:file_file_times} +\end{table} + +Il primo punto da tenere presente è la differenza fra il cosiddetto tempo di +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 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 +(talvolta insieme anche al tempo di cambiamento di stato) per decidere quali +file devono essere archiviati per il backup. Il tempo di ultimo accesso viene +di solito usato per identificare i file che non vengono più utilizzati per un +certo lasso di tempo. Ad esempio un programma come \texttt{leafnode} lo usa +per cancellare gli articoli letti più vecchi, mentre \texttt{mutt} lo usa per +marcare i messaggi di posta che risultano letti. Il sistema non tiene conto +dell'ultimo accesso \itindex{inode} all'\textit{inode}, pertanto funzioni come +\func{access} o \func{stat} non hanno alcuna influenza sui tre tempi. Il +comando \cmd{ls} (quando usato con le opzioni \cmd{-l} o \cmd{-t}) mostra i +tempi dei file secondo lo schema riportato nell'ultima colonna di +tab.~\ref{tab:file_file_times}. + +L'aggiornamento del tempo di ultimo accesso è stato a lungo considerato un +difetto progettuale di Unix, questo infatti comporta la necessità di +effettuare un accesso in scrittura sul disco anche in tutti i casi in cui +questa informazione non interessa e sarebbe possibile avere un semplice +accesso in lettura sui dati bufferizzati. Questo comporta un ovvio costo sia +in termini di prestazioni, che di consumo di risorse come la batteria per i +portatili, o cicli di riscrittura per i dischi su memorie riscrivibili. + +% TODO aggiustare per il contenuto duplicato con le analoghe MS_* + +Per questo motivo, onde evitare di mantenere una informazione che nella +maggior parte dei casi non interessa, è sempre stato possibile disabilitare +l'aggiornamento del tempo di ultimo accesso con l'opzione di montaggio +\texttt{noatime}. Dato però che questo può creare problemi a qualche +programma, in Linux è stata introdotta la opzione \texttt{relatime} che esegue +l'aggiornamento soltanto se il tempo di ultimo accesso è precedente al tempo di +ultima modifica o cambiamento, così da rendere evidente che vi è stato un +accesso dopo la scrittura, ed evitando al contempo ulteriori operazioni su +disco negli accessi successivi. In questo modo l'informazione relativa al +fatto che un file sia stato letto resta disponibile, e ad esempio i programmi +citati in precedenza continuano a funzionare. Questa opzione, a partire dal +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}.} + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|c|c|c|c|c|c|l|} + \hline + \multicolumn{1}{|p{3cm}|}{\centering{\vspace{6pt}\textbf{Funzione}}} & + \multicolumn{3}{|p{3.6cm}|}{\centering{ + \textbf{File o directory del riferimento}}}& + \multicolumn{3}{|p{3.6cm}|}{\centering{ + \textbf{Directory contenente il riferimento}}} + &\multicolumn{1}{|p{3.6cm}|}{\centering{\vspace{6pt}\textbf{Note}}} \\ + \cline{2-7} + \cline{2-7} + \multicolumn{1}{|p{3cm}|}{} + &\multicolumn{1}{|p{.9cm}|}{\centering{\textsl{(a)}}} + &\multicolumn{1}{|p{.9cm}|}{\centering{\textsl{(m)}}} + &\multicolumn{1}{|p{.9cm}|}{\centering{\textsl{(c)}}} + &\multicolumn{1}{|p{.9cm}|}{\centering{\textsl{(a)}}} + &\multicolumn{1}{|p{.9cm}|}{\centering{\textsl{(m)}}} + &\multicolumn{1}{|p{.9cm}|}{\centering{\textsl{(c)}}} + &\multicolumn{1}{|p{3cm}|}{} \\ + \hline + \hline + \func{chmod}, \func{fchmod} + & -- & -- &$\bullet$& -- & -- & -- &\\ + \func{chown}, \func{fchown} + & -- & -- &$\bullet$& -- & -- & -- &\\ + \func{creat} + &$\bullet$&$\bullet$&$\bullet$& -- &$\bullet$&$\bullet$& + con \const{O\_CREATE} \\ + \func{creat} + & -- &$\bullet$&$\bullet$& -- &$\bullet$&$\bullet$& + con \const{O\_TRUNC} \\ + \func{exec} + &$\bullet$& -- & -- & -- & -- & -- &\\ + \func{lchown} + & -- & -- &$\bullet$& -- & -- & -- &\\ + \func{link} + & -- & -- &$\bullet$& -- &$\bullet$&$\bullet$&\\ + \func{mkdir} + &$\bullet$&$\bullet$&$\bullet$& -- &$\bullet$&$\bullet$&\\ + \func{mkfifo} + &$\bullet$&$\bullet$&$\bullet$& -- &$\bullet$&$\bullet$&\\ + \func{open} + &$\bullet$&$\bullet$&$\bullet$& -- &$\bullet$&$\bullet$& + con \const{O\_CREATE} \\ + \func{open} + & -- &$\bullet$&$\bullet$& -- & -- & -- & + con \const{O\_TRUNC} \\ + \func{pipe} + &$\bullet$&$\bullet$&$\bullet$& -- & -- & -- &\\ + \func{read} + &$\bullet$& -- & -- & -- & -- & -- &\\ + \func{remove} + & -- & -- &$\bullet$& -- &$\bullet$&$\bullet$& + se esegue \func{unlink}\\ + \func{remove} + & -- & -- & -- & -- &$\bullet$&$\bullet$& + se esegue \func{rmdir}\\ + \func{rename} + & -- & -- &$\bullet$& -- &$\bullet$&$\bullet$& + per entrambi gli argomenti\\ + \func{rmdir} + & -- & -- & -- & -- &$\bullet$&$\bullet$&\\ + \func{truncate}, \func{ftruncate} + & -- &$\bullet$&$\bullet$& -- & -- & -- &\\ + \func{unlink} + & -- & -- &$\bullet$& -- &$\bullet$&$\bullet$&\\ + \func{utime} + &$\bullet$&$\bullet$&$\bullet$& -- & -- & -- &\\ + \func{write} + & -- &$\bullet$&$\bullet$& -- & -- & -- &\\ + \hline + \end{tabular} + \caption{Prospetto dei cambiamenti effettuati sui tempi di ultimo + accesso \textsl{(a)}, ultima modifica \textsl{(m)} e ultimo cambiamento + \textsl{(c)} dalle varie funzioni operanti su file e directory.} + \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 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 +esiste. Per questo motivo quando si copia un file, a meno di preservare +esplicitamente i tempi (ad esempio con l'opzione \cmd{-p} di \cmd{cp}) esso +avrà sempre il tempo corrente come data di ultima modifica. + +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)} + 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: + \begin{errlist} + \item[\errcode{EACCES}] non si ha il permesso di scrittura sul file. + \item[\errcode{EPERM}] non si è proprietari del file. + \end{errlist} + ed inoltre \errval{EROFS} e \errval{ENOENT}.} +\end{prototype} + +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]{\textwidth} + \includestruct{listati/utimbuf.h} + \end{minipage} + \normalsize + \caption{La struttura \structd{utimbuf}, usata da \func{utime} per modificare + i tempi dei file.} + \label{fig:struct_utimebuf} +\end{figure} + +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. + +Si tenga presente che non è comunque possibile specificare il tempo di +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 è 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 +nanosecondi per la gran parte dei filesystem. La ulteriore informazione può +essere acceduta attraverso altri campi appositamente aggiunti alla struttura +\struct{stat}. Se si sono definite le macro \macro{\_BSD\_SOURCE} o +\macro{\_SVID\_SOURCE} questi sono \var{st\_atim.tv\_nsec}, +\var{st\_mtim.tv\_nsec} e \var{st\_ctim.tv\_nsec} se queste non sono definite, +\var{st\_atimensec}, \var{st\_mtimensec} e \var{st\_mtimensec}. Qualora il +supporto per questa maggior precisione sia assente questi campi aggiuntivi +saranno nulli. + +Per la gestione di questi nuovi valori è stata definita una seconda funzione +di modifica, \funcd{utimes}, che consente di specificare tempi con maggior +precisione; il suo prototipo è: +\begin{prototype} + {sys/time.h} + {int utimes(const char *filename, struct timeval times[2])} + 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: + \begin{errlist} + \item[\errcode{EACCES}] non si ha il permesso di scrittura sul file. + \item[\errcode{EPERM}] non si è proprietari del file. + \end{errlist} + ed inoltre \errval{EROFS} e \errval{ENOENT}.} +\end{prototype} + +La funzione è del tutto analoga alla precedente \func{utime} ma usa come +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. Se si indica come secondo argomento un +puntatore nullo di nuovo verrà utilizzato il tempo corrente. + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{\textwidth} + \includestruct{listati/timeval.h} + \end{minipage} + \normalsize + \caption{La struttura \structd{timeval} usata per indicare valori di tempo + con la precisione del microsecondo.} + \label{fig:sys_timeval_struct} +\end{figure} + +Oltre ad \func{utimes} su Linux sono presenti altre due funzioni,\footnote{le + due funzioni non sono definite in nessuno standard, ma sono presenti, oltre + che su Linux, anche su BSD.} \funcd{futimes} e \funcd{lutimes}, che +consentono rispettivamente di effettuare la modifica utilizzando un file +già aperto o di eseguirla direttamente su un link simbolico. I relativi +prototipi sono: +\begin{functions} + \headdecl{sys/time.h} + + \funcdecl{int futimes(int fd, const struct timeval tv[2])} Cambia i tempi + di un file già aperto specificato tramite il file descriptor \param{fd}. + + \funcdecl{int lutimes(const char *filename, const struct timeval tv[2])} + Cambia i tempi di \param{filename} anche se questo è un link simbolico. + + + \bodydesc{Le funzioni restituiscono zero in caso di successo e $-1$ per un + errore, nel qual caso \var{errno} assumerà gli stessi valori di + \func{utimes}, con in più per \func{futimes}: + \begin{errlist} + \item[\errcode{EBADF}] \param{fd} non è un file descriptor. + \item[\errcode{ENOSYS}] il filesystem \texttt{/proc} non è accessibile. + \end{errlist}} +\end{functions} + +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 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 +valori con questa precisione. Per questo sono state introdotte due nuove +funzioni, \funcd{futimens} e \func{utimensat}, in grado di eseguire questo +compito; i rispettivi prototipi sono: +\begin{functions} + \headdecl{sys/time.h} + + \funcdecl{futimens(int fd, const struct timespec times[2])} Cambia i tempi + di un file già aperto, specificato dal file descriptor \param{fd}. + + \funcdecl{int utimensat(int dirfd, const char *pathname, const struct + timespec times[2], int flags)} Cambia i tempi del file \param{pathname}. + + + \bodydesc{Le funzioni restituiscono zero in caso di successo e $-1$ per un + errore, nel qual caso \var{errno} assumerà gli stessi valori di + \func{utimes}, con in più per \func{futimes}: + \begin{errlist} + \item[\errcode{EBADF}] \param{fd} non è un file descriptor. + \item[\errcode{ENOSYS}] il filesystem \texttt{/proc} non è accessibile. + \end{errlist}} +\end{functions} + +Entrambe le funzioni utilizzano per indicare i valori dei tempi un +vettore \param{times} di due strutture \struct{timespec} che permette di +specificare un valore di tempo con una precisione fino al nanosecondo, la cui +definizione è riportata in fig.~\ref{fig:sys_timespec_struct}. + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{\textwidth} + \includestruct{listati/timespec.h} + \end{minipage} + \normalsize + \caption{La struttura \structd{timespec} usata per indicare valori di tempo + con la precisione del nanosecondo.} + \label{fig:sys_timespec_struct} +\end{figure} + +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 \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 +\const{UTIME\_OMIT} si richiede di non impostare il tempo. Si può così +aggiornare in maniera specifica soltanto uno fra il tempo di ultimo accesso e +quello di ultima modifica. Quando si usa uno di questi valori speciali per +\var{tv\_nsec} il corrispondente valore di \var{tv\_sec} viene ignorato. + +Queste due funzioni sono una estensione definita in una recente revisione +dello standard POSIX (la POSIX.1-2008); sono state introdotte a partire dal +kernel 2.6.22, e supportate dalle \acr{glibc} a partire dalla versione +2.6.\footnote{in precedenza, a partire dal kernel 2.6.16, era stata introdotta + la funzione \funcm{futimesat} seguendo una bozza della revisione dello + standard poi modificata, questa funzione, sostituita da \func{utimensat}, è + stata dichiarata obsoleta, non è supportata da nessuno standard e non deve + essere più utilizzata: pertanto non la tratteremo.} La prima è +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} consente una indicazione sicura dei +\itindsub{pathname}{relativo} \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; 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} -\label{sec:filedir_access_control} +\label{sec:file_access_control} -Una delle caratteristiche fondamentali di tutti i sistemi unix-like è quella +Una delle caratteristiche fondamentali di tutti i sistemi unix-like è quella del controllo di accesso ai file, che viene implementato per qualunque -filesystem standard. In questa sezione ne esamineremo i concetti essenziali e -le funzioni usate per gestirne i vari aspetti. +filesystem standard.\footnote{per standard si intende che implementa le + caratteristiche previste dallo standard POSIX; in Linux sono disponibili + anche una serie di altri filesystem, come quelli di Windows e del Mac, che + non supportano queste caratteristiche.} In questa sezione ne esamineremo i +concetti essenziali e le funzioni usate per gestirne i vari aspetti. \subsection{I permessi per l'accesso ai file} -\label{sec:filedir_perm_overview} - -Il controllo di accesso ai file in unix segue un modello abbastanza semplice, -ma adatto alla gran parte delle esigenze, in cui si dividono i permessi su tre -livelli. Si tenga conto poi che quanto diremo è vero solo per filesystem di -tipo unix, e non è detto che sia applicabile a un filesystem -qualunque\footnote{ed infatti non è vero per il filesystem vfat di Windows, - per il quale vengono assegnati in maniera fissa con un opzione in fase di - montaggio}. Esistono inoltre estensioni che permettono di implementare le -ACL (\textit{Access Control List}) che sono un meccanismo di controllo di -accesso molto più sofisticato. - -Ad ogni file unix associa sempre l'utente che ne è proprietario (il cosiddetto -\textit{owner}) e il gruppo di appartenenza, secondo il meccanismo degli -identificatori di utenti e gruppi (\textsl{uid} e \textsl{gid}), e accessibili -da programma tramite i campi \var{st\_uid} e \var{st\_gid} della struttura -\var{stat} (si veda \secref{sec:filedir_stat}). Ad ogni file viene inoltre -associato un insieme di permessi che sono divisi in tre classi, e cioè -attribuiti rispettivamente all'utente proprietario del file, a un qualunque -utente faccia parte del gruppo cui appartiene il file, e a tutti gli altri -utenti. - -I permessi, così come vengono presi dai comandi e dalle routine di sistema -sono espressi da un numero di 12 bit; di questi i nove meno significativi sono -usati a gruppi di tre per indicare i permessi base di lettura, scrittura ed -esecuzione (indicati rispettivamente con le lettere \textsl{w}, \textit{r} -\textsl{x} nei comandi di sistema) applicabili rispettivamente al -proprietario, al gruppo, a tutti. I restanti tre bit (\textsl{suid}, -\textsl{sgid}, e \textsl{sticky}) sono usati per indicare alcune -caratteristiche più complesse su cui torneremo in seguito (vedi -\secref{sec:filedir_suid_sgid} e \secref{sec:filedir_sticky}). - -Anche i permessi sono tenuti per ciascun file (di qualunque tipo, quindi anche -per le fifo, i socket e i file di dispositivo) nell'inode, in opportuni bit -del campo \var{st\_mode} della struttura letta da \func{stat} (vedi -\figref{fig:filedir_stat_struct}). - - -In genere ci si riferisce a questi permessi usando le lettere \textsl{u} (per -\textit{user}), \textsl{g} (per \textit{group}) e \textsl{o} (per -\textit{other}), inoltre se si vuole indicare tutti questi gruppi insieme si -usa la lettera \textsl{a} (per \textit{all}). Si tenga ben presente questa -distinzione, dato che in certi casi, mutuando la terminologia in uso nel VMS, -si parla dei permessi base come di permessi di owner, group ed all, le cui -iniziali possono da luogo a confusione. Le costanti che permettono di accedere -al valore numerico di questi bit sono riportate in \ntab. +\label{sec:file_perm_overview} + +Ad ogni file Linux associa sempre l'utente che ne è proprietario (il +cosiddetto \textit{owner}) ed un gruppo di appartenenza, secondo il meccanismo +degli identificatori di utente e gruppo (\ids{UID} e \ids{GID}). Questi valori +sono accessibili da programma tramite la funzione \func{stat}, e sono +mantenuti nei campi \var{st\_uid} e \var{st\_gid} della struttura +\struct{stat} (si veda sez.~\ref{sec:file_stat}).\footnote{questo è vero solo + per filesystem di tipo Unix, ad esempio non è vero per il filesystem vfat di + Windows, che non fornisce nessun supporto per l'accesso multiutente, e per + il quale i permessi vengono assegnati in maniera fissa con un opzione in + fase di montaggio.} + +Il controllo di accesso ai file segue un modello abbastanza semplice che +prevede tre permessi fondamentali strutturati su tre livelli di accesso. +Esistono varie estensioni a questo modello,\footnote{come le \textit{Access + Control List} che sono state aggiunte ai filesystem standard con opportune + estensioni (vedi sez.~\ref{sec:file_ACL}) per arrivare a meccanismi di + controllo ancora più sofisticati come il \textit{mandatory access control} + di SE-Linux.} ma nella maggior parte dei casi il meccanismo standard è più +che sufficiente a soddisfare tutte le necessità più comuni. I tre permessi di +base associati ad ogni file sono: +\begin{itemize*} +\item il permesso di lettura (indicato con la lettera \texttt{r}, dall'inglese + \textit{read}). +\item il permesso di scrittura (indicato con la lettera \texttt{w}, + dall'inglese \textit{write}). +\item il permesso di esecuzione (indicato con la lettera \texttt{x}, + dall'inglese \textit{execute}). +\end{itemize*} +mentre i tre livelli su cui sono divisi i privilegi sono: +\begin{itemize*} +\item i privilegi per l'utente proprietario del file. +\item i privilegi per un qualunque utente faccia parte del gruppo cui + appartiene il file. +\item i privilegi per tutti gli altri utenti. +\end{itemize*} + +L'insieme dei permessi viene espresso con un numero a 12 bit; di questi i nove +meno significativi sono usati a gruppi di tre per indicare i permessi base di +lettura, scrittura ed esecuzione e sono applicati rispettivamente +rispettivamente al proprietario, al gruppo, a tutti gli altri. + +\begin{figure}[htb] + \centering + \includegraphics[width=6cm]{img/fileperm} + \caption{Lo schema dei bit utilizzati per specificare i permessi di un file + contenuti nel campo \var{st\_mode} di \struct{stat}.} + \label{fig:file_perm_bit} +\end{figure} + +I restanti tre bit (noti come \itindex{suid~bit} \textit{suid bit}, +\itindex{sgid~bit} \textit{sgid bit}, e \itindex{sticky~bit} \textit{sticky + bit}) sono usati per indicare alcune caratteristiche più complesse del +meccanismo del controllo di accesso su cui torneremo in seguito (in +sez.~\ref{sec:file_special_perm}); lo schema di allocazione dei bit è +riportato in fig.~\ref{fig:file_perm_bit}. + +Anche i permessi, come tutte le altre informazioni pertinenti al file, sono +memorizzati \itindex{inode} nell'\textit{inode}; in particolare essi sono +contenuti in alcuni bit del campo \var{st\_mode} della struttura \struct{stat} +(si veda di nuovo fig.~\ref{fig:file_stat_struct}). + +In genere ci si riferisce ai tre livelli dei privilegi usando le lettere +\cmd{u} (per \textit{user}), \cmd{g} (per \textit{group}) e \cmd{o} (per +\textit{other}), inoltre se si vuole indicare tutti i raggruppamenti insieme +si usa la lettera \cmd{a} (per \textit{all}). Si tenga ben presente questa +distinzione dato che in certi casi, mutuando la terminologia in uso nel VMS, +si parla dei permessi base come di permessi per \textit{owner}, \textit{group} +ed \textit{all}, le cui iniziali possono dar luogo a confusione. Le costanti +che permettono di accedere al valore numerico di questi bit nel campo +\var{st\_mode} sono riportate in tab.~\ref{tab:file_bit_perm}. \begin{table}[htb] \centering \footnotesize \begin{tabular}[c]{|c|l|} \hline - \var{st\_mode} bit & Significato \\ + \textbf{\var{st\_mode}} bit & \textbf{Significato} \\ \hline \hline - \macro{S\_IRUSR} & \textit{user-read}, l'utente può leggere \\ - \macro{S\_IWUSR} & \textit{user-write}, l'utente può scrivere \\ - \macro{S\_IXUSR} & \textit{user-execute}, l'utente può eseguire \\ - \hline - \macro{S\_IRGRP} & \textit{group-read}, il gruppo può leggere \\ - \macro{S\_IWGRP} & \textit{group-write}, il gruppo può scrivere \\ - \macro{S\_IXGRP} & \textit{group-execute}, il gruppo può eseguire\\ - \hline - \macro{S\_IROTH} & \textit{other-read}, tutti possono leggere \\ - \macro{S\_IWOTH} & \textit{other-write}, tutti possono scrivere \\ - \macro{S\_IXOTH} & \textit{other-execute}, tutti possono eseguire\\ + \const{S\_IRUSR} & \textit{user-read}, l'utente può leggere.\\ + \const{S\_IWUSR} & \textit{user-write}, l'utente può scrivere.\\ + \const{S\_IXUSR} & \textit{user-execute}, l'utente può eseguire.\\ + \hline + \const{S\_IRGRP} & \textit{group-read}, il gruppo può leggere.\\ + \const{S\_IWGRP} & \textit{group-write}, il gruppo può scrivere.\\ + \const{S\_IXGRP} & \textit{group-execute}, il gruppo può eseguire.\\ + \hline + \const{S\_IROTH} & \textit{other-read}, tutti possono leggere.\\ + \const{S\_IWOTH} & \textit{other-write}, tutti possono scrivere.\\ + \const{S\_IXOTH} & \textit{other-execute}, tutti possono eseguire.\\ \hline \end{tabular} \caption{I bit dei permessi di accesso ai file, come definiti in @@ -93,1142 +3537,3672 @@ al valore numerico di questi bit sono riportate in \ntab. \label{tab:file_bit_perm} \end{table} -Questi permessi vengono usati in maniera diversa dalle varie funzioni, e a -seconda che si riferiscano a file, link simbolici o directory, qui ci -limiteremo ad un riassunto delle regole generali, entrando nei -dettagli più avanti. - -La prima regola è che per poter accedere ad un file attraverso il suo pathname -occorre il permesso di esecuzione in ciascuna delle directory che compongono -il pathname, e lo stesso vale per aprire un file nella directory corrente (per -la quale appunto serve il diritto di esecuzione). - -Per una directory infatti il permesso di esecuzione ha il significato -specifico che essa può essere attraversata nella risoluzione del pathname, ed -è distinto dal permesso di lettura che invece implica che si può leggere il -contenuto della directory. Questo significa che se si ha il permesso di -esecuzione senza permesso di lettura si potrà lo stesso aprire un file in una -directory (se si hanno i permessi opportuni per il medesimo) ma non si potrà -vederlo con \cmd{ls} (per crearlo occorrerà anche il permesso di scrittura per -la directory). - -Il permesso di lettura per un file consente di aprirlo con le opzioni di sola -lettura (\macro{O\_RDONLY}) o di lettura-scrittura (\macro{O\_RDWR}) e -leggerne il contenuto. Il permesso di scrittura consente di aprire un file in -sola scrittura (\macro{O\_WRONLY}) o lettura-scrittura (\macro{O\_RDWR}) e -modificarne il contenuto, lo stesso permesso è necessario per poter troncare -il file con l'opzione \macro{O\_TRUNC}. - -Non si può creare un file fintanto che non si disponga del permesso di +I permessi vengono usati in maniera diversa dalle varie funzioni, e a seconda +che si riferiscano a dei file, dei link simbolici o delle directory; qui ci +limiteremo ad un riassunto delle regole generali, entrando nei dettagli più +avanti. + +La prima regola è che per poter accedere ad un file attraverso il suo +\textit{pathname} occorre il permesso di esecuzione in ciascuna delle +directory che compongono il \textit{pathname}; lo stesso vale per aprire un +file nella directory corrente (per la quale appunto serve il diritto di +esecuzione). + +Per una directory infatti il permesso di esecuzione significa che essa può +essere attraversata nella risoluzione del \textit{pathname}, ed è distinto dal +permesso di lettura che invece implica che si può leggere il contenuto della +directory. + +Questo significa che se si ha il permesso di esecuzione senza permesso di +lettura si potrà lo stesso aprire un file in una directory (se si hanno i +permessi opportuni per il medesimo) ma non si potrà vederlo con \cmd{ls} +(mentre per crearlo occorrerà anche il permesso di scrittura per la +directory). + +Avere il permesso di lettura per un file consente di aprirlo con le opzioni +(si veda quanto riportato in tab.~\ref{tab:file_open_flags}) di sola lettura o +di lettura/scrittura e leggerne il contenuto. Avere il permesso di scrittura +consente di aprire un file in sola scrittura o lettura/scrittura e modificarne +il contenuto, lo stesso permesso è necessario per poter troncare il file. + +Non si può creare un file fintanto che non si disponga del permesso di esecuzione e di quello di scrittura per la directory di destinazione; gli stessi permessi occorrono per cancellare un file da una directory (si ricordi -che questo non implica necessariamente la rimozione fisica del file), non è -necessario nessun tipo di permesso per il file stesso (infatti esso non viene -toccato, viene solo modificato il contenute della directory). +che questo non implica necessariamente la rimozione del contenuto del file dal +disco), non è necessario nessun tipo di permesso per il file stesso (infatti +esso non viene toccato, viene solo modificato il contenuto della directory, +rimuovendo la voce che ad esso fa riferimento). Per poter eseguire un file (che sia un programma compilato od uno script di -shell), occorre il permesso di esecuzione per il medesimo, inoltre solo i file -regolari possono essere eseguiti. +shell, od un altro tipo di file eseguibile riconosciuto dal kernel), occorre +avere il permesso di esecuzione, inoltre solo i file regolari possono essere +eseguiti. + +I permessi per un link simbolico sono ignorati, contano quelli del file a cui +fa riferimento; per questo in genere il comando \cmd{ls} riporta per un link +simbolico tutti i permessi come concessi; utente e gruppo a cui esso +appartiene vengono pure ignorati quando il link viene risolto, vengono +controllati solo quando viene richiesta la rimozione del link e quest'ultimo è +in una directory con lo \itindex{sticky~bit} \textit{sticky bit} impostato (si +veda sez.~\ref{sec:file_special_perm}). La procedura con cui il kernel stabilisce se un processo possiede un certo permesso (di lettura, scrittura o esecuzione) si basa sul confronto fra l'utente e il gruppo a cui il file appartiene (i valori di \var{st\_uid} e -\var{st\_gid} accennati in precedenza) e l'\textit{effective user id}, -l'\textit{effective group id} e gli eventuali \textit{supplementary group id} -del processo. +\var{st\_gid} accennati in precedenza) e l'\ids{UID} effettivo, il \ids{GID} +effettivo e gli eventuali \ids{GID} supplementari del processo.\footnote{in + realtà Linux, per quanto riguarda l'accesso ai file, utilizza gli + identificatori del gruppo \textit{filesystem} (si ricordi quanto esposto in + sez.~\ref{sec:proc_perms}), ma essendo questi del tutto equivalenti ai primi, + eccetto il caso in cui si voglia scrivere un server NFS, ignoreremo questa + differenza.} Per una spiegazione dettagliata degli identificatori associati ai processi si -veda \secref{sec:prochand_perms}; normalmente, a parte quanto vedremo in -\secref{sec:filedir_suid_sgid}, l'\textit{effective user id} e -l'\textit{effective group id} corrispondono a uid e gid dell'utente che ha -lanciato il processo, mentre i \textit{supplementary group id} sono quelli dei -gruppi cui l'utente appartiene. - -% Quando un processo cerca l'accesso al file esso controlla i propri uid e gid -% confrontandoli con quelli del file e se l'operazione richiesta è compatibile -% con i permessi associati al file essa viene eseguita, altrimenti viene -% bloccata ed è restituito un errore di \texttt{EPERM}. Questo procedimento non -% viene eseguito per l'amministratore di sistema (il cui uid è zero) il quale -% a -% pertanto accesso senza restrizione a qualunque file del sistema. - -% In realtà il procedimento è più complesso di quanto descritto in maniera -% elementare qui; inoltre ad un processo sono associati diversi identificatori, -% torneremo su questo in maggiori dettagli in seguito in -% \secref{sec:proc_perms}. +veda sez.~\ref{sec:proc_perms}; normalmente, a parte quanto vedremo in +sez.~\ref{sec:file_special_perm}, l'\ids{UID} effettivo e il \ids{GID} effettivo +corrispondono ai valori dell'\ids{UID} e del \ids{GID} dell'utente che ha +lanciato il processo, mentre i \ids{GID} supplementari sono quelli dei gruppi +cui l'utente appartiene. I passi attraverso i quali viene stabilito se il processo possiede il diritto di accesso sono i seguenti: -\begin{itemize} -\item Se l'\textit{effective user id} del processo è zero (corrispondente - all'amministratore) l'accesso è sempre garantito senza nessun ulteriore - controllo. Per questo motivo \textsl{root} ha piena libertà di accesso a +\begin{enumerate} +\item Se l'\ids{UID} effettivo del processo è zero (corrispondente + all'amministratore) l'accesso è sempre garantito senza nessun ulteriore + controllo. Per questo motivo \textsl{root} ha piena libertà di accesso a tutti i file. -\item Se l'\textit{effective user id} del processo è uguale all'uid del - proprietario del file (nel qual caso si dice che il processo è proprietario +\item Se l'\ids{UID} effettivo del processo è uguale all'\ids{UID} del + proprietario del file (nel qual caso si dice che il processo è proprietario del file) allora: - \begin{itemize} + \begin{itemize*} \item se il relativo\footnote{per relativo si intende il bit di user-read se - il processo, vuole accedere in scrittura, quello di user-write per - l'accesso in scrittura, etc.} bit dei permessi d'accesso dell'utente è - settato, l'accesso è consentito - \item altrimenti l'accesso è negato - \end{itemize} -\item Se l'\textit{effective group id} del processo o uno dei - \textit{supplementary group id} dei processi corrispondono al gid del file - allora: - \begin{itemize} - \item se il bit dei permessi d'accesso del gruppo è settato, l'accesso è - consentito, altrimenti l'accesso è negato - \end{itemize} -\item se il bit dei permessi d'accesso per tutti gli altri è settato, - l'accesso è consentito, altrimenti l'accesso è negato. -\end{itemize} + il processo vuole accedere in lettura, quello di user-write per + l'accesso in scrittura, ecc.} bit dei permessi d'accesso dell'utente è + impostato, l'accesso è consentito + \item altrimenti l'accesso è negato + \end{itemize*} +\item Se il \ids{GID} effettivo del processo o uno dei \ids{GID} supplementari + dei processi corrispondono al \ids{GID} del file allora: + \begin{itemize*} + \item se il bit dei permessi d'accesso del gruppo è impostato, l'accesso è + consentito, + \item altrimenti l'accesso è negato + \end{itemize*} +\item Se il bit dei permessi d'accesso per tutti gli altri è impostato, + l'accesso è consentito, altrimenti l'accesso è negato. +\end{enumerate} Si tenga presente che questi passi vengono eseguiti esattamente in -quest'ordine. Questo vuol dire che se un processo è il proprietario di un file -l'accesso è consentito o negato solo sulla base dei permessi per l'utente; i -permessi per il gruppo non vengono neanche controllati; lo stesso vale se il +quest'ordine. Questo vuol dire che se un processo è il proprietario di un file, +l'accesso è consentito o negato solo sulla base dei permessi per l'utente; i +permessi per il gruppo non vengono neanche controllati. Lo stesso vale se il processo appartiene ad un gruppo appropriato, in questo caso i permessi per tutti gli altri non vengono controllati. -\subsection{I bit \textsl{suid} e \textsl{sgid}} -\label{sec:filedir_suid_sgid} - -Come si è accennato (in \secref{sec:filedir_perm_overview}) nei dodici bit del -campo \var{st\_mode} usati per il controllo di accesso oltre ai bit dei -permessi veri e propri, ci sono altri tre bit che vengono usati per indicare -alcune proprietà speciali dei file. Due di questi sono i bit detti -\textsl{suid} (o \textit{set-user-ID bit}) e \textsl{sgid} (o -\textit{set-group-ID bit}) che sono identificati dalle constanti -\macro{S\_ISUID} e \macro{S\_ISGID}. - -Come spiegato in dettaglio in \secref{sec:prochand_exec}, quando si lancia un -programma il comportamendo normale del kernel è quello di settare -l'\textit{effective user id} e l'\textit{effective group id} del nuovo -processo all'uid e al gid del processo corrente, che normalmente corrispondono -dell'utente con cui si è entrati nel sistema. - -Se però il file del programma (che ovviamente deve essere eseguibile) ha il -bit \textsl{suid} settato, il kernel assegnerà come \textit{effective user id} -al nuovo processo l'uid del proprietario del file al posto dell'uid del -processo originario. Avere il bit \textsl{sgid} settato ha lo stesso effetto -sull'\textit{effective group id} del processo. - -I bit \textsl{suid} e \textsl{sgid} vengono usati per permettere agli utenti -normali di usare programmi che abbisognano di privilegi speciali; l'esempio -classico è il comando \cmd{passwd} che ha la necessità di modificare il file -delle password, quest'ultimo ovviamente può essere scritto solo -dall'amministratore, ma non è necessario chiamare l'amministratore per -cambiare la propria password. Infatti il comando \cmd{passwd} appartiene a root -ma ha il suid bit settato per cui quando viene lanciato da un utente normale -parte con i privilegi di root. + +\subsection{I bit dei permessi speciali} +\label{sec:file_special_perm} + +\itindbeg{suid~bit} +\itindbeg{sgid~bit} + +Come si è accennato (in sez.~\ref{sec:file_perm_overview}) nei dodici bit del +campo \var{st\_mode} di \struct{stat} che vengono usati per il controllo di +accesso oltre ai bit dei permessi veri e propri, ci sono altri tre bit che +vengono usati per indicare alcune proprietà speciali dei file. Due di questi +sono i bit detti \acr{suid} (da \textit{set-user-ID bit}) e \acr{sgid} (da +\textit{set-group-ID bit}) che sono identificati dalle costanti +\const{S\_ISUID} e \const{S\_ISGID}. + +Come spiegato in dettaglio in sez.~\ref{sec:proc_exec}, quando si lancia un +programma il comportamento normale del kernel è quello di impostare gli +identificatori del gruppo \textit{effective} del nuovo processo al valore dei +corrispondenti del gruppo \textit{real} del processo corrente, che normalmente +corrispondono a quelli dell'utente con cui si è entrati nel sistema. + +Se però il file del programma (che ovviamente deve essere +eseguibile\footnote{per motivi di sicurezza il kernel ignora i bit \acr{suid} + e \acr{sgid} per gli script eseguibili.}) ha il bit \acr{suid} impostato, il +kernel assegnerà come \ids{UID} effettivo al nuovo processo l'\ids{UID} del +proprietario del file al posto dell'\ids{UID} del processo originario. Avere +il bit \acr{sgid} impostato ha lo stesso effetto sul \ids{GID} effettivo del +processo. + +I bit \acr{suid} e \acr{sgid} vengono usati per permettere agli utenti normali +di usare programmi che richiedono privilegi speciali; l'esempio classico è il +comando \cmd{passwd} che ha la necessità di modificare il file delle password, +quest'ultimo ovviamente può essere scritto solo dall'amministratore, ma non è +necessario chiamare l'amministratore per cambiare la propria password. Infatti +il comando \cmd{passwd} appartiene a root ma ha il bit \acr{suid} impostato +per cui quando viene lanciato da un utente normale parte con i privilegi di +root. Chiaramente avere un processo che ha privilegi superiori a quelli che avrebbe normalmente l'utente che lo ha lanciato comporta vari rischi, e questo tipo di -programmi devono essere scritti accuratamente (torneremo sull'argomento in -\secref{sec:prochand_perms}). - -La presenza dei bit \textsl{suid} e \textsl{sgid} su un file può essere -rilevata con il comando \cmd{ls -l}, in tal caso comparirà la lettera \cmd{s} -al posto della \cmd{x} in corrispondenza dei permessi di utente o gruppo. La -stessa lettera \cmd{s} può essere usata nel comando \cmd{chmod} per settare -questi bit. Infine questi bit possono essere controllati all'interno di -\var{st\_mode} con l'uso delle due costanti \macro{S\_ISUID} e -\macro{S\_IGID}, i cui valori sono riportati in -\tabref{tab:filedir_file_mode_flags}. +programmi devono essere scritti accuratamente per evitare che possano essere +usati per guadagnare privilegi non consentiti (l'argomento è affrontato in +dettaglio in sez.~\ref{sec:proc_perms}). + +La presenza dei bit \acr{suid} e \acr{sgid} su un file può essere rilevata con +il comando \cmd{ls -l}, che visualizza una lettera \cmd{s} al posto della +\cmd{x} in corrispondenza dei permessi di utente o gruppo. La stessa lettera +\cmd{s} può essere usata nel comando \cmd{chmod} per impostare questi bit. +Infine questi bit possono essere controllati all'interno di \var{st\_mode} con +l'uso delle due costanti \const{S\_ISUID} e \const{S\_IGID}, i cui valori sono +riportati in tab.~\ref{tab:file_mode_flags}. Gli stessi bit vengono ad assumere in significato completamente diverso per le -directory, normalmente infatti linux usa la convezione di SVR4 per indicare +directory, normalmente infatti Linux usa la convenzione di SVr4 per indicare con questi bit l'uso della semantica BSD nella creazione di nuovi file (si -veda \secref{sec:filedir_ownership}). +veda sez.~\ref{sec:file_ownership_management} per una spiegazione dettagliata +al proposito). -Infine il caso in cui il file abbia il bit \textsl{sgid} settato ma non il -corrispondente bit per l'esecuzione viene utilizzato per attivare per quel -file il \textit{mandatory locking} (argomento affrontato nei dettagli in -\secref{sec:xxx_mandatory_lock}). +Infine Linux utilizza il bit \acr{sgid} per un'ulteriore estensione mutuata +da SVr4. Il caso in cui un file ha il bit \acr{sgid} impostato senza che lo +sia anche il corrispondente bit di esecuzione viene utilizzato per attivare +per quel file il \itindex{mandatory~locking} \textit{mandatory locking} +(affronteremo questo argomento in dettaglio più avanti, in +sez.~\ref{sec:file_mand_locking}). +\itindend{suid~bit} +\itindend{sgid~bit} -\subsection{Il bit \textsl{sticky}} -\label{sec:filedir_sticky} -L'ultimo dei bit rimanenti, identificato dalla costante \macro{S\_ISVTX} è in +\itindbeg{sticky~bit} + +L'ultimo dei bit rimanenti, identificato dalla costante \const{S\_ISVTX}, è in parte un rimasuglio delle origini dei sistemi Unix. A quell'epoca infatti la -memoria virtuale e l'accesso ai files erano molto meno sofisticati e per -ottenere la massima velocità possibile per i programmi usati più comunemente -si poteva settare questo bit. - -L'effetto di questo bit è che il segmento di testo del programma (si veda -\secref{sec:proc_mem_layout} per i dettagli) veniva scritto nella swap la -prima volta che questo veniva lanciato, e vi permaneva fino al riavvio della -mecchina (da questo il nome di \textsl{sticky bit}); essendo la swap un file -continuo indicizzato direttamente in questo modo si poteva risparmiare in -tempo di caricamento rispetto alla ricerca del file su disco. - -Ovviamente per evitare che gli utenti possano intasare la swap solo -l'amministratore è in grado di settare questo bit, che venne poi chiamato -anche \textit{saved text bit}, da cui deriva il nome della costante. Le -attuali implementazioni di memoria virtuale e filesystem rendono +memoria virtuale e l'accesso ai file erano molto meno sofisticati e per +ottenere la massima velocità possibile per i programmi usati più comunemente +si poteva impostare questo bit. + +L'effetto di questo bit era che il \index{segmento!testo} segmento di testo +del programma (si veda sez.~\ref{sec:proc_mem_layout} per i dettagli) veniva +scritto nella swap la prima volta che questo veniva lanciato, e vi permaneva +fino al riavvio della macchina (da questo il nome di \textsl{sticky bit}); +essendo la swap un file continuo o una partizione indicizzata direttamente si +poteva risparmiare in tempo di caricamento rispetto alla ricerca attraverso la +struttura del filesystem. Lo \textsl{sticky bit} è indicato usando la lettera +\texttt{t} al posto della \texttt{x} nei permessi per gli altri. + +Ovviamente per evitare che gli utenti potessero intasare la swap solo +l'amministratore era in grado di impostare questo bit, che venne chiamato +anche con il nome di \textit{saved text bit}, da cui deriva quello della +costante. Le attuali implementazioni di memoria virtuale e filesystem rendono sostanzialmente inutile questo procedimento. -Benché ormai non venga più utilizzato per i file, lo \textsl{sticky bit} ha -invece assunto un uso corrente per le directory\footnote{lo \textsl{sticky - bit} è una estensione non definita nello standard POSIX, linux la - supporta, così come BSD e SRV4}, se il bit è settato infatti un file può -essere rimosso dalla directory soltanto se l'utente ha il permesso di -scrittura ed inoltre è vera una delle seguenti condizioni: -\begin{itemize} -\item l'utente è proprietario del file -\item l'utente è proprietario della directory -\item l'utente è l'amministratore -\end{itemize} -il classico esempio di directory che ha questo bit settato è \file{/tmp}, i -permessi infatti di solito sono settati come: +Benché ormai non venga più utilizzato per i file, lo \textit{sticky bit} ha +invece assunto un uso importante per le directory;\footnote{lo \textit{sticky + bit} per le directory è un'estensione non definita nello standard POSIX, + Linux però la supporta, così come BSD e SVr4.} in questo caso se tale bit è +impostato un file potrà essere rimosso dalla directory soltanto se l'utente ha +il permesso di scrittura su di essa ed inoltre è vera una delle seguenti +condizioni: +\begin{itemize*} +\item l'utente è proprietario del file +\item l'utente è proprietario della directory +\item l'utente è l'amministratore +\end{itemize*} +un classico esempio di directory che ha questo bit impostato è \file{/tmp}, i +permessi infatti di solito sono i seguenti: \begin{verbatim} +$ ls -ld /tmp drwxrwxrwt 6 root root 1024 Aug 10 01:03 /tmp -\end{verbatim} -in questo modo chiunque può leggere, scrivere ed eseguire i file, o crearne di -nuovi, ma solo l'utente che ha creato un file nella directory potrà -cancellarlo o rinominarlo. +\end{verbatim}%$ +quindi con lo \textit{sticky bit} bit impostato. In questo modo qualunque +utente nel sistema può creare dei file in questa directory (che, come +suggerisce il nome, è normalmente utilizzata per la creazione di file +temporanei), ma solo l'utente che ha creato un certo file potrà cancellarlo o +rinominarlo. In questo modo si evita che un utente possa, più o meno +consapevolmente, cancellare i file temporanei creati degli altri utenti. + +\itindend{sticky~bit} + +\subsection{Le funzioni per la gestione dei permessi dei file} +\label{sec:file_perm_management} + +Come visto in sez.~\ref{sec:file_access_control} il controllo di accesso ad un +file viene fatto utilizzando l'\ids{UID} ed il \ids{GID} effettivo del processo; +ci sono casi però in cui si può voler effettuare il controllo con l'\ids{UID} +reale ed il \ids{GID} reale, vale a dire usando i valori di \ids{UID} e +\ids{GID} relativi all'utente che ha lanciato il programma, e che, come +accennato in sez.~\ref{sec:file_special_perm} e spiegato in dettaglio in +sez.~\ref{sec:proc_perms}, non è detto siano uguali a quelli effettivi. + +Per far questo si può usare la funzione \funcd{access}, il cui prototipo è: +\begin{prototype}{unistd.h} +{int access(const char *pathname, int mode)} + +Verifica i permessi di accesso. + +\bodydesc{La funzione ritorna 0 se l'accesso è consentito, -1 se l'accesso non + è consentito ed in caso di errore; nel qual caso la variabile \var{errno} + assumerà i valori: + \begin{errlist} + \item[\errcode{EINVAL}] il valore di \param{mode} non è valido. + \item[\errcode{EACCES}] l'accesso al file non è consentito, o non si ha il + permesso di attraversare una delle directory di \param{pathname}. + \item[\errcode{EROFS}] si è richiesto l'accesso in scrittura per un file su + un filesystem montato in sola lettura. + \end{errlist} + ed inoltre \errval{EFAULT}, \errval{ENAMETOOLONG}, \errval{ENOENT}, + \errval{ENOTDIR}, \errval{ELOOP}, \errval{EIO}.} +\end{prototype} + +La funzione verifica i permessi di accesso, indicati da \param{mode}, per il +file indicato da \param{pathname}. I valori possibili per l'argomento +\param{mode} sono esprimibili come combinazione delle costanti numeriche +riportate in tab.~\ref{tab:file_access_mode_val} (attraverso un OR binario +delle stesse). I primi tre valori implicano anche la verifica dell'esistenza +del file, se si vuole verificare solo quest'ultima si può usare \const{F\_OK}, +o anche direttamente \func{stat}. Nel caso in cui \param{pathname} si +riferisca ad un link simbolico, questo viene seguito ed il controllo è fatto +sul file a cui esso fa riferimento. + +La funzione controlla solo i bit dei permessi di accesso, si ricordi che il +fatto che una directory abbia permesso di scrittura non significa che ci si +possa scrivere come in un file, e il fatto che un file abbia permesso di +esecuzione non comporta che contenga un programma eseguibile. La funzione +ritorna zero solo se tutte i permessi controllati sono disponibili, in caso +contrario (o di errore) ritorna -1. +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}{|c|l|} + \hline + \textbf{\param{mode}} & \textbf{Significato} \\ + \hline + \hline + \const{R\_OK} & Verifica il permesso di lettura. \\ + \const{W\_OK} & Verifica il permesso di scrittura. \\ + \const{X\_OK} & Verifica il permesso di esecuzione. \\ + \const{F\_OK} & Verifica l'esistenza del file. \\ + \hline + \end{tabular} + \caption{Valori possibile per l'argomento \param{mode} della funzione + \func{access}.} + \label{tab:file_access_mode_val} +\end{table} + +Un esempio tipico per l'uso di questa funzione è quello di un processo che sta +eseguendo un programma coi privilegi di un altro utente (ad esempio attraverso +l'uso del \itindex{suid~bit} \textit{suid bit}) che vuole controllare se +l'utente originale ha i permessi per accedere ad un certo file. + +Del tutto analoghe a \func{access} sono le due funzioni \funcd{euidaccess} e +\funcd{eaccess} che ripetono lo stesso controllo usando però gli +identificatori del gruppo effettivo, verificando quindi le effettive capacità +di accesso ad un file. Le funzioni hanno entrambe lo stesso +prototipo\footnote{in realtà \func{eaccess} è solo un sinonimo di + \func{euidaccess} fornita per compatibilità con l'uso di questo nome in + altri sistemi.} che è del tutto identico a quello di \func{access}. Prendono +anche gli stessi valori e restituiscono gli stessi risultati e gli stessi +codici di errore. + +Per cambiare i permessi di un file il sistema mette ad disposizione due +funzioni \funcd{chmod} e \funcd{fchmod}, che operano rispettivamente su un +filename e su un file descriptor, i loro prototipi sono: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{sys/stat.h} + + \funcdecl{int chmod(const char *path, mode\_t mode)} Cambia i permessi del + file indicato da \param{path} al valore indicato da \param{mode}. + + \funcdecl{int fchmod(int fd, mode\_t mode)} Analoga alla precedente, ma usa + il file descriptor \param{fd} per indicare il file. + + \bodydesc{Le funzioni restituiscono zero in caso di successo e -1 per + un errore, in caso di errore \var{errno} può assumere i valori: + \begin{errlist} + \item[\errcode{EPERM}] l'\ids{UID} effettivo non corrisponde a quello del + proprietario del file o non è zero. + \item[\errcode{EROFS}] il file è su un filesystem in sola lettura. + \end{errlist} + ed inoltre \errval{EIO}; \func{chmod} restituisce anche \errval{EFAULT}, + \errval{ENAMETOOLONG}, \errval{ENOENT}, \errval{ENOMEM}, \errval{ENOTDIR}, + \errval{EACCES}, \errval{ELOOP}; \func{fchmod} anche \errval{EBADF}.} +\end{functions} + +Entrambe le funzioni utilizzano come secondo argomento \param{mode}, una +variabile dell'apposito tipo primitivo \type{mode\_t} (vedi +tab.~\ref{tab:intro_primitive_types}) utilizzato per specificare i permessi sui +file. + +\begin{table}[!htb] + \centering + \footnotesize + \begin{tabular}[c]{|c|c|l|} + \hline + \textbf{\param{mode}} & \textbf{Valore} & \textbf{Significato} \\ + \hline + \hline + \const{S\_ISUID} & 04000 & Set user ID \itindex{suid~bit}.\\ + \const{S\_ISGID} & 02000 & Set group ID \itindex{sgid~bit}.\\ + \const{S\_ISVTX} & 01000 & Sticky bit \itindex{sticky~bit}.\\ + \hline + \const{S\_IRWXU} & 00700 & L'utente ha tutti i permessi.\\ + \const{S\_IRUSR} & 00400 & L'utente ha il permesso di lettura.\\ + \const{S\_IWUSR} & 00200 & L'utente ha il permesso di scrittura.\\ + \const{S\_IXUSR} & 00100 & L'utente ha il permesso di esecuzione.\\ + \hline + \const{S\_IRWXG} & 00070 & Il gruppo ha tutti i permessi.\\ + \const{S\_IRGRP} & 00040 & Il gruppo ha il permesso di lettura.\\ + \const{S\_IWGRP} & 00020 & Il gruppo ha il permesso di scrittura.\\ + \const{S\_IXGRP} & 00010 & Il gruppo ha il permesso di esecuzione.\\ + \hline + \const{S\_IRWXO} & 00007 & Gli altri hanno tutti i permessi.\\ + \const{S\_IROTH} & 00004 & Gli altri hanno il permesso di lettura.\\ + \const{S\_IWOTH} & 00002 & Gli altri hanno il permesso di scrittura.\\ + \const{S\_IXOTH} & 00001 & Gli altri hanno il permesso di esecuzione.\\ + \hline + \end{tabular} + \caption{Valori delle costanti usate per indicare i vari bit di + \param{mode} utilizzato per impostare i permessi dei file.} + \label{tab:file_permission_const} +\end{table} + +Le costanti con cui specificare i singoli bit di \param{mode} sono riportate +in tab.~\ref{tab:file_permission_const}. Il valore di \param{mode} può essere +ottenuto combinando fra loro con un OR binario le costanti simboliche relative +ai vari bit, o specificato direttamente, come per l'omonimo comando di shell, +con un valore numerico (la shell lo vuole in ottale, dato che i bit dei +permessi sono divisibili in gruppi di tre), che si può calcolare direttamente +usando lo schema si utilizzo dei bit illustrato in +fig.~\ref{fig:file_perm_bit}. + +Ad esempio i permessi standard assegnati ai nuovi file (lettura e scrittura +per il proprietario, sola lettura per il gruppo e gli altri) sono +corrispondenti al valore ottale $0644$, un programma invece avrebbe anche il +bit di esecuzione attivo, con un valore di $0755$, se si volesse attivare il +bit \itindex{suid~bit} \acr{suid} il valore da fornire sarebbe $4755$. + +Il cambiamento dei permessi di un file eseguito attraverso queste funzioni ha +comunque alcune limitazioni, previste per motivi di sicurezza. L'uso delle +funzioni infatti è possibile solo se l'\ids{UID} effettivo del processo +corrisponde a quello del proprietario del file o dell'amministratore, +altrimenti esse falliranno con un errore di \errcode{EPERM}. + +Ma oltre a questa regola generale, di immediata comprensione, esistono delle +limitazioni ulteriori. Per questo motivo, anche se si è proprietari del file, +non tutti i valori possibili di \param{mode} sono permessi o hanno effetto; +in particolare accade che: +\begin{enumerate} +\item siccome solo l'amministratore può impostare lo \itindex{sticky~bit} + \textit{sticky bit}, se l'\ids{UID} effettivo del processo non è zero esso + viene automaticamente cancellato (senza notifica di errore) qualora sia + stato indicato in \param{mode}. +\item per quanto detto in sez.~\ref{sec:file_ownership_management} riguardo la + creazione dei nuovi file, si può avere il caso in cui il file creato da un + processo è assegnato ad un gruppo per il quale il processo non ha privilegi. + Per evitare che si possa assegnare il bit \itindex{sgid~bit} \acr{sgid} ad + un file appartenente ad un gruppo per cui non si hanno diritti, questo viene + automaticamente cancellato da \param{mode} (senza notifica di errore) + qualora il gruppo del file non corrisponda a quelli associati al processo + (la cosa non avviene quando l'\ids{UID} effettivo del processo è zero). +\end{enumerate} + +Per alcuni filesystem\footnote{i filesystem più comuni (\textsl{ext2}, + \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 +quando il file viene creato. Le funzioni dell'interfaccia nativa di Unix, come +vedremo in sez.~\ref{sec:file_open}, permettono di indicare esplicitamente i +permessi di creazione di un file, ma questo non è possibile per le funzioni +dell'interfaccia standard ANSI C che non prevede l'esistenza di utenti e +gruppi, ed inoltre il problema si pone anche per l'interfaccia nativa quando i +permessi non vengono indicati esplicitamente. + +\itindbeg{umask} + +Per le funzioni dell'interfaccia standard ANSI C l'unico riferimento possibile +è quello della modalità di apertura del nuovo file (lettura/scrittura o sola +lettura), che però può fornire un valore che è lo stesso per tutti e tre i +permessi di sez.~\ref{sec:file_perm_overview} (cioè $666$ nel primo caso e +$222$ nel secondo). Per questo motivo il sistema associa ad ogni +processo\footnote{è infatti contenuta nel campo \var{umask} della struttura + \kstruct{fs\_struct}, vedi fig.~\ref{fig:proc_task_struct}.} una maschera +di bit, la cosiddetta \textit{umask}, che viene utilizzata per impedire che +alcuni permessi possano essere assegnati ai nuovi file in sede di creazione. I +bit indicati nella maschera vengono infatti cancellati dai permessi quando un +nuovo file viene creato.\footnote{l'operazione viene fatta sempre: anche + qualora si indichi esplicitamente un valore dei permessi nelle funzioni di + creazione che lo consentono, i permessi contenuti nella \textit{umask} + verranno tolti.} + +La funzione che permette di impostare il valore di questa maschera di +controllo è \funcd{umask}, ed il suo prototipo è: +\begin{prototype}{stat.h} +{mode\_t umask(mode\_t mask)} + +Imposta la maschera dei permessi dei bit al valore specificato da \param{mask} +(di cui vengono presi solo i 9 bit meno significativi). + + \bodydesc{La funzione ritorna il precedente valore della maschera. È una + delle poche funzioni che non restituisce codici di errore.} +\end{prototype} + +In genere si usa questa maschera per impostare un valore predefinito che +escluda preventivamente alcuni permessi (usualmente quello di scrittura per il +gruppo e gli altri, corrispondente ad un valore per \param{mask} pari a +$022$). In questo modo è possibile cancellare automaticamente i permessi non +voluti. Di norma questo valore viene impostato una volta per tutte al login a +$022$, e gli utenti non hanno motivi per modificarlo. + +\itindend{umask} + + +\subsection{La gestione della titolarità dei file} +\label{sec:file_ownership_management} + +Vedremo in sez.~\ref{sec:file_base_func} con quali funzioni si possono creare +nuovi file, in tale occasione vedremo che è possibile specificare in sede di +creazione quali permessi applicare ad un file, però non si può indicare a +quale utente e gruppo esso deve appartenere. Lo stesso problema si presenta +per la creazione di nuove directory (procedimento descritto in +sez.~\ref{sec:file_dir_creat_rem}). + +Lo standard POSIX prescrive che l'\ids{UID} del nuovo file corrisponda +all'\ids{UID} effettivo del processo che lo crea; per il \ids{GID} invece +prevede due diverse possibilità: +\begin{itemize*} +\item il \ids{GID} del file corrisponde al \ids{GID} effettivo del processo. +\item il \ids{GID} del file corrisponde al \ids{GID} della directory in cui + esso è creato. +\end{itemize*} +in genere BSD usa sempre la seconda possibilità, che viene per questo chiamata +semantica BSD. Linux invece segue quella che viene chiamata semantica SVr4; di +norma cioè il nuovo file viene creato, seguendo la prima opzione, con il +\ids{GID} del processo, se però la directory in cui viene creato il file ha il +bit \acr{sgid} impostato allora viene usata la seconda opzione. + +Usare la semantica BSD ha il vantaggio che il \ids{GID} viene sempre +automaticamente propagato, restando coerente a quello della directory di +partenza, in tutte le sotto-directory. + +La semantica SVr4 offre la possibilità di scegliere, ma per ottenere lo stesso +risultato di coerenza che si ha con BSD necessita che quando si creano nuove +directory venga anche propagato anche il bit \acr{sgid}. Questo è il +comportamento predefinito del comando \cmd{mkdir}, ed è in questo modo ad +esempio che le varie distribuzioni assicurano che le sotto-directory create +nella home di un utente restino sempre con il \ids{GID} del gruppo primario +dello stesso. + +La presenza del bit \acr{sgid} è inoltre molto comoda quando si hanno +directory contenenti file condivisi all'intero di un gruppo in cui possono +scrivere tutti i membri dello stesso, dato che assicura che i file che gli +utenti vi creano appartengano sempre allo stesso gruppo. Questo non risolve +però completamente i problemi di accesso da parte di altri utenti dello stesso +gruppo, in quanto i permessi assegnati al gruppo potrebbero non essere +sufficienti; in tal caso si deve aver cura di usare un valore di +\itindex{umask} \textit{umask} che ne lasci di sufficienti.\footnote{in tal + caso si può assegnare agli utenti del gruppo una \textit{umask} di $002$, + anche se la soluzione migliore in questo caso è usare una ACL di default + (vedi sez.~\ref{sec:file_ACL}).} + +Come avviene nel caso dei permessi il sistema fornisce anche delle funzioni, +\funcd{chown}, \funcd{fchown} e \funcd{lchown}, che permettono di cambiare sia +l'utente che il gruppo a cui un file appartiene; i rispettivi prototipi sono: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{sys/stat.h} + + \funcdecl{int chown(const char *path, uid\_t owner, gid\_t group)} + \funcdecl{int fchown(int fd, uid\_t owner, gid\_t group)} + \funcdecl{int lchown(const char *path, uid\_t owner, gid\_t group)} + + Le funzioni cambiano utente e gruppo di appartenenza di un file ai valori + specificati dalle variabili \param{owner} e \param{group}. + + \bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 per un + errore, nel qual caso caso \var{errno} assumerà i valori: + \begin{errlist} + \item[\errcode{EPERM}] l'\ids{UID} effettivo non corrisponde a quello del + proprietario del file o non è zero, o utente e gruppo non sono validi + \end{errlist} + Oltre a questi entrambe restituiscono gli errori \errval{EROFS} e + \errval{EIO}; \func{chown} restituisce anche \errval{EFAULT}, + \errval{ENAMETOOLONG}, \errval{ENOENT}, \errval{ENOMEM}, \errval{ENOTDIR}, + \errval{EACCES}, \errval{ELOOP}; \func{fchown} anche \errval{EBADF}.} +\end{functions} + +Con Linux solo l'amministratore\footnote{o in generale un processo con la + \itindex{capabilities} capacità \const{CAP\_CHOWN}, vedi + sez.~\ref{sec:proc_capabilities}.} può cambiare il proprietario di un file; +in questo viene seguita la semantica usata da BSD che non consente agli utenti +di assegnare i loro file ad altri utenti evitando eventuali aggiramenti delle +quote. L'amministratore può cambiare sempre il gruppo di un file, il +proprietario può cambiare il gruppo solo dei file che gli appartengono e solo +se il nuovo gruppo è il suo gruppo primario o uno dei gruppi di cui fa parte. + +La funzione \func{chown} segue i link simbolici, per operare direttamente su +un link simbolico si deve usare la funzione \func{lchown}.\footnote{fino alla + versione 2.1.81 in Linux \func{chown} non seguiva i link simbolici, da + allora questo comportamento è stato assegnato alla funzione \func{lchown}, + introdotta per l'occasione, ed è stata creata una nuova system call per + \func{chown} che seguisse i link simbolici.} La funzione \func{fchown} opera +su un file aperto, essa è mutuata da BSD, ma non è nello standard POSIX. +Un'altra estensione rispetto allo standard POSIX è che specificando -1 come +valore per \param{owner} e \param{group} i valori restano immutati. + +Quando queste funzioni sono chiamate con successo da un processo senza i +privilegi di root entrambi i bit \itindex{suid~bit} \acr{suid} e +\itindex{sgid~bit} \acr{sgid} vengono cancellati. Questo non avviene per il +bit \acr{sgid} nel caso in cui esso sia usato (in assenza del corrispondente +permesso di esecuzione) per indicare che per il file è attivo il +\itindex{mandatory~locking} \textit{mandatory locking} (vedi +sez.~\ref{sec:file_mand_locking}). + + +\subsection{Un quadro d'insieme sui permessi} +\label{sec:file_riepilogo} + +Avendo affrontato in maniera separata il comportamento delle varie funzioni +che operano sui permessi dei file ed avendo trattato in sezioni diverse il +significato dei singoli bit dei permessi, vale la pena di fare un riepilogo in +cui si riassumano le caratteristiche di ciascuno di essi, in modo da poter +fornire un quadro d'insieme. + +\begin{table}[!htb] + \centering + \footnotesize + \begin{tabular}[c]{|c|c|c|c|c|c|c|c|c|c|c|c|l|} + \hline + \multicolumn{3}{|c|}{special}& + \multicolumn{3}{|c|}{user}& + \multicolumn{3}{|c|}{group}& + \multicolumn{3}{|c|}{other}& + \multirow{2}{*}{\textbf{Significato per i file}} \\ + \cline{1-12} + \acr{s}&\acr{s}&\acr{t}&r&w&x&r&w&x&r&w&x& \\ + \hline + \hline + 1&-&-&-&-&-&-&-&-&-&-&-&Se eseguito ha i permessi del proprietario.\\ + -&1&-&-&-&1&-&-&-&-&-&-&Se eseguito ha i permessi del gruppo proprietario.\\ + -&1&-&-&-&0&-&-&-&-&-&-&Il \itindex{mandatory~locking} + \textit{mandatory locking} è abilitato.\\ + -&-&1&-&-&-&-&-&-&-&-&-&Non utilizzato.\\ + -&-&-&1&-&-&-&-&-&-&-&-&Permesso di lettura per il proprietario.\\ + -&-&-&-&1&-&-&-&-&-&-&-&Permesso di scrittura per il proprietario.\\ + -&-&-&-&-&1&-&-&-&-&-&-&Permesso di esecuzione per il proprietario.\\ + -&-&-&-&-&-&1&-&-&-&-&-&Permesso di lettura per il gruppo proprietario.\\ + -&-&-&-&-&-&-&1&-&-&-&-&Permesso di scrittura per il gruppo proprietario.\\ + -&-&-&-&-&-&-&-&1&-&-&-&Permesso di esecuzione per il gruppo proprietario.\\ + -&-&-&-&-&-&-&-&-&1&-&-&Permesso di lettura per tutti gli altri.\\ + -&-&-&-&-&-&-&-&-&-&1&-&Permesso di scrittura per tutti gli altri.\\ + -&-&-&-&-&-&-&-&-&-&-&1&Permesso di esecuzione per tutti gli altri.\\ + \hline + \hline + \multicolumn{3}{|c|}{special}& + \multicolumn{3}{|c|}{user}& + \multicolumn{3}{|c|}{group}& + \multicolumn{3}{|c|}{other}& + \multirow{2}{*}{\textbf{Significato per le directory}} \\ + \cline{1-12} + \acr{s}&\acr{s}&\acr{t}&r&w&x&r&w&x&r&w&x& \\ + \hline + \hline + 1&-&-&-&-&-&-&-&-&-&-&-&Non utilizzato.\\ + -&1&-&-&-&-&-&-&-&-&-&-&Propaga il gruppo proprietario ai nuovi file + creati.\\ + -&-&1&-&-&-&-&-&-&-&-&-&Limita l'accesso in scrittura dei file nella + directory.\\ + -&-&-&1&-&-&-&-&-&-&-&-&Permesso di visualizzazione per il proprietario.\\ + -&-&-&-&1&-&-&-&-&-&-&-&Permesso di aggiornamento per il proprietario.\\ + -&-&-&-&-&1&-&-&-&-&-&-&Permesso di attraversamento per il proprietario.\\ + -&-&-&-&-&-&1&-&-&-&-&-&Permesso di visualizzazione per il gruppo + proprietario.\\ + -&-&-&-&-&-&-&1&-&-&-&-&Permesso di aggiornamento per il gruppo + proprietario.\\ + -&-&-&-&-&-&-&-&1&-&-&-&Permesso di attraversamento per il gruppo + proprietario.\\ + -&-&-&-&-&-&-&-&-&1&-&-&Permesso di visualizzazione per tutti gli altri.\\ + -&-&-&-&-&-&-&-&-&-&1&-&Permesso di aggiornamento per tutti gli altri.\\ + -&-&-&-&-&-&-&-&-&-&-&1&Permesso di attraversamento per tutti gli altri.\\ + \hline + \end{tabular} + \caption{Tabella riassuntiva del significato dei bit dei permessi per un + file e directory.} + \label{tab:file_fileperm_bits} +\end{table} + +Nella parte superiore di tab.~\ref{tab:file_fileperm_bits} si è riassunto il +significato dei vari bit dei permessi per un file ordinario; per quanto +riguarda l'applicazione dei permessi per proprietario, gruppo ed altri si +ricordi quanto illustrato in sez.~\ref{sec:file_perm_overview}. Per +compattezza, nella tabella si sono specificati i bit di \itindex{suid~bit} +\textit{suid}, \itindex{sgid~bit} \textit{sgid} e \textit{sticky} +\itindex{sticky~bit} con la notazione illustrata anche in +fig.~\ref{fig:file_perm_bit}. Nella parte inferiore si sono invece riassunti +i significati dei vari bit dei permessi per una directory; anche in questo +caso si è riapplicato ai bit di \itindex{suid~bit} \textit{suid}, +\itindex{sgid~bit} \textit{sgid} e \textit{sticky} \itindex{sticky~bit} la +notazione illustrata in fig.~\ref{fig:file_perm_bit}. + +Si ricordi infine che i permessi non hanno alcun significato per i link +simbolici, mentre per i \index{file!di~dispositivo} file di dispositivo hanno +senso soltanto i permessi di lettura e scrittura, che si riflettono sulla +possibilità di compiere dette operazioni sul dispositivo stesso. + +Nella tabella si è indicato con il carattere ``-'' il fatto che il valore del +bit in questione non è influente rispetto a quanto indicato nella riga della +tabella; la descrizione del significato fa riferimento soltanto alla +combinazione di bit per i quali è stato riportato esplicitamente un valore. +Si rammenti infine che il valore dei bit dei permessi non ha alcun effetto +qualora il processo possieda i privilegi di amministratore. + + +\section{Caratteristiche e funzionalità avanzate} +\label{sec:file_dir_advances} + +Tratteremo qui alcune caratteristiche e funzionalità avanzate della gestione +di file e directory, affrontando anche una serie di estensioni +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} + +\itindbeg{Extended~Attributes} + +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. + +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. + +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. + +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}[htb] + \centering + \footnotesize + \begin{tabular}{|l|p{12cm}|} + \hline + \textbf{Nome} & \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)} 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{I nomi utilizzati valore di \texttt{namespace} per distinguere le + varie classi di \textit{Extended Attributes}.} + \label{tab:extended_attribute_class} +\end{table} + + +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 \itindex{capabilities} + \textit{capability} \const{CAP\_SYS\_ADMIN}. + +\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} \itindex{capabilities} + \const{CAP\_FOWNER}.\footnote{vale a dire una politica di accesso analoga a + quella impiegata per gli ordinari permessi dei file.} + +\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 \itindex{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. + +\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.} + + 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 \itindex{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 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/types.h} + \headdecl{attr/xattr.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)} + + Le funzioni leggono il valore di un attributo esteso. + + \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} + 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 \textit{pathname} che indica il file di cui si vuole richiedere un +attributo, la sola differenza è che la seconda, se il \textit{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.} + +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/types.h} + \headdecl{attr/xattr.h} + + \funcdecl{int setxattr(const char *path, const char *name, const void + *value, size\_t size, int flags)} + + \funcdecl{int lsetxattr(const char *path, const char *name, const void + *value, size\_t size, int flags)} + + \funcdecl{int fsetxattr(int filedes, const char *name, const void *value, + size\_t size, int flags)} + + Impostano il valore di un attributo esteso. + + \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} + +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'è. + +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} + + \funcdecl{ssize\_t listxattr(const char *path, char *list, size\_t size)} + + \funcdecl{ssize\_t llistxattr(const char *path, char *list, size\_t size)} + + \funcdecl{ssize\_t flistxattr(int filedes, char *list, size\_t size)} + + Leggono la lista degli attributi estesi di un file. + + \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} + +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 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. + +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. + +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)} + + \funcdecl{int lremovexattr(const char *path, const char *name)} + + \funcdecl{int fremovexattr(int filedes, const char *name)} + + + Rimuovono un attributo esteso di un file. + + \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} + +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} + + +\subsection{Le \textit{Access Control List}} +\label{sec:file_ACL} + +% la documentazione di sistema è nei pacchetti libacl1-dev e acl +% vedi anche http://www.suse.de/~agruen/acl/linux-acls/online/ + +\itindbeg{Access~Control~List~(ACL)} + +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 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. + +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}. + +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. + +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. + +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 \itindex{capabilities} \const{CAP\_FOWNER}. + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}{|l|p{8cm}|} + \hline + \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.\\ + \hline + \end{tabular} + \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. + +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. + +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. + +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}.} + +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}. + +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. + +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'\ids{UID} del processo è nullo l'accesso è sempre garantito senza + nessun controllo. +\item Se l'\ids{UID} 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'\ids{UID} 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 \ids{GID} del processo o uno dei \ids{GID} 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 \ids{GID} del processo o uno dei \ids{GID} 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*} + +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{sys/acl.h} + + \funcdecl{acl\_t acl\_init(int count)} + + 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 \val{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. + \end{errlist} +} +\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 \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}''. + +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{sys/acl.h} + + \funcdecl{int acl\_free(void * obj\_p)} + + 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} + +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 è: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{sys/acl.h} + + \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{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} +} +\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. + +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{sys/acl.h} + + \funcdecl{acl\_t acl\_from\_mode(mode\_t mode)} + + 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}. + +} +\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. + +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} + + \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}. + +} +\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 +\textit{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}. + +\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} + +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 è: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{sys/acl.h} + + \funcdecl{acl\_t acl\_from\_text(const char *buf\_p)} + + 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} + +} +\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. + +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)} + + 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} + +} +\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 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)} + + 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} -\subsection{La titolarità di nuovi file e directory} -\label{sec:filedir_ownership} +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. -Come spiegato in \secref{} per creare un nuovo file in una directory occorre -avere il permesso di scrittura, ma +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 + \footnotesize + \begin{tabular}{|l|p{8cm}|} + \hline + \textbf{Tipo} & \textbf{Descrizione} \\ + \hline + \hline + \const{TEXT\_ABBREVIATE} & stampa le voci in forma abbreviata.\\ + \const{TEXT\_NUMERIC\_IDS} & non effettua la risoluzione numerica di + \ids{UID} e \ids{GID}.\\ + \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{Possibili valori per l'argomento \param{options} di + \func{acl\_to\_any\_text}.} + \label{tab:acl_to_text_options} +\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)} -\subsection{La funzione \texttt{access}} -\label{sec:filedir_access} + 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} -\subsection{La funzione \texttt{umask}} -\label{sec:filedir_umask} +} +\end{functions} +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. -\subsection{Le funzioni \texttt{chmod} e \texttt{fchmod}} -\label{sec:filedir_chmod} +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)} -\subsection{Le funzioni \texttt{chown}, \texttt{fchown} e \texttt{lchown}} -\label{sec:filedir_chown} + 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}. -%La struttura fondamentale che contiene i dati essenziali relativi ai file è il -%cosiddetto \textit{inode}; questo conterrà informazioni come il -%tipo di file (file di dispositivo, directory, file di dati, per un elenco -%completo vedi \ntab), i permessi (vedi \secref{sec:file_perms}), le date (vedi -%\secref{sec:file_times}). +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} -\section{La manipolazione delle caratteristiche dei files} -\label{sec:filedir_infos} +} +\end{functions} -Come spiegato in \secref{sec:fileintr_filesystem} tutte le informazioni -generali relative alle caratteristiche di ciascun file sono mantenute -nell'inode. Vedremo in questa sezione come sia possibile accedervi usando la -funzione \texttt{stat} ed esamineremo alcune funzioni utilizzabili per -manipolare una parte di questa informazione. Tutto quello che invece riguarda -il meccanismo di controllo di accesso ad i file e le relative funzioni di -manipolazione sarà invece esaminato in \secref{sec:filedir_access_control}. +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. -\subsection{Le funzioni \texttt{stat}, \texttt{fstat} e \texttt{lstat}} -\label{sec:filedir_stat} + \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 lettura delle informazioni relative ai file è fatta attraverso la famiglia -delle funzioni \func{stat}, che è la funzione che il comando \cmd{ls} usa -per poter stampare tutti i dati dei files. I prototipi di queste funzioni sono -i seguenti: +La funzione consente di assegnare la ACL contenuta in \param{acl} al file o +alla directory indicate dal \textit{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 +\param{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 + \textit{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/stat.h} - \headdecl{unistd.h} - - \funcdecl{int stat(const char *file\_name, struct stat *buf)} Legge le - informazione del file specificato da \var{file\_name} e le inserisce in - \var{buf}. - - \funcdecl{int lstat(const char *file\_name, struct stat *buf)} Identica a - \func{stat} eccetto che se il \var{file\_name} è un link simbolico vengono - lette le informazioni relativa ad esso e non al file a cui fa riferimento. + \headdecl{sys/acl.h} - \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 \var{filedes}. - - Le funzioni restituiscono zero in caso di successo e -1 per un errore, in - caso di errore \texttt{errno} viene settato ai valori: + \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 \texttt{EACCESS} non c'è il permesso di accedere al file. - \item \texttt{ENOTDIR} una componente del pathname non è una directory. - \item \texttt{EMLOOP} ci sono troppi link simbolici nel pathname. - \item \texttt{EFAULT} i puntatori usati sono fuori dallo spazio di indirizzi - del processo. - \item \texttt{ENOMEM} il kernel non ha a disposizione memoria sufficiente a - completare l'operazione. - \item \texttt{ENAMETOOLONG} il filename è troppo lungo. + \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 struttura \texttt{stat} è definita nell'header \texttt{sys/stat.h} e in -generale dipende dall'implementazione, la versione usata da Linux è mostrata -in \nfig, così come riportata dalla man page (in realtà la definizione -effettivamente usata nel kernel dipende dall'architettura e ha altri campi -riservati per estensioni come tempi più precisi, o per il padding dei campi). - -\begin{figure}[!htb] - \footnotesize - \centering - \begin{minipage}[c]{15cm} - \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{} -struct stat { - dev_t st_dev; /* device */ - ino_t st_ino; /* inode */ - mode_t st_mode; /* protection */ - nlink_t st_nlink; /* number of hard links */ - uid_t st_uid; /* user ID of owner */ - gid_t st_gid; /* group ID of owner */ - dev_t st_rdev; /* device type (if inode device) */ - off_t st_size; /* total size, in bytes */ - unsigned long st_blksize; /* blocksize for filesystem I/O */ - unsigned long st_blocks; /* number of blocks allocated */ - time_t st_atime; /* time of last access */ - time_t st_mtime; /* time of last modification */ - time_t st_ctime; /* time of last change */ -}; - \end{lstlisting} - \end{minipage} - \normalsize - \caption{La struttura \texttt{stat} per la lettura delle informazioni dei - file} - \label{fig:filedir_stat_struct} -\end{figure} +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)} -Si noti come i vari membri della struttura siano specificati come tipi nativi -del sistema (di quelli definiti in \tabref{tab:xxx_sys_types}, e dichiarati in -\texttt{sys/types.h}). + 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} -\subsection{I tipi di file} -\label{sec:filedir_file_types} +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 \ids{UID} e \ids{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}. -Come riportato in \tabref{tab:fileintr_file_types} in Linux oltre ai file e -alle directory esistono vari altri oggetti che possono stare su un filesystem; -il tipo di file è ritornato dalla \texttt{stat} nel campo \texttt{st\_mode}. -Dato che il valore numerico può variare a seconda delle implementazioni, lo -standard POSIX definisce un insieme di macro per verificare il tipo di files, -queste vengono usate anche da Linux che supporta pure le estensioni per link -simbolici e socket definite da BSD, l'elenco completo di tutte le macro -definite in GNU/Linux è riportato in \ntab: \begin{table}[htb] \centering \footnotesize - \begin{tabular}[c]{|l|l|} + \begin{tabular}{|l|p{10cm}|} \hline - Macro & Tipo del file \\ + \textbf{Comando} & \textbf{Descrizione} \\ \hline \hline - \macro{S\_ISREG(m)} & file regolare \\ - \macro{S\_ISDIR(m)} & directory \\ - \macro{S\_ISCHR(m)} & device a caraetteri \\ - \macro{S\_ISBLK(m)} & device a blocchi\\ - \macro{S\_ISFIFO(m)} & fifo \\ - \macro{S\_ISLNK(m)} & link simbolico \\ - \macro{S\_ISSOCK(m)} & socket \\ - \hline + \const{Q\_QUOTAON} & Attiva l'applicazione delle quote disco per il + filesystem indicato da \param{dev}, si deve passare + in \param{addr} il \textit{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{Macro per i tipi di file (definite in \texttt{sys/stat.h})} - \label{tab:filedir_file_type_macro} + \caption{Possibili valori per l'argomento \param{subcmd} di + \macro{QCMD}.} + \label{tab:quotactl_commands} \end{table} -Oltre a queste macro è possibile usare direttamente il valore di -\var{st\_mode} per ricavare il significato dei vari bit in esso memorizzati, -per questo sempre in \texttt{sys/stat.h} sono definiti i flag riportati in -\ntab: + +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}[c]{|l|c|l|} + \begin{tabular}{|l|p{10cm}|} \hline - Flag & Valore & Significato \\ + \textbf{Identificatore} & \textbf{Descrizione} \\ \hline \hline - \macro{S\_IFMT} & 0170000 & bitmask per i bit del tipo di file \\ - \macro{S\_IFSOCK} & 0140000 & socket \\ - \macro{S\_IFLNK} & 0120000 & link simbolico \\ - \macro{S\_IFREG} & 0100000 & file regolare \\ - \macro{S\_IFBLK} & 0060000 & device a blocchi \\ - \macro{S\_IFDIR} & 0040000 & directory \\ - \macro{S\_IFCHR} & 0020000 & device a caratteri \\ - \macro{S\_IFIFO} & 0010000 & fifo \\ + \const{QFMT\_VFS\_OLD}& il vecchio (ed obsoleto) formato delle quote.\\ + \const{QFMT\_VFS\_V0} & la versione 0 usata dal VFS di Linux (supporta + \ids{UID} e \ids{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 + \ids{UID} e \ids{GID} a 32 bit e limiti fino a + $2^{64}$ byte e $2^{64}$ file.\\ \hline - \macro{S\_ISUID} & 0004000 & set UID bit \\ - \macro{S\_ISGID} & 0002000 & set GID bit \\ - \macro{S\_ISVTX} & 0001000 & sticky bit \\ + \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 - \macro{S\_IRWXU} & 00700 & bitmask per i permessi del proprietario \\ - \macro{S\_IRUSR} & 00400 & il proprietario ha permesso di lettura \\ - \macro{S\_IWUSR} & 00200 & il proprietario ha permesso di scrittura \\ - \macro{S\_IXUSR} & 00100 & il proprietario ha permesso di esecuzione\\ + \textbf{Costante} & \textbf{Descrizione} \\ \hline - \macro{S\_IRWXG} & 00070 & bitmask per i permessi del gruppo \\ - \macro{S\_IRGRP} & 00040 & il gruppo ha permesso di lettura \\ - \macro{S\_IWGRP} & 00020 & il gruppo ha permesso di scrittura \\ - \macro{S\_IXGRP} & 00010 & il gruppo ha permesso di esecuzione \\ \hline - \macro{S\_IRWXO} & 00007 & bitmask per i permessi di tutti gli altri\\ - \macro{S\_IROTH} & 00004 & gli altri hanno permesso di lettura \\ - \macro{S\_IWOTH} & 00002 & gli altri hanno permesso di esecuzione \\ - \macro{S\_IXOTH} & 00001 & gli altri hanno permesso di esecuzione \\ - \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 l'identificazione dei vari bit che compongono il campo - \var{st\_mode} (definite in \texttt{sys/stat.h})} - \label{tab:filedir_file_mode_flags} + \caption{Costanti per il campo \val{dqb\_valid} di \struct{dqblk}.} + \label{tab:quotactl_qif_const} \end{table} -Il primo valore definisce la maschera dei bit usati nei quali viene -memorizzato il tipo di files, mentre gli altri possono essere usati per -effettuare delle selezioni sul tipo di file voluto, combinando opportunamente -i vari flag; ad esempio se si volesse controllare se un file è una directory o -un file ordinario si potrebbe definire la condizione: -\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{} -#define IS_FILE_DIR(x) (((x) & S_IFMT) & (S_IFDIR | S_IFREG)) -\end{lstlisting} -in cui prima si estraggono da \var{st\_mode} i bit relativi al tipo di file e -poi si effettua il confronto con la combinazione di tipi scelta. -\subsection{La dimensione dei file} -\label{sec:filedir_file_size} +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}. -Il membro \var{st\_size} contiene la dimensione del file in byte (se il file -è un file normale, nel caso di un link simbolico al dimensione è quella del -pathname che contiene). - -Il campo \var{st\_blocks} definisce la lunghezza del file in blocchi di 512 -bytes. Il campo \var{st\_blksize} infine definisce la dimensione preferita per -i trasferimenti sui file (che è la dimensione usata anche dalle librerie del C -per l'interfaccia degli stream); scrivere sul file a blocchi di dati di -dimensione inferiore sarebbe inefficiente. +\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} -Si tenga conto che 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 \textsl{buchi} (detti normalmente \textit{holes}) che -si formano tutte le volte che si va a scrivere su un file dopo aver eseguito -una \func{seek} (vedi \secref{sec:fileunix_lseek}) oltre la sua conclusione -corrente. +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. -In tal caso si avranno differenti risultati a seconda del modi in cui si -calcola la lunghezza del file, ad esempio il comando \cmd{du}, (che riporta il -numero di blocchi occupati) potrà dare una dimensione inferiore, mentre se si -legge dal file (ad esempio usando \cmd{wc -c}), dato che in tal caso per le -parti non scritte vengono restituiti degli zeri, si avrà lo stesso risultato -di \cmd{ls}. - -Se è sempre possibile allargare un file scrivendoci sopra od usando la -funzione \func{seek} per spostarsi oltre la sua fine. Esistono però anche casi -in cui si può avere bisogno di effettuare un troncamento scartando i dati al -di là della dimensione scelta come nuova fine del file. - -Un file può essere troncato a zero aprendolo con il flag \macro{O\_TRUNC}, ma -questo è un caso particolare; per qualunque altra dimensione si possono usare -le due funzioni: -\begin{functions} - \headdecl{unistd.h} \funcdecl{int truncate(const char *file\_name, off\_t - length)} Fa si che la dimensione del file \var{file\_name} sia troncata ad - un valore massimo specificato da \var{lenght}. - - \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 \var{fd}, - - Le funzioni restituiscono zero in caso di successo e -1 per un errore, in - caso di errore \texttt{errno} viene settato ai valori: - \begin{errlist} - \item \texttt{EACCESS} non c'è il permesso di accedere al file. - \item \texttt{ENOTDIR} una componente del pathname non è una directory. - \item \texttt{EMLOOP} ci sono troppi link simbolici nel pathname. - \item \texttt{EFAULT} i puntatori usati sono fuori dallo spazio di indirizzi - del processo. - \item \texttt{ENOMEM} il kernel non ha a disposizione memoria sufficiente a - completare l'operazione. - \item \texttt{ENOENT} il file non esiste. - \item \texttt{ENAMETOOLONG} il filename è troppo lungo. - \end{errlist} -\end{functions} +\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} -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; in quest'ultimo caso lo spazio viene riempito con -zeri (e in genere si ha la creazione di un hole nel file). +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} -\subsection{I tempi dei file} -\label{sec:filedir_file_times} +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 +\sysctlfile{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 +\sysctlfile{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} -Il sistema mantiene per ciascun file tre tempi. Questi sono registrati -nell'inode insieme agli altri attibuti del file e possono essere letti tramite -la funzione \func{stat}, che li restituisce attraverso tre campi della -struttura in \figref{fig:filedir_stat_struct}. Il significato di detti tempi e -dei relativi campi è riportato nello schema in \ntab: +\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 \ids{UID} reale 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 \ids{UID} +nullo a \ids{UID} 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 \ids{UID} effettivo nullo a non nullo + l'\textit{effective set} del processo viene totalmente azzerato, se + viceversa si passa da \ids{UID} effettivo non nullo a nullo il + \textit{permitted set} viene copiato nell'\textit{effective set}; +\item se si passa da \textit{file system} \ids{UID} 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 \ids{UID} 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 - \begin{tabular}[c]{|c|l|l|c|} + \footnotesize + \begin{tabular}{|l|p{10cm}|} \hline - Membro & Significato & Funzione&opzione \\ + \textbf{Flag} & \textbf{Descrizione} \\ \hline \hline - \var{st\_atime}& ultimo accesso ai dati del file &\func{read}& \cmd{-u}\\ - \var{st\_mtime}& ultima modifica ai dati del file &\func{write}& default\\ - \var{st\_ctime}& ultima modifica ai dati dell'inode&\func{chmod}, - \func{utime} & \cmd{-c} \\ + \const{SECURE\_KEEP\_CAPS}& Il processo non subisce la cancellazione delle + sue \textit{capabilities} quando tutti i suoi + \ids{UID} passano ad un valore non + nullo (regola di compatibilità per il cambio + di \ids{UID} 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 \ids{UID} + dei gruppi \textit{effective} e + \textit{file system} (regole di compatibilità + per il cambio di \ids{UID} nn.~1 e 2 del + precedente elenco).\\ + \const{SECURE\_NOROOT} & Il processo non assume nessuna capacità + aggiuntiva quando esegue un programma, anche + se ha \ids{UID} 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{I tre tempi associati a ciascun file} - \label{tab:filedir_file_times} + \caption{Costanti identificative dei flag che compongono la maschera dei + \textit{securebits}.} + \label{tab:securebits_values} \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{chage time} \var{st\_ctime}). Il primo -infatti fa riferimento ad una modifica del contenuto di un file, mentre il -secondo ad una modifica dell'inode; siccome esistono molte operazioni (come la -funzione \func{link} e molte altre che vedremo in seguito) che modificano solo -le informazioni contenute nell'inode senza toccare il file, diventa necessario -l'utilizzo di un altro tempo. - -Il sistema non tiene conto dell'ultimo accesso all'inode, pertanto funzioni -come \func{access} o \func{stat} non hanno alcuna influenza sui tre tempi. Il -tempo di ultimo accesso viene di solito usato per cancellare i file che non -servono più dopo un certo lasso di tempo (ad esempio \cmd{leafnode} cancella i -vecchi articoli sulla base di questo tempo). - -Il tempo di ultima modifica invece viene usato da \cmd{make} per decidere -quali file necessitano di essere ricompilati o (talvolta insieme anche al -tempo di cambiamento di stato) per decidere quali file devono essere -archiviati per il backup. Il comando \cmd{ls} (quando usato con le opzioni -\cmd{-l} o \cmd{-t}) mostra i tempi dei file secondo lo schema riportato -nell'ultima colonna di \curtab. - -L'effetto delle varie funzioni di manipolazione dei file sui tempi è -illustrato in \ntab. 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 files, che il sistema tratta in maniera del tutto analoga agli -altri. - -Per questo motivo tutte le volte che compiremo una operazione su un file che -comporta una modifica della sua directory entry, 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, mentre leggere o scrivere o -cambiarne i permessi ha effetti solo sui tempi del file. - -\begin{table}[htb] +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{include/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}[c]{|l|c|c|c|c|c|c|l|} + \begin{tabular}{|l|p{10.5cm}|} \hline - \multicolumn{1}{|c|}{Funzione} - &\multicolumn{3}{p{2cm}}{File o directory di riferimento} - &\multicolumn{3}{p{2cm}}{Directory genitrice del riferimento} - &\multicolumn{1}{|c|}{Note} \\ - \cline{2-7} - & \textsl{(a)} & \textsl{(m)}& \textsl{(c)} - & \textsl{(a)} & \textsl{(m)}& \textsl{(c)}& \\ + \textbf{Capacità}&\textbf{Descrizione}\\ \hline \hline - \func{chmod}, \func{fchmod} - & & &$\bullet$& & & & \\ - \func{chown}, \func{fchown} - & & &$\bullet$& & & & \\ - \func{creat} - &$\bullet$&$\bullet$&$\bullet$& &$\bullet$&$\bullet$& con - \macro{O\_CREATE} \\ \func{creat} - & &$\bullet$&$\bullet$& &$\bullet$&$\bullet$& - con \macro{O\_TRUNC} \\ \func{exec} - &$\bullet$& & & & & & \\ - \func{lchown} - & & &$\bullet$& & & & \\ - \func{link} - & & &$\bullet$& &$\bullet$&$\bullet$& \\ - \func{mkdir} - &$\bullet$&$\bullet$&$\bullet$& &$\bullet$&$\bullet$& \\ - \func{mkfifo} - &$\bullet$&$\bullet$&$\bullet$& &$\bullet$&$\bullet$& \\ - \func{open} - &$\bullet$&$\bullet$&$\bullet$& &$\bullet$&$\bullet$& con - \macro{O\_CREATE} \\ \func{open} - & &$\bullet$&$\bullet$& & & & con - \macro{O\_TRUNC} \\ \func{pipe} - &$\bullet$&$\bullet$&$\bullet$& & & & \\ - \func{read} - &$\bullet$& & & & & & \\ - \func{remove} - & & &$\bullet$& &$\bullet$&$\bullet$& using - \func{unlink}\\ \func{remove} - & & & & &$\bullet$&$\bullet$& using - \func{rmdir}\\ \func{rename} - & & &$\bullet$& &$\bullet$&$\bullet$& per entrambi - gli argomenti\\ \func{rmdir} - & & & & &$\bullet$&$\bullet$& \\ - \func{truncate}, \func{ftruncate} - & &$\bullet$&$\bullet$& & & & \\ - \func{unlink} - & & &$\bullet$& &$\bullet$&$\bullet$& \\ - \func{utime} - &$\bullet$&$\bullet$&$\bullet$& & & & \\ - \func{write} - & &$\bullet$&$\bullet$& & & & \\ +% +% 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} + \itindex{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{Effetti delle varie funzioni su tempi di ultimo accesso - \textsl{(a)}, ultima modifica \textsl{(m)} e ultimo cambiamento - \textsl{(c)}} - \label{tab:filedir_times_effects} + \caption{Le costanti che identificano le \textit{capabilities} presenti nel + kernel.} +\label{tab:proc_capabilities} \end{table} -Si noti infine come \var{st\_ctime} non abbia nulla a che fare con il tempo di -creazione del file, usato da molti altri sistemi operativi, che in unix non -esiste. +\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'\ids{UID} effettivo del + processo (o meglio l'\ids{UID} di filesystem, 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. + +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. + +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 \ids{UID} 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 \sysctlfile{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/capability.h} + \funcdecl{int capget(cap\_user\_header\_t hdrp, cap\_user\_data\_t datap)} + Legge le \textit{capabilities}. -\subsection{La funzione \texttt{utime}} -\label{sec:filedir_utime} + \funcdecl{int capset(cap\_user\_header\_t hdrp, const cap\_user\_data\_t + datap)} + Imposta le \textit{capabilities}. -I tempi di ultimo accesso e modifica possono essere cambiati usando la -funzione \func{utime}, il cui prototipo è: + + \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} -\begin{prototype}{utime.h} -{int utime(const char * filename, struct utimbuf *times)} - -Cambia i tempi di ultimo accesso e modifica dell'inode specificato da -\var{filename} secondo i campi \var{actime} e \var{modtime} di \var{times}. Se -questa è \macro{NULL} allora viene usato il tempo corrente. - -La funzione restituisce zero in caso di successo e -1 in caso di errore, nel -qual caso \var{errno} è settata opportunamente. -\begin{errlist} -\item \texttt{EACCESS} non si ha il permesso di scrittura sul file. -\item \texttt{ENOENT} \var{filename} non esiste. -\end{errlist} -\end{prototype} - -La struttura \var{utimebuf} usata da \func{utime} è definita come: -\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{} -struct utimbuf { - time_t actime; /* access time */ - time_t modtime; /* modification time */ -}; -\end{lstlisting} +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 +\headfile{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. -L'effetto della funzione e i privilegi necessari per eseguirla dipendono da -cosa è l'argomento \var{times}; se è \textit{NULL} la funzione setta 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). +\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} -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 l'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 device, scrivendo -direttamente sul disco senza passare attraverso il filesystem, ma ovviamente è -molto più complicato da realizzare. +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/capability.h} + \funcdecl{cap\_t cap\_init(void)} + Crea ed inizializza un \textit{capability state}. + + \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} +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/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} +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}. + +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{cap\_t cap\_dup(cap\_t cap\_p)} + Duplica un \textit{capability state} restituendone una copia. + + \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} -\section{La manipolazione di file e directory} +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. } + +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} -Come già accennato in \secref{sec:fileintr_filesystem} in un sistema unix-like -i file hanno delle caratteristiche specifiche dipendenti dall'architettura del -sistema, esamineremo qui allora le funzioni usate per la creazione di link -simbolici e diretti e per la gestione delle directory, approfondendo quanto -già accennato in precedenza. + \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} +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}. -\subsection{Le funzioni \texttt{link} e \texttt{unlink}} -\label{sec:fileintr_link} +\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} -Una delle caratteristiche comuni a vari sistemi operativi è quella di poter -creare dei nomi fittizi (alias o collegamenti) per potersi riferire allo -stesso file accedendovi da directory diverse. Questo è possibile anche in -ambiente unix, dove tali collegamenti sono usualmente chiamati \textit{link}, -ma data la struttura del sistema ci sono due metodi sostanzialmente diversi -per fare questa operazione. +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/capability.h} -Come spiegato in \secref{sec:fileintr_architecture} l'accesso al contenuto di -un file su disco avviene attraverso il suo inode, e il nome che si trova in -una directory è solo una etichetta associata ad un puntatore a detto inode. -Questo significa che la realizzazione di un link è immediata in quanto uno -stesso file può avere tanti nomi diversi allo stesso tempo, dati da -altrettante diverse associazioni allo stesso inode; si noti poi che nessuno di -questi nomi viene ad assumere una particolare preferenza rispetto agli altri. + \funcdecl{int cap\_clear\_flag(cap\_t cap\_p, cap\_flag\_t flag)} -Per aggiungere un nome ad un inode si utilizza la funzione \texttt{link}; si -suole chiamare questo tipo di associazione un collegamento diretto (o -\textit{hard link}). Il prototipo della funzione e le sue caratteristiche -principali, come risultano dalla man page, sono le seguenti: -\begin{prototype}{unistd.h} -{int link(const char * oldpath, const char * newpath)} - Crea un nuovo collegamento diretto al file indicato da \texttt{oldpath} - dandogli nome \texttt{newpath}. - - La funzione restituisce zero in caso di successo e -1 in caso di errore. La - variabile \texttt{errno} viene settata opportunamente, i principali codici - di errore sono: - \begin{errlist} - \item \texttt{EXDEV} \texttt{oldpath} e \texttt{newpath} non sono sullo - stesso filesystem. - \item \texttt{EPERM} il filesystem che contiene \texttt{oldpath} e - \texttt{newpath} non supporta i link diretti o è una directory. - \item \texttt{EEXIST} un file (o una directory) con quel nome esiste di - già. - \item \texttt{EMLINK} ci sono troppi link al file \texttt{oldpath} (il - numero massimo è specificato dalla variabile \texttt{LINK\_MAX}, vedi - \secref{sec:xxx_limits}). - \end{errlist} + Cancella dal \textit{capability state} \param{cap\_p} tutte le + \textit{capabilities} dell'insieme \param{flag}. -\end{prototype} - -La creazione di un nuovo collegamento diretto non copia il contenuto del file, -ma si limita ad aumentare di uno il numero di referenze al file (come si può -controllare con il campo \var{st\_nlink} di \var{stat}) aggiungendo il nuovo -nome ai precedenti. Si noti che uno stesso file può essere così richiamato in -diverse directory. - -Per quanto dicevamo in \secref{sec:fileintr_filesystem} la creazione del -collegamento diretto è possibile solo se entrambi i pathname sono nello stesso -filesystem; inoltre il filesystem deve supportare i collegamenti diretti (non è -il caso ad esempio del filesystem \texttt{vfat} di windows). - -La funzione opera sui file ordinari, come sugli altri oggetti del filesystem, -in alcuni filesystem solo l'amministratore è in grado di creare un -collegamento diretto ad un'altra directory, questo lo si fa perché in questo -caso è possibile creare dei circoli nel filesystem (vedi -\secref{sec:fileintr_symlink}) che molti programmi non sono in grado di -gestire e la cui rimozione diventa estremamente complicata (in genere occorre -far girare il programma \texttt{fsck} per riparare il filesystem); data la sua -pericolosità in generale nei filesystem usati in Linux questa caratteristica è -stata disabilitata, e la funzione restituisce l'errore \texttt{EPERM}. - -La rimozione di un file (o più precisamente della voce che lo referenzia) si -effettua con la funzione \texttt{unlink}; il suo prototipo è il seguente: - -\begin{prototype}{unistd.h}{int unlink(const char * pathname)} - Cancella il nome specificato dal pathname nella relativa directory e - decrementa il numero di riferimenti nel relativo inode. Nel caso di link - simbolico cancella il link simbolico; nel caso di socket, fifo o file di - dispositivo rimuove il nome, ma come per i file i processi che hanno aperto - uno di questi oggetti possono continuare ad utilizzarlo. - - La funzione restituisce zero in caso di successo e -1 per un errore, nel - qual caso il file non viene toccato. La variabile \texttt{errno} viene - settata secondo i seguenti codici di errore: - \begin{errlist} - \item \texttt{EISDIR} \var{pathname} si riferisce ad una directory - (valore specifico ritornato da linux che non consente l'uso di - \texttt{unlink} con le directory, e non conforme allo standard POSIX, che - prescrive invece l'uso di \texttt{EPERM} in caso l'operazione non sia - consentita o il processo non abbia privilegi sufficienti). - \item \texttt{EROFS} \var{pathname} è su un filesystem montato in sola - lettura. - \item \texttt{EISDIR} \var{pathname} fa riferimento a una directory. - \end{errlist} -\end{prototype} + \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} -Per cancellare una voce in una directory è necessario avere il permesso di -scrittura su di essa (dato che si va a rimuovere una voce dal suo contenuto) e -il diritto di esecuzione sulla directory che la contiene (torneremo in -dettaglio sui permessi e gli attributi fra poco), se inoltre lo -\textit{sticky} bit è settato occorrerà anche essere proprietari del file o -proprietari della directory (o root, per cui nessuna delle restrizioni è -applicata). - -Una delle caratteristiche di queste funzioni è che la creazione/rimozione -della nome dalla directory e l'incremento/decremento del numero di riferimenti -nell'inode deve essere una operazione atomica (cioè non interrompibile da -altri) processi, per questo entrambe queste funzioni sono realizzate tramite -una singola system call. - -Si ricordi infine che il file non viene eliminato dal disco fintanto che tutti -i riferimenti ad esso sono stati cancellati, solo quando il \textit{link - count} mantenuto nell'inode diventa zero lo spazio occupato viene rimosso. A -questo però si aggiunge una altra condizione, e cioè che non ci siano processi -che abbiano detto file aperto. Come accennato questa proprietà viene spesso -usata per essere sicuri di non lasciare file temporanei su disco in caso di -crash dei programmi; la tecnica è quella di aprire il file e chiamare -\texttt{unlink} subito dopo. - -\subsection{Le funzioni \texttt{remove} e \texttt{rename}} -\label{sec:fileintr_remove} - -Al contrario di quanto avviene con altri unix in Linux non è possibile usare -\texttt{unlink} sulle directory, per cancellare una directory si può usare la -funzione \texttt{rmdir} (vedi \secref{sec:filedir_dir_creat_rem}), oppure la -funzione \texttt{remove}. Questa è la funzione prevista dallo standard ANSI C -per cancellare un file o una directory (e funziona anche per i sistemi che non -supportano i link diretti), che per i file è identica alla \texttt{unlink} e -per le directory è identica alla \texttt{rmdir}: - -\begin{prototype}{stdio.h}{int remove(const char *pathname)} - Cancella un nome dal filesystem. Usa \texttt{unlink} per i file e - \texttt{rmdir} per le directory. - - La funzione restituisce zero in caso di successo e -1 per un errore, nel - qual caso il file non viene toccato. Per i codici di errori vedi quanto - riportato nella descrizione di \texttt{unlink} e \texttt{rmdir}. -\end{prototype} +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 \headfile{sys/capability.h}.} uno dei valori +illustrati in tab.~\ref{tab:cap_set_identifier}. -Per cambiare nome ad un file si usa invece la funzione \texttt{rename}, il -vantaggio nell'uso di questa funzione al posto della chiamata successiva di -\texttt{unlink} e \texttt{link} è che l'operazione è eseguita atomicamente, in -questo modo non c'è la possibilità che un processo che cerchi di accedere al -nuovo nome dopo che il vecchio è stato cambiato lo trovi mancante. - -\begin{prototype}{stdio.h} -{int rename(const char *oldpath, const char *newpath)} - Rinomina un file, spostandolo fra directory diverse quando richiesto. - - La funzione restituisce zero in caso di successo e -1 per un errore, nel - qual caso il file non viene toccato. La variabile \texttt{errno} viene - settata secondo i seguenti codici di errore: - \begin{errlist} - \item \texttt{EISDIR} \texttt{newpath} è una directory già esistente mentre - \texttt{oldpath} non è una directory. - \item \texttt{EXDEV} \texttt{oldpath} e \texttt{newpath} non sono sullo - stesso filesystem. - \item \texttt{ENOTEMPTY} \texttt{newpath} è una directory già esistente e - non vuota. - \item \texttt{EBUSY} o \texttt{oldpath} o \texttt{newpath} sono in uso da - parte di qualche processo (come directory di lavoro o come root) o del - sistema (come mount point). - \item \texttt{EINVAL} \texttt{newpath} contiene un prefisso di - \texttt{oldpath} o più in generale si è cercato di creare una directory - come sottodirectory di se stessa. - \item \texttt{EMLINK} \texttt{oldpath} ha già il massimo numero di link - consentiti o è una directory e la directory che contiene \texttt{newpath} - ha già il massimo numero di link. - \item \texttt{ENOTDIR} Uno dei componenti dei pathname non è una directory - o\texttt{oldpath} è una directory e \texttt{newpath} esiste e non è una - directory. - \item \texttt{EFAULT} o \texttt{oldpath} o \texttt{newpath} è fuori dello - spazio di indirizzi del processo. - \item \texttt{EACCESS} Non c'è il permesso di scrittura per la directory in - cui si vuole creare il nuovo link o una delle directory del pathname non - consente la ricerca (permesso di esecuzione). - \item \texttt{EPERM} le directory contenenti \texttt{oldpath} o - \texttt{newpath} hanno lo sticky bit attivo e i permessi del processo non - consentono rispettivamente la cancellazione e la creazione del file, o il - filesystem non supporta i link. - \item \texttt{ENAMETOOLONG} uno dei pathname è troppo lungo. - \item \texttt{ENOENT} Uno dei componenti del pathname non esiste o è un link - simbolico spezzato. - \item \texttt{ENOMEM} il kernel non ha a disposizione memoria sufficiente a - completare l'operazione. - \item \texttt{EROFS} I file sono su un filesystem montato in sola lettura. - \item \texttt{ELOOP} Ci sono troppi link simbolici nella risoluzione del - pathname. - \item \texttt{ENOSPC} Il device di destinazione non ha più spazio per la - nuova voce. - \end{errlist} -\end{prototype} +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/capability.h} + \funcdecl{int cap\_compare(cap\_t cap\_a, cap\_t cap\_b)} -\subsection{I link simbolici} -\label{sec:fileintr_symlink} + Confronta due \textit{capability state}. + + \bodydesc{La funzione ritorna 0 se i \textit{capability state} sono identici + ed un valore positivo se differiscono, non sono previsti errori.} +\end{functions} -Siccome la funzione \texttt{link} crea riferimenti agli inodes, essa può -funzionare soltanto per file che risiedono sullo stesso filesystem, dato che -in questo caso è garantita l'unicità dell'inode, e solo per un filesystem di -tipo unix. Inoltre in Linux non è consentito eseguire un link diretto ad una -directory. +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} -Per ovviare a queste limitazioni i sistemi unix supportano un'altra forma di -link (i cosiddetti \textit{soft link} o \textit{symbolic link}), che sono, -come avviene in altri sistemi operativi, dei file che contengono il -semplicemente il riferimento ad un altro file (o directory). In questo modo è -possibile effettuare link anche attraverso filesystem diversi e a directory, e -pure a file che non esistono ancora. - -Il sistema funziona in quanto i link simbolici sono contrassegnati come tali -al kernel (analogamente a quanto avviene per le directory) per cui la chiamata -ad una \texttt{open} o una \texttt{stat} su un link simbolico comporta la -lettura del contenuto del medesimo e l'applicazione della funzione al file -specificato da quest'ultimo. Invece altre funzioni come quelle per cancellare -o rinominare i file operano direttamente sul link simbolico (per l'elenco vedi -\ntab). Inoltre esistono funzioni apposite, come la \texttt{readlink} e la -\texttt{lstat} per accedere alle informazioni del link invece che a quelle del -file a cui esso fa riferimento. - -Le funzioni per operare sui link simbolici sono le seguenti, esse sono tutte -dichiarate nell'header file \texttt{unistd.h}. +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. + +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/capability.h} -\begin{prototype}{unistd.h} -{int symlink(const char * oldname, const char * newname)} - Crea un nuovo link simbolico al file indicato da \texttt{oldname} dandogli - nome \texttt{newname}. - - La funzione restituisce zero in caso di successo e -1 per un errore, in caso - di errore. La variabile \texttt{errno} viene settata secondo i codici di - errore standard di accesso ai file (trattati in dettaglio in - \secref{sec:filedir_access_control}) ai quali si aggiungono i seguenti: - \begin{errlist} - \item \texttt{EEXIST} Un file (o una directory) con quel nome esiste di - già. - \item \texttt{EROFS} La directory su cui si vuole inserire il nuovo link è - su un filesystem montato readonly. - \item \texttt{ENOSPC} La directory o il filesystem in cui si vuole creare il - link è piena e non c'è ulteriore spazio disponibile. - \item \texttt{ELOOP} Ci sono troppi link simbolici nella risoluzione di - \texttt{oldname} o di \texttt{newname}. - \end{errlist} -\end{prototype} + \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}. -Dato che la funzione \texttt{open} segue i link simbolici, è necessaria usare -un'altra funzione quando si vuole leggere il contenuto di un link simbolico, -questa funzione è la: + \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} -\begin{prototype}{unistd.h} -{int readlink(const char * path, char * buff, size\_t size)} - Legge il contenuto del link simbolico indicato da \texttt{path} nel buffer - \texttt{buff} di dimensione \texttt{size}. Non chiude la stringa con un - carattere nullo e la tronca a \texttt{size} nel caso il buffer sia troppo - piccolo per contenerla. - - La funzione restituisce il numero di caratteri letti dentro \texttt{buff} o - -1 per un errore, in caso di errore. La variabile \texttt{errno} viene - settata secondo i codici di errore: - \begin{errlist} - \item \texttt{EEXIST} Un file (o una directory) con quel nome esiste di - già. - \item \texttt{EROFS} La directory su cui si vuole inserire il nuovo link è - su un filesystem montato readonly. - \item \texttt{ENOSPC} La directory o il filesystem in cui si vuole creare il - link è piena e non c'è ulteriore spazio disponibile. - \item \texttt{ELOOP} Ci sono troppi link simbolici nella risoluzione di - \texttt{oldname} o di \texttt{newname}. - \end{errlist} -\end{prototype} +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}. + +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 + \headfile{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}. -In \ntab\ si è riportato un elenco dei comportamenti delle varie funzioni che -operano sui file rispetto ai link simbolici; specificando quali seguono il -link simbolico e quali possono operare direttamente sul suo contenuto. \begin{table}[htb] \centering \footnotesize - \begin{tabular}[c]{|l|c|c|} + \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 - Funzione & Segue il link & Non segue il link \\ - \hline - \hline - \func{access} & $\bullet$ & \\ - \func{chdir} & $\bullet$ & \\ - \func{chmod} & $\bullet$ & \\ - \func{chown} & & $\bullet$ \\ - \func{creat} & $\bullet$ & \\ - \func{exec} & $\bullet$ & \\ - \func{lchown} & $\bullet$ & $\bullet$ \\ - \func{link} & & \\ - \func{lstat} & & $\bullet$ \\ - \func{mkdir} & $\bullet$ & \\ - \func{mkfifo} & $\bullet$ & \\ - \func{mknod} & $\bullet$ & \\ - \func{open} & $\bullet$ & \\ - \func{opendir} & $\bullet$ & \\ - \func{pathconf} & $\bullet$ & \\ - \func{readlink} & & $\bullet$ \\ - \func{remove} & & $\bullet$ \\ - \func{rename} & & $\bullet$ \\ - \func{stat} & $\bullet$ & \\ - \func{truncate} & $\bullet$ & \\ - \func{unlink} & & $\bullet$ \\ - \hline \end{tabular} - \caption{Uso dei link simbolici da parte di alcune funzioni.} - \label{tab:filedir_symb_effect} + \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} -si noti che non si è specificato il comportamento delle funzioni che operano -con i file descriptor, in quanto la gestione del link simbolico viene in -genere effettuata dalla funzione che restituisce il file descriptor -(normalmente la \func{open}). -\begin{figure}[htb] - \centering - \includegraphics[width=5cm]{img/link_loop.eps} - \caption{Esempio di loop nel filesystem creato con un link simbolico.} - \label{fig:filedir_link_loop} -\end{figure} +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. + +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}. + +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/capability.h} -Un caso comune che si può avere con i link simbolici è la creazione dei -cosiddetti \textit{loop}. La situazione è illustrata in \curfig, che riporta -la struttura della directory \file{/boot}. Come si vede si è creato al suo -interno un link simbolico che punta di nuovo a \file{/boot}\footnote{Questo - tipo di loop è stato effettuato per poter permettere a \cmd{grub} (un - bootloader estremamente avanzato in grado di accedere direttamente - attraverso vari filesystem al file da lanciare come sistema operativo) di - vedere i file in questa directory, che è montata su una partizione separata - (e che grub vedrebbe come radice), con lo stesso path con cui verrebbero - visti dal sistema operativo.}. - -Questo può causare problemi per tutti quei programmi che effettuassero uno -scan di una directory senza tener conto dei link simbolici, in quel caso -infatti il loop nella directory - -Un secondo punto da tenere presente è che un link simbolico può essere fatto -anche ad un file che non esiste; ad esempio possiamo creare un file temporaneo -nella nostra directory con un link del tipo: -\begin{verbatim} -$ln -s /tmp/tmp_file temporaneo -\end{verbatim}%$ -ma anche se \file{/tmp/tmp\_file} non esiste. Aprendo in scrittura -\file{temporaneo} questo verrà scritto; ma se cercassimo di accederlo in sola -lettura (ad esempio con \cmd{cat}) otterremmo: -\begin{verbatim} -$ cat prova -cat: prova: No such file or directory -\end{verbatim}%$ -con un errore che sembra sbagliato, dato \cmd{ls} ci mostrerebbe l'esistenza -di \file{temporaneo}. + \funcdecl{char * cap\_to\_text(cap\_t caps, ssize\_t * length\_p)} + Genera una visualizzazione testuale delle \textit{capabilities}. + + \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} -\subsection{Le funzioni \texttt{mkdir} e \texttt{rmdir}} -\label{sec:filedir_dir_creat_rem} +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} -Per creare una nuova directory si può usare la seguente funzione, omonima -dell'analogo comando di shell \texttt{mkdir}; per accedere ai tipi usati -programma deve includere il file \texttt{sys/types.h}. + \funcdecl{cap\_t cap\_from\_text(const char *string)} -\begin{prototype}{sys/stat.h} -{int mkdir (const char * dirname, mode\_t mode)} - Questa funzione crea una nuova directory vuota con il nome indicato da - \texttt{dirname}, assegnandole i permessi indicati da \texttt{mode}. Il nome - può essere indicato con il pathname assoluto o relativo. - - La funzione restituisce zero in caso di successo e -1 per un errore, in caso - di errore \texttt{errno} viene settata secondo i codici di errore standard - di accesso ai file (trattati in dettaglio in - \secref{sec:filedir_access_control}) ai quali si aggiungono i seguenti: - \begin{errlist} - \item \texttt{EACCESS} - Non c'è il permesso di scrittura per la directory in cui si vuole inserire - la nuova directory. - \item \texttt{EEXIST} Un file (o una directory) con quel nome esiste di già. - \item \texttt{EMLINK} La directory in cui si vuole creare la nuova directory - contiene troppi file. Sotto Linux questo normalmente non avviene perché il - filesystem standard consente la creazione di un numero di file maggiore di - quelli che possono essere contenuti nell'hard-disk, ma potendo avere a che - fare anche con filesystem di altri sistemi questo errore può presentarsi. - \item \texttt{ENOSPC} Non c'è abbastanza spazio sul file system per creare - la nuova directory. - \item \texttt{EROFS} La directory su cui si vuole inserire la nuova - directory è su un filesystem montato readonly. - \end{errlist} -\end{prototype} - + Crea un \textit{capability state} dalla sua rappresentazione testuale. -\subsection{Accesso alle directory} -\label{sec:filedir_dir_read} + \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} -Benché le directory siano oggetti del filesystem come tutti gli altri non ha -ovviamente senso aprirle come fossero dei file di dati. Può però essere utile -poterne leggere il contenuto ad esempio per fare la lista dei file che esse -contengono o ricerche sui medesimi. +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, +\funcd{cap\_to\_name} e \funcd{cap\_from\_name}, sono estensioni specifiche di +Linux ed i rispettivi prototipi sono: +\begin{functions} + \headdecl{sys/capability.h} -Per accedere al contenuto delle directory si usano i cosiddetti -\textit{directory streams} (chiamati così per l'analogia con i file stream); -la funzione \texttt{opendir} apre uno di questi stream e la funzione -\texttt{readdir} legge il contenuto della directory, i cui elementi sono le -\textit{directory entries} (da distinguersi da quelle della cache di cui -parlavamo in \secref{sec:fileintr_vfs}) in una opportuna struttura -\texttt{struct dirent}. + \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. + + \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} +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}. + +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} -\subsection{La directory di lavoro} -\label{sec:filedir_work_dir} - -A ciascun processo è associato ad una directory nel filesystem che è chiamata -directory corrente o directory di lavoro (\textit{current working directory}) -che è quella a cui si fa riferimento quando un filename è espresso in forma -relativa (relativa appunto a questa directory). - -Quando un utente effettua il login questa directory viene settata alla -cosiddetta \textit{home directory} del suo account, il comando \texttt{cd} -della shell consente di cambiarla a piacere, spostandosi da una directory ad -un'altra. Siccome la directory corrente resta la stessa quando viene creato -un processo figlio, la directory corrente della shell diventa anche la -directory corrente di qualunque comando da essa lanciato. + \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} -Le funzioni qui descritte servono esaminare e cambiare la directory di lavoro -corrente. - -\begin{prototype}{unistd.h}{char * getcwd (char * buffer, size\_t size)} - Restituisce il filename completo della directory di lavoro corrente nella - stringa puntata da \texttt{buffer}, che deve essere precedentemente - allocata, per una dimensione massima di \texttt{size}. Si può anche - specificare un puntatore nullo come \textit{buffer}, nel qual caso la - stringa sarà allocata automaticamente per una dimensione pari a - \texttt{size} qualora questa sia diversa da zero, o della lunghezza esatta - del pathname altrimenti. In questo caso si deve ricordare di disallocare la - stringa una volta cessato il suo utilizzo. - - La funzione restituisce il puntatore \texttt{buffer} se riesce, - \texttt{NULL} se fallisce, in quest'ultimo caso la variabile - \texttt{errno} è settata con i seguenti codici di errore: - \begin{errlist} - \item \texttt{EINVAL} L'argomento \texttt{size} è zero e \texttt{buffer} non - è nullo. - \item \texttt{ERANGE} L'argomento \texttt{size} è più piccolo della - lunghezza del pathname. - \item \texttt{EACCESS} Manca il permesso di lettura o di ricerca su uno dei - componenti del pathname (cioè su una delle directory superiori alla - corrente). - \end{errlist} -\end{prototype} +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. + +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 \headfile{sys/capability.h}.} è: +\begin{functions} + \headdecl{sys/capability.h} -Di questa funzione esiste una versione \texttt{char * getwd(char * buffer)} -fatta per compatibilità all'indietro con BSD, che non consente di specificare -la dimensione del buffer; esso deve essere allocato in precedenza ed avere una -dimensione superiore a \texttt{PATH\_MAX} (di solito 256 bytes, vedi -\secref{sec:xxx_limits}; il problema è che in Linux non esiste una dimensione -superiore per un pathname, per cui non è detto che il buffer sia sufficiente a -contenere il nome del file, e questa è la ragione principale per cui questa -funzione è deprecata. - -Una seconda funzione simile è \texttt{char * get\_current\_dir\_name(void)} -che è sostanzialmente equivalente ad una \texttt{getcwd(NULL, 0)}, con la sola -differenza che essa ritorna il valore della variabile di ambiente -\texttt{PWD}, che essendo costruita dalla shell può contenere anche dei -riferimenti simbolici. - -Come già detto in unix anche le directory sono file, è possibile pertanto -riferirsi ad esse tramite il file descriptor dell'interfaccia a basso livello, -e non solo tramite il filename; per questo motivo ci sono due diverse funzioni -per cambiare directory di lavoro. - -\begin{prototype}{unistd.h}{int chdir (const char * pathname)} - Come dice il nome (che significa \textit{change directory}) questa funzione - serve a cambiare la directory di lavoro a quella specificata dal pathname - contenuto nella stringa \texttt{pathname}. -\end{prototype} + \funcdecl{int capgetp(pid\_t pid, cap\_t cap\_d)} + Legge le \textit{capabilities} del processo indicato da \param{pid}. -\begin{prototype}{unistd.h}{int fchdir (int filedes)} - Analoga alla precedente, ma usa un file descriptor invece del pathname. + \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{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/capability.h} - Entrambe le funzioni restituiscono zero in caso di successo e -1 per un - errore, in caso di errore \texttt{errno} viene settata secondo i codici di - errore standard di accesso ai file (trattati in dettaglio in - \secref{sec:filedir_access_control}) ai quali si aggiunge il codice - \texttt{ENOTDIR} nel caso il \texttt{filename} indichi un file che non sia - una directory. -\end{prototype} + \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}[!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} +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/ + + + +\subsection{La gestione dei {chroot}} +\label{sec:file_chroot} + +% TODO introdurre nuova sezione sulle funzionalità di sicurezza avanzate, con +% 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 +programma ad una sezione limitata del filesystem, per cui ne parleremo in +questa sezione. + +% TODO riferimenti ai bind mount, link simbolici ecc. + +Come accennato in sez.~\ref{sec:proc_fork} ogni processo oltre ad una +\index{directory~di~lavoro} directory di lavoro, ha anche una directory +\textsl{radice}\footnote{entrambe sono contenute in due campi (rispettivamente + \var{pwd} e \var{root}) di \kstruct{fs\_struct}; vedi + fig.~\ref{fig:proc_task_struct}.} che, pur essendo di norma corrispondente +alla radice dell'albero di file e directory come visto dal kernel (ed +illustrato in sez.~\ref{sec:file_pathname}), ha per il processo il significato +specifico di directory rispetto alla quale vengono risolti i +\itindsub{pathname}{assoluto}\textit{pathname} assoluti.\footnote{cioè quando + un processo chiede la risoluzione di un \textit{pathname}, il kernel usa + sempre questa directory come punto di partenza.} Il fatto che questo valore +sia specificato per ogni processo apre allora la possibilità di modificare le +modalità di risoluzione dei \textit{pathname} assoluti da parte di un processo +cambiando questa directory, così come si fa coi +\itindsub{pathname}{relativo}\textit{pathname} relativi cambiando la +\index{directory~di~lavoro} directory di lavoro. + +Normalmente la directory radice di un processo coincide anche con la radice +del filesystem usata dal kernel, e dato che il suo valore viene ereditato dal +padre da ogni processo figlio, in generale i processi risolvono i +\itindsub{pathname}{assoluto} \textit{pathname} assoluti a partire sempre +dalla stessa directory, che corrisponde alla radice del sistema. + +In certe situazioni però è utile poter impedire che un processo possa accedere +a tutto il filesystem; per far questo si può cambiare la sua directory radice +con la funzione \funcd{chroot}, il cui prototipo è: +\begin{prototype}{unistd.h}{int chroot(const char *path)} + Cambia la directory radice del processo a quella specificata da + \param{path}. + +\bodydesc{La funzione restituisce zero in caso di successo e -1 per + un errore, in caso di errore \var{errno} può assumere i valori: + \begin{errlist} + \item[\errcode{EPERM}] l'\ids{UID} effettivo del processo non è zero. + \end{errlist} + ed inoltre \errval{EFAULT}, \errval{ENAMETOOLONG}, \errval{ENOENT}, + \errval{ENOMEM}, \errval{ENOTDIR}, \errval{EACCES}, \errval{ELOOP}; + \errval{EROFS} e \errval{EIO}.} +\end{prototype} +\noindent in questo modo la directory radice del processo diventerà +\param{path} (che ovviamente deve esistere) ed ogni +\itindsub{pathname}{assoluto}\textit{pathname} assoluto usato dalle funzioni +chiamate nel processo sarà risolto a partire da essa, rendendo impossibile +accedere alla parte di albero sovrastante. Si ha così quella che viene +chiamata una \textit{chroot jail}, in quanto il processo non può più accedere +a file al di fuori della sezione di albero in cui è stato +\textsl{imprigionato}. + +Solo un processo con i privilegi di amministratore può usare questa funzione, +e la nuova radice, per quanto detto in sez.~\ref{sec:proc_fork}, sarà ereditata +da tutti i suoi processi figli. Si tenga presente però che la funzione non +cambia la directory di lavoro, che potrebbe restare fuori dalla \textit{chroot + jail}. + +Questo è il motivo per cui la funzione è efficace solo se dopo averla eseguita +si cedono i privilegi di root. Infatti se per un qualche motivo il processo +resta con \index{directory~di~lavoro} la directory di lavoro fuori dalla +\textit{chroot jail}, potrà comunque accedere a tutto il resto del filesystem +usando \itindsub{pathname}{relativo}\textit{pathname} relativi, i quali, +partendo dalla directory di lavoro che è fuori della \textit{chroot jail}, +potranno (con l'uso di ``\texttt{..}'') risalire fino alla radice effettiva +del filesystem. + +Ma se ad un processo restano i privilegi di amministratore esso potrà comunque +portare la sua \index{directory~di~lavoro} directory di lavoro fuori dalla +\textit{chroot jail} in cui si trova. Basta infatti creare una nuova +\textit{chroot jail} con l'uso di \func{chroot} su una qualunque directory +contenuta nell'attuale directory di lavoro. Per questo motivo l'uso di questa +funzione non ha molto senso quando un processo necessita dei privilegi di root +per le sue normali operazioni. + +Un caso tipico di uso di \func{chroot} è quello di un server FTP anonimo, in +questo caso infatti si vuole che il server veda solo i file che deve +trasferire, per cui in genere si esegue una \func{chroot} sulla directory che +contiene i file. Si tenga presente però che in questo caso occorrerà +replicare all'interno della \textit{chroot jail} tutti i file (in genere +programmi e librerie) di cui il server potrebbe avere bisogno. + + + + +% TODO: trattare la funzione setns e i namespace file descriptors (vedi +% http://lwn.net/Articles/407495/) introdotti con il kernel 3.0 + +% TODO: spostare chroot e le funzioni affini relative ai container da qualche +% parte diversa se è il caso. + +% LocalWords: sez like filesystem unlink MacOS Windows VMS inode kernel unistd +% 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 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 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 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 +% LocalWords: strcmp DirScan direntry while current working home shell pwd get +% LocalWords: getcwd ERANGE getwd change fd race condition tmpnam getfacl mark +% LocalWords: string tmpdir TMP tempnam pfx TMPNAME suid tmp EXCL tmpfile pid +% 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 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: 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 acl GETINFO +% LocalWords: OBJ setfacl len any prefix separator options NUMERIC IDS SMART +% 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 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 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 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 is +% 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 Virtual everything +% LocalWords: dentry register resolution cache dcache operation llseek poll ln +% LocalWords: multiplexing fsync fasync seek block superblock gapil tex img du +% LocalWords: second linked journaled source filesystemtype unsigned device +% LocalWords: mountflags NODEV ENXIO dummy devfs magic MGC RDONLY NOSUID MOVE +% LocalWords: NOEXEC SYNCHRONOUS REMOUNT MANDLOCK NODIRATIME umount MNT statfs +% LocalWords: fstatfs fstab mntent ino bound orig new setpcap metadati sysfs + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "gapil" +%%% End: +% LocalWords: bind DIRSYNC lsattr Hierarchy FHS SHARED UNBINDABLE shared REC +% LocalWords: subtree SILENT log unbindable BUSY EAGAIN EXPIRE DETACH NOFOLLOW +% LocalWords: lazy