Trattazione di linkat e openat con O_TMPFILE, con programmi di test ed
[gapil.git] / fileio.tex
index 27c02ac1ffd23bf118b8612e24caec7c64971ca2..d2522e1442955588d0147419db29764fdb6eeed0 100644 (file)
@@ -510,16 +510,16 @@ tab.~\ref{tab:file_file_times} vengono impostati al tempo corrente. Se invece
 si tronca il file con \const{O\_TRUNC} verranno impostati soltanto il
 \textit{modification time} e lo \textit{status change time}.
 
-Il flag \constd{O\_TMPFILE}, introdotto con il kernel
-3.11,\footnote{inizialmente solo su alcuni filesystem (i vari \acr{extN},
-  \acr{Minix}, \acr{UDF}, \acr{shmem}) poi progressivamente esteso ad altri
-  (\acr{XFS} con il 3.15, \acr{Btrfs} e \acr{F2FS} con il 3.16, \acr{ubifs}
-  con il 4.9).}  consente di aprire un file temporaneo senza che questo venga
-associato ad un nome e compaia nel filesystem. In questo caso la funzione
-restituirà un file descriptor da poter utilizzare per leggere e scrivere dati,
-ma il contenuto dell'argomento \param{path} verrà usato solamente per
-determinare, in base alla directory su cui si verrebbe a trovare il
-\textit{pathname} indicato, il filesystem all'interno del quale deve essere
+Il flag \label{open_o_tmpfile_flag} \constd{O\_TMPFILE}, introdotto con il
+kernel 3.11,\footnote{inizialmente solo su alcuni filesystem (i vari
+  \acr{extN}, \acr{Minix}, \acr{UDF}, \acr{shmem}) poi progressivamente esteso
+  ad altri (\acr{XFS} con il 3.15, \acr{Btrfs} e \acr{F2FS} con il 3.16,
+  \acr{ubifs} con il 4.9).}  consente di aprire un file temporaneo senza che
+questo venga associato ad un nome e compaia nel filesystem. In questo caso la
+funzione restituirà un file descriptor da poter utilizzare per leggere e
+scrivere dati, ma il contenuto dell'argomento \param{path} verrà usato
+solamente per determinare, in base alla directory su cui si verrebbe a trovare
+il \textit{pathname} indicato, il filesystem all'interno del quale deve essere
 allocato l'\textit{inode} e lo spazio disco usato dal file
 descriptor. L'\textit{inode} resterà anonimo e l'unico riferimento esistente
 sarà quello contenuto nella \textit{file table} del processo che ha chiamato
@@ -1722,6 +1722,7 @@ descriptor su cui si sta operando, e la registrazione immediata dei dati sarà
 limitata al filesystem su cui il file ad esso corrispondente si trova.
 
 
+
 \subsection{Le \textit{at-functions}: \func{openat} e le altre}
 \label{sec:file_openat}
 
@@ -1775,8 +1776,8 @@ si intende usare come base per la risoluzione dei \textit{pathname} relativi
 (ad esempio usando \func{open} con il flag \const{O\_PATH} visto in
 sez.~\ref{sec:file_open_close}) per ottenere un file descriptor che dovrà
 essere passato alle stesse.  Tutte queste funzioni infatti prevedono la
-presenza un apposito argomento, in genere il primo, che negli esempi seguenti
-chiameremo sempre \param{dirfd}.
+presenza un apposito argomento, in genere il primo che negli esempi seguenti
+chiameremo sempre \param{dirfd}, per indicare la directory di partenza.
 
 In questo modo, una volta aperta la directory di partenza, si potranno
 effettuare controlli ed aperture solo con \textit{pathname} relativi alla
@@ -1796,7 +1797,7 @@ profonde. Infatti in questo caso basta eseguire la risoluzione del
 file che essa contiene. Infine poter identificare una directory di partenza
 tramite il suo file descriptor consente di avere un riferimento stabile alla
 stessa anche qualora venisse rinominata, e tiene occupato il filesystem dove
-si trova, come per la directory di lavoro di un processo.
+si trova come per la directory di lavoro di un processo.
 
 La sintassi generica di queste nuove funzioni prevede l'utilizzo come primo
 argomento del file descriptor della directory da usare come base per la
@@ -2026,7 +2027,7 @@ il suo prototipo è:
 
 La funzione esegue il controllo di accesso ad un file, e \param{flags}
 consente di modificarne il comportamento rispetto a quello ordinario di
