Finite fexecve e execveat
authorSimone Piccardi <piccardi@truelite.it>
Thu, 22 Aug 2019 11:54:16 +0000 (13:54 +0200)
committerSimone Piccardi <piccardi@truelite.it>
Thu, 22 Aug 2019 11:54:16 +0000 (13:54 +0200)
fileio.tex
listati/statx.h

index 5444348..a0d5475 100644 (file)
@@ -2708,13 +2708,13 @@ ad informazioni locali, e sono sempre disponibili in maniera diretta.
 % NOTE: per statx https://lwn.net/Articles/707602/ e
 % https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a528d35e8bfcc521d7cb70aaf03e1bd296c8493f)
 
-Infine trattiamo qui altre due funzioni che non attengono che in maniera
-indiretta all'uso dei file, ma sono comunque legate all'interfaccia delle
-\textit{at-functions}. In realtà la sola effettivamente collegata
-all'interfaccia delle \textit{at-functions} è la funzione di sistema
-\func{execveat}, introdotta con il kernel 3.19, e per la quale non è
-disponibile ancora un'interfaccia diretta nella \acr{glibc} che però la usa
-(quando disponibile) per realizzare \func{fexecve}.
+Infine trattiamo qui altre due funzioni, \func{fexecve} e \func{execveat}, che
+non attengono che in maniera indiretta all'uso dei file, ma sono comunque
+legate all'interfaccia delle \textit{at-functions}. In realtà la sola
+effettivamente collegata all'interfaccia delle \textit{at-functions} è la
+funzione di sistema \func{execveat}, introdotta con il kernel 3.19, e per la
+quale non è disponibile ancora un'interfaccia diretta nella \acr{glibc} che
+però la usa (quando disponibile) per realizzare \func{fexecve}.
 
 L'introduzione di queste funzioni nasce dall'esigenza di verificare i
 contenuti di un file eseguibile prima di eseguirlo. Fare il controllo (aprendo
@@ -2748,8 +2748,8 @@ avere il permesso di esecuzione) corrispondente a \param{fd}; questo deve
 essere stato ottenuto aprendo il relativo eseguibile in sola lettura o con
 \const{O\_PATH}. Questa funzione fino al kernel 3.19 veniva realizzata nella
 \acr{glibc} usando il filesystem \file{/proc} per ottenere da \param{fd} il
-file corrispondente, in maniera analoga a quanto visto per l'esempio di
-fig.~\ref{fig:initfile}.
+file corrispondente in \file{/proc/self/fd/}, in maniera analoga a quanto
+visto per l'esempio di fig.~\ref{fig:initfile}.
 
 La funzione di sistema \funcd{execveat} è stata introdotta proprio per rendere
 più sicura l'esecuzione ed evitare la necessità di avere disponibile
@@ -2779,28 +2779,49 @@ più sicura l'esecuzione ed evitare la necessità di avere disponibile
 \end{funcproto}
 
 La funzione segue la sintassi delle \textit{at-functions} per indicare il file
-da eseguire, e per il resto si comporta esattamente con come \func{execve}; è
-pertanto possibile indicare il programma da eseguire sia con un
-\textit{pathname} assoluto che relativo, ed anche con un \textit{pathname}
-relativo alla directory indicata da \param{dirfd}. Inoltre usando per
-\param{flags} il valore \const{AT\_EMPTY\_PATH} si può indicare direttamente
-il file con il file descriptor \param{dirfd} ottenendo il comportamento di
-\func{fexecve}, che è equivalnente all'esecuzione di:
-\includecodesnip{listati/fexecve.c} l'unico altro valore utilizzabile per
-\param{flags} è \const{AT\_SYMLINK\_NOFOLLOW} che fa fallire la funzione con
-un errore di \errval{ELOOP} se il file indicato è un link simbolico.
+da eseguire, e per il resto si comporta esattamente con come \func{execve} (le
+cui caratteristiche sono già state illustrate in
+sez.~\ref{sec:file_stat}). Diventa così possibile indicare il programma da
+eseguire sia con un \textit{pathname} assoluto che relativo (usando
+\const{AT\_FDCWD} come \param{dirfd}), oppure con un \textit{pathname}
+relativo alla directory indicata da \param{dirfd}. In quest'ultima forma l'uso
+della funzione consente estendere i vantaggi delle \textit{at-functions} anche
+al caso dell'esecuzione di un programma.
+
+Inoltre usando, per \param{flags} il valore \const{AT\_EMPTY\_PATH}, si può
+indicare direttamente il file da eseguire aprendolo e passandone il file
+descriptor nell'argomento \param{dirfd}, ottenendo il comportamento di
+\func{fexecve}; quest'ultima infatti è sostanzialmente equivalente
+all'esecuzione di: \includecodesnip{listati/fexecve.c} l'unico altro valore
+utilizzabile per \param{flags} è \const{AT\_SYMLINK\_NOFOLLOW} che fa fallire
+la funzione con un errore di \errval{ELOOP}, se il file indicato è un link
+simbolico.
 
 Quando si usano \func{execveat} o \func{fexecve} per eseguire un programma