-\func{access} (cui è analoga, e con cui condivide i problemi di sicurezza
+\func{access} (cui è analoga e con cui condivide i problemi di sicurezza
 visti in sez.~\ref{sec:file_stat}) usando il valore \const{AT\_EACCES} per
 indicare alla funzione di eseguire il controllo dei permessi con l'\ids{UID}
 \textsl{effettivo} invece di quello \textsl{reale}. L'unico altro valore
@@ -2175,45 +2176,114 @@ suo prototipo è:
   \item[\errcode{EBADF}] \param{olddirfd} o \param{newdirfd} non sono un file
     descriptor valido.
   \item[\errcode{EINVAL}] \param{flags} non ha un valore valido.
+  \item[\errcode{ENOENT}] \param{oldpath} o \param{newpath} è un
+    \textit{pathname} relativo, ma la corrispondente directory di partenza
+    (\param{olddirfd} o \param{newdirfd}) è stata cancellata, oppure si è
+    cercato di creare un \textit{link} da un file descriptor aperto con
+    \const{O\_TMPFILE} e \const{O\_EXCL}, oppure si è usato
+    \const{AT\_EMPTY\_PATH} senza privilegi amministrativi. 
   \item[\errcode{ENOTDIR}] \param{oldpath} e \param{newpath} sono
-    \textit{pathname} relativi, ma \param{oldirfd} o \param{newdirfd} fa
+    \textit{pathname} relativi, ma \param{olddirfd} o \param{newdirfd} fa
     riferimento ad un file.
+  \item[\errcode{EPERM}] si è usato \const{AT\_EMPTY\_PATH} con
+    \param{oldpath} vuoto e \param{olddirfd} che fa riferimento ad una
+    directory.
   \end{errlist}
 }  
 \end{funcproto}
 
-Anche in questo caso la funzione è sostanzialmente identica alla classica
-\func{link}, ma dovendo specificare due \textit{pathname} (sorgente e
-destinazione) aggiunge a ciascuno di essi un argomento (rispettivamente
-\param{olddirfd} e \param{newdirfd}) per poter indicare entrambi come relativi
-a due directory aperte in precedenza.
+Anche in questo caso la funzione svolge lo stesso compito della
+corrispondente classica \func{link}, ma dovendo specificare due
+\textit{pathname} (sorgente e destinazione) aggiunge a ciascuno di essi un
+argomento (rispettivamente \param{olddirfd} e \param{newdirfd}) per poter
+indicare entrambi come relativi a due directory aperte in precedenza.
 
 In questo caso, dato che su Linux il comportamento di \func{link} è quello di
 non seguire mai i collegamenti simbolici, \const{AT\_SYMLINK\_NOFOLLOW} non
 viene utilizzato. A partire dal kernel 2.6.18 è stato aggiunto a questa
 funzione la possibilità di usare il valore \const{AT\_SYMLINK\_FOLLOW} per
-l'argomento \param{flags},\footnote{nei kernel precendenti, dall'introduzione
+l'argomento \param{flags},\footnote{nei kernel precedenti, dall'introduzione
   nel 2.6.16, l'argomento \param{flags} era presente, ma senza alcun valore
   valido, e doveva essere passato sempre con valore nullo.}  che richiede di
-dereferenziare i collegamenti simbolici. Inoltre a partire dal kernel 3.11 si
-può usare \const{AT\_EMPTY\_PATH} per creare un nuovo \textit{hard link} al
-file associato al file descriptor \param{olddirfd}.
+dereferenziare un eventuale collegamento simbolico creando un \textit{hard
+  link} al file puntato da quest'ultimo.
+
+Inoltre a partire dal kernel 3.11 si può usare \const{AT\_EMPTY\_PATH} con lo
+stesso significato già visto in precedenza applicato ad \param{olddirfd}, si
+può cioè creare un nuovo \textit{hard link} al file associato al file
+descriptor \param{olddirfd}, passando un valore nullo per
+\param{oldpath}. Questa operazione però è privilegiata e richiede i privilegi
+di amministratore (la \textit{capability} \const{CAP\_DAC\_READ\_SEARCH}),
+infatti in questo modo la funzione si comporta come una ipotetica
+\texttt{flink}, una \textit{system call} di cui è stato spesso chiesta la
+creazione, che permetterebbe di associare direttamente un nome ad un file
+descriptor, ma che non è mai stata realizzata per problemi di sicurezza.
+
+Il problema infatti è che le verifiche di accesso sono fatte quando il file
+viene aperto e non attengono solo ai permessi del file stesso, ma anche a
+quelli delle directory del suo \textit{pathname}; se una volta aperto venisse
+collegato in un altra directory eventuali restrizioni imposte sulle directory
+del suo \textit{pathname} andrebbero perse. Inoltre sarebbe possibile accedere
+al file sottostante anche in scrittura per un file descriptor che è stato
+fornito come aperto in sola lettura, o con accesso libero per un file
+descriptor fornito aperto in \textit{append}. Infine e la funzione
+consentirebbe rendere accessibile all'interno di un \textit{choot} (vedi
+sez.~\ref{sec:file_chroot}) un qualunque file sia stato aperto fuori dallo
+stesso prima di entrarvi.
 
 
 % NOTE per la discussione sui problemi di sicurezza relativi a questa
 % funzionalità vedi http://lwn.net/Articles/562488/
 
-La funzione prevede inoltre un comportamento specifico nel caso che
-\param{olddirfd} faccia riferimento ad un file anonimo ottenuto usando
-\func{open} con \const{O\_TMPFILE}. In generale quando il file associato ad
-\param{olddirfd} ha un numero di link nullo (come in questo caso), la funzione
-fallisce, c'è però una 
+Per questo motivo l'uso di \const{AT\_EMPTY\_PATH} richiede comunque privilegi
+amministrativi, anche se, quando è disponibile il filesystem \texttt{/proc}, è
+possibile usare \func{linkat} per creare un file da un qualunque file
+descriptor un processo abbia aperto, usandola con un codice analogo al
+seguente:\footnote{non esiste, al momento, una modalità per evitare i rischi
+  illustrati in precedenza se si sta usando il filesystem \textit{proc}.}
+\includecodesnip{listati/procfd_linkat.c}
+
+Questa modalità è anche quella con cui è possibile assegnare in un secondo
+tempo il nome ad un file anonimo creato usando \func{open} con
+\const{O\_TMPFILE}; ma si deve tenere presente che per questi file la funzione
+ha un comportamento particolare. In generale infatti quando il file sorgente
+di \func{linkat} ha un numero di collegamenti nulli (cosa che avviene ad
+esempio quando si apre un file temporaneo e lo si cancella subito dopo oppure
+quando viene cancellato un file aperto in precedenza) la funzione non consente
+di ricollegarlo ad un altro file riassegnandogli un nuovo nome e fallisce
+sempre, qualunque siano i permessi del processo e che si usi questo approccio
+o \const{AT\_EMPTY\_PATH}, con un errore di \errval{ENOENT}.
+
+Questo non avviene se il file descriptor sorgente è stato ottenuto con
+\const{O\_TMPFILE} e la funzione ha successo, a meno che non si sia usato
+nell'apertura anche \const{O\_EXCL} per impedire questo specifico
+comportamento, e continuare ad ottenere l'errore di \errval{ENOENT}. In fig.
+
+Pertanto la modalità per creare in maniera sicura la versione iniziale di un
+file cui abbiamo accennato a pag.~\pageref{open_o_tmpfile_flag},
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{\codesamplewidth}
+    \includecodesample{listati/initfile.c}
+  \end{minipage}
+  \caption{Esempio di codice creare in maniera sicura il contenuto iniziale di
+    un file.} 
+  \label{fig:initfile}
+\end{figure}
+
+
 
 
-l'uso di \const{AT\_EMPTY\_PATH} assume un significato
-ulteriore, e richiede i privilegi di amministratore (la \textit{capability}
-\const{CAP\_DAC\_READ\_SEARCH}) quando viene usato con un file descriptor
-anomino ottenuto usando \const{O\_TMPFILE} con \func{open}. In generale
+
+
+% TODO: Trattare esempio di inzializzazione di file e successivo collegamento
+% con l'uso di O_TMPFILE e linkat, vedi man open
+
+
+
+% TODO manca prototipo di renameat2, introdotta nel 3.15, vedi
+% http://lwn.net/Articles/569134/ 
 
 
 Altre due funzioni che utilizzano due \textit{pathname} (e due file
@@ -2256,7 +2326,7 @@ classica \func{rename}; i rispettivi prototipi sono:
 
 In realtà la corrispondente di \func{rename}, prevista dallo standard
 POSIX.1-2008 e disponibile dal kernel 2.6.16 come le altre
-\textit{at-functions}, sarebbe soltanti \func{renameat}, su Linux però, a
+\textit{at-functions}, sarebbe soltanto \func{renameat}, su Linux però, a
 partire dal kernel dal 3.15, questa è stata realizzata in termini della nuova
 funzione di sistema \func{renameat2} che prevede l'uso dell'argomento
 aggiuntivo \param{flags}; in questo caso \func{renameat} è totalmente
@@ -2264,7 +2334,7 @@ equivalente all'utilizzo di \func{renamat2} con un valore nullo per
 \param{flags}.
 
 L'uso di \func{renameat} è identico a quello di \func{rename}, con le solite
-note relativie alle estensioni delle \textit{at-functions}, applicate ad
+note relative alle estensioni delle \textit{at-functions}, applicate ad
 entrambi i \textit{pathname} passati come argomenti alla funzione. Con
 \func{renameat2} l'introduzione dell'argomento \func{flags} (i cui valori
 possibili sono riportati in tab.~\ref{tab:renameat2_flag_values}) ha permesso
@@ -2319,7 +2389,7 @@ quella del cambio di nome.
 \itindbeg{union~filesytem}
 
 Infine il flag \constd{RENAME\_WHITEOUT}, introdotto con il kernel 3.18,
-richiede un approfomdimento specifico, in quanto attiene all'uso della
+richiede un approfondimento specifico, in quanto attiene all'uso della
 funzione con dei filesystem di tipo \textit{overlay}/\textit{union}, dato che
 il flag ha senso solo quando applicato a file che stanno su questo tipo di
 filesystem. 
@@ -2347,9 +2417,6 @@ che esso non appaia più è possibile creare
 % https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a528d35e8bfcc521d7cb70aaf03e1bd296c8493f) 
 
 