-attraverso un file descriptor è opportuno impostare sempre sullo stesso il
-flag di \textit{close-on-exec}, in modo che questo venga automaticamente
-chiuso all'esecuzione. Questo evita di consumare inutilmente un file
-descriptor (un programma non ha bisogno di un riferimento a se stesso), ma
-soprattutto evita problemi in caso di un eventuale uso ricorsivo di queste
-funzioni che potrebbe portare, restando aperto ogni volta un ulteriore file
-descriptor, all'esaurimento degli stessi.
-
-
-
+attraverso un file descriptor è naturale impostare sullo stesso il flag di
+\textit{close-on-exec} in modo che questo venga automaticamente chiuso
+all'esecuzione. Questo evita di lasciare aperto inutilmente un file descriptor
+(un programma in genere non ha bisogno di avere un file aperto su se stesso),
+ma soprattutto evita problemi in caso di un eventuale uso ricorsivo di queste
+funzioni, in tal caso infatti, restando aperto ad ogni iterazione un ulteriore
+file descriptor, si potrebbe arrivare all'esaurimento degli stessi.
+
+Tutto questo però non è vero quando si vuole eseguire uno script; in tal caso
+infatti (si ricordi quanto detto a questo riguardo in
+sez.~\ref{sec:file_stat}) il programma che viene effettivamente messo in
+esecuzione è l'interprete indicato nella riga iniziale dello script, che poi
+legge ed interpreta il codice da eseguire dallo script stesso. Ma se lancia lo
+script usando un file descriptor su cui è attivo il flag di
+\textit{close-on-exec}, questo sarà già chiuso quando l'interprete viene posto
+in esecuzione, rendendo impossibile la lettura del programma da
+interpretare.
+
+Per questo motivo, quando ci si trova in questa situazione, \func{execveat} (e
+quindi anche \func{fexecve}) eseguono un controllo preventivo e falliscono con
+un errore di \errval{ENOENT}. Pertanto se si vuole eseguire uno script
+passandone il file descriptor l'unica possibilità è non attivare il flag di
+\textit{close-on-exec}, esponendosi però al rischio di incorrere nei problemi
+accennati in precedenza.
 
 % TODO: manca prototipo e motivazione di fexecve, da trattare qui in quanto
 % inserita nello stesso standard e da usare con openat, vedi 
index 4eecfd6..5bec4de 100644 (file)
@@ -1,21 +1,22 @@
 struct statx {
     __u32 stx_mask;        /* Mask of bits indicating filled fields */
-    __u32 stx_blksize;     /* Block size for filesystem I/O */
+    __u32 stx_blksize;     /* Preferred block size for filesystem I/O */
     __u64 stx_attributes;  /* Extra file attribute indicators */
     __u32 stx_nlink;       /* Number of hard links */
     __u32 stx_uid;         /* User ID of owner */
     __u32 stx_gid;         /* Group ID of owner */
     __u16 stx_mode;        /* File type and mode */
+    __u16 __spare0[1];
     __u64 stx_ino;         /* Inode number */
-    __u64 stx_size;        /* Total size in bytes */
-    __u64 stx_blocks;      /* Number of 512B blocks allocated */
+    __u64 stx_size;        /* File size in bytes */
+    __u64 stx_blocks;      /* Number of 512-byte blocks allocated */
     __u64 stx_attributes_mask; 
                            /* Mask to show what's supported in stx_attributes */
     /* The following fields are file timestamps */
-    struct statx_timestamp stx_atime;  /* Last access */
-    struct statx_timestamp stx_btime;  /* Creation */
-    struct statx_timestamp stx_ctime;  /* Last status change */
-    struct statx_timestamp stx_mtime;  /* Last modification */
+    struct statx_timestamp stx_atime;  /* Last access time */
+    struct statx_timestamp stx_btime;  /* File creation time */
+    struct statx_timestamp stx_ctime;  /* Last status change time */
+    struct statx_timestamp stx_mtime;  /* Last data modification time */
     /* If this file represents a device, then the next two
        fields contain the ID of the device */
     __u32 stx_rdev_major;  /* Major ID */
@@ -24,4 +25,5 @@ struct statx {
        containing the filesystem where the file resides */
     __u32 stx_dev_major;   /* Major ID */
     __u32 stx_dev_minor;   /* Minor ID */
+    __u64 __spare2[14];    /* Spare space for future expansion */
 };