-% TODO: Trattare esempio di inzializzazione di file e successivo collegamento
-% con l'uso di O_TMPFILE e linkat, vedi man open
-
 % TODO: manca prototipo e motivazione di fexecve, da trattare qui in quanto
 % inserita nello stesso standard e da usare con openat, vedi 
 % http://pubs.opengroup.org/onlinepubs/9699939699/toc.pdf
@@ -2358,15 +2425,10 @@ che esso non appaia più è possibile creare
 % TODO: manca prototipo e motivazione di execveat, vedi
 % http://man7.org/linux/man-pages/man2/execveat.2.html 
 
-% TODO manca prototipo di renameat2, introdotta nel 3.15, vedi
-% http://lwn.net/Articles/569134/ 
-
 
 % TODO: trattare i nuovi AT_flags quando e se arriveranno, vedi
 % https://lwn.net/Articles/767547/ 
 
-
-
 \itindend{at-functions}
 
 
@@ -4745,15 +4807,18 @@ con uno dei valori \const{FSETLOCKING\_INTERNAL} o
 % LocalWords:  FIONREAD epoll FIOQSIZE side effects SAFE BYCALLER QUERY EACCES
 % LocalWords:  EBUSY OpenBSD syncfs futimes timespec only init ESRCH kill NTPL
 % LocalWords:  ENXIO  NONBLOCK WRONLY EPERM NOATIME ETXTBSY EWOULDBLOCK PGRP SZ
-% LocalWords:  EFAULT capabilities GETPIPE SETPIPE RESOURCE dell'I all' NFSv
+% LocalWords:  EFAULT capabilities GETPIPE SETPIPE RESOURCE NFSv
+% LocalWords:  Documentation Urlich Drepper futimesat times
+% LocalWords:  futimens fs Tread TMPFILE EDQUOT extN Minix UDF XFS
+% LocalWords:  shmem Btrfs ubifs tmpfile fchmod fchown fsetxattr fchdir PF
+% LocalWords:  fstatfs SIGTTIN EDESTADDRREQ datagram connect seal pag
+% LocalWords:  dirty execveat execve scandirat statx AUTOMOUNT automount DAC
+% LocalWords:  wrapper EMPTY olddirfd oldpath newdirfd newpath capability
+% LocalWords:  SEARCH flink choot oldirfd NOREPLACE EXCHANGE WHITEOUT union
+% LocalWords:  renamat syscall whiteout overlay filesytem Live
 
 %%% Local Variables: 
 %%% mode: latex
 %%% TeX-master: "gapil"
 %%% End: 
 
-% LocalWords:  nell' du vm Documentation Urlich Drepper futimesat times l'I
-%  LocalWords:  futimens fs Tread all'I ll TMPFILE EDQUOT extN Minix UDF XFS
-%  LocalWords:  shmem Btrfs ubifs tmpfile fchmod fchown fsetxattr fchdir PF
-%  LocalWords:  fstatfs sull' SIGTTIN EDESTADDRREQ datagram connect seal
-%  LocalWords:  dirty execveat execve scandirat statx