From ee65c9e30267ed1b0c0cef337c3ff86f9e0b370d Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Thu, 16 Aug 2018 22:06:08 +0200 Subject: [PATCH] Correzioni per execve e setuid. --- img/exec_rel.dia | Bin 2025 -> 2123 bytes prochand.tex | 240 ++++++++++++++++++++++++++++------------------- 2 files changed, 145 insertions(+), 95 deletions(-) diff --git a/img/exec_rel.dia b/img/exec_rel.dia index fd76c3dd121e96458014d9e6fc44b24378e63b8e..9ec59fea300cb08e923fe43b9c2959c343bc2179 100644 GIT binary patch literal 2123 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 HWsLv;a=+Sn diff --git a/prochand.tex b/prochand.tex index 1d8cadb..30e272c 100644 --- a/prochand.tex +++ b/prochand.tex @@ -477,12 +477,12 @@ della CPU e nell'unità di gestione della memoria virtuale, senza doverli invalidare, cosa che per i processori moderni, che hanno linee di cache interne molto profonde, avrebbe un forte impatto sulle prestazioni. -Allora anche se quanto detto in precedenza vale come comportamento effettivo -dei programmi soltanto per i kernel fino alla serie 2.4, per mantenere la -portabilità con altri kernel unix-like, e con i diversi comportamenti adottati -dalle Linux nella sua evoluzione, è comunque opportuno non fare affidamento su -nessun tipo di comportamento predefinito e non fare assunzioni sull'ordine di -esecuzione di padre e figlio. +Allora anche se quanto detto in precedenza si verifica nel comportamento +effettivo dei programmi soltanto per i kernel fino alla serie 2.4, per +mantenere la portabilità con altri kernel unix-like e con i diversi +comportamenti adottati dalle Linux nella sua evoluzione, è comunque opportuno +non fare nessuna assunzione sull'ordine di esecuzione di padre e figlio dopo +la chiamata a \func{fork}. Si noti infine come dopo la \func{fork}, essendo i segmenti di memoria utilizzati dai singoli processi completamente indipendenti, le modifiche delle @@ -576,10 +576,10 @@ corrente nel file. Quando un processo scrive su un file la posizione corrente viene aggiornata sulla \textit{file table}, e tutti gli altri processi, che vedono la stessa \textit{file table}, vedranno il nuovo valore. In questo modo si evita, in -casi come quello appena mostrato in cui diversi processi scrivono sullo stesso -file, che l'output di un processo successivo vada a sovrapporsi a quello dei -precedenti: l'output potrà risultare mescolato, ma non ci saranno parti -perdute per via di una sovrascrittura. +casi come quello appena mostrato in cui diversi figli scrivono sullo stesso +file usato dal padre, che una scrittura eseguita in un secondo tempo da un +processo vada a sovrapporsi a quelle precedenti: l'output potrà risultare +mescolato, ma non ci saranno parti perdute per via di una sovrascrittura. Questo tipo di comportamento è essenziale in tutti quei casi in cui il padre crea un figlio e attende la sua conclusione per proseguire, ed entrambi @@ -587,9 +587,9 @@ scrivono sullo stesso file. Un caso tipico di questo comportamento è la shell quando lancia un programma. In questo modo, anche se lo standard output viene rediretto, il padre potrà sempre continuare a scrivere in coda a quanto scritto dal figlio in maniera automatica; se così non fosse ottenere questo -comportamento sarebbe estremamente complesso necessitando di una qualche forma -di comunicazione fra i due processi per far riprendere al padre la scrittura -al punto giusto. +comportamento sarebbe estremamente complesso, necessitando di una qualche +forma di comunicazione fra i due processi per far riprendere al padre la +scrittura al punto giusto. In generale comunque non è buona norma far scrivere più processi sullo stesso file senza una qualche forma di sincronizzazione in quanto, come visto anche @@ -772,10 +772,12 @@ terminato; si potrebbe avere cioè quello che si chiama un processo \textsl{orfano}. Questa complicazione viene superata facendo in modo che il processo orfano -venga \textsl{adottato} da \cmd{init}, o meglio dal processo con \ids{PID} 1, -cioè quello lanciato direttamente dal kernel all'avvio, che sta alla base -dell'albero dei processi visto in sez.~\ref{sec:proc_hierarchy} e che anche -per questo motivo ha un ruolo essenziale nel sistema e non può mai +venga \textsl{adottato} da \cmd{init}, o meglio dal processo con \ids{PID} +1,\footnote{anche se, come vedremo in sez.~\ref{sec:process_prctl}, a partire + dal kernel 3.4 è diventato possibile delegare questo compito anche ad un + altro processo.} cioè quello lanciato direttamente dal kernel all'avvio, che +sta alla base dell'albero dei processi visto in sez.~\ref{sec:proc_hierarchy} +e che anche per questo motivo ha un ruolo essenziale nel sistema e non può mai terminare.\footnote{almeno non senza un blocco completo del sistema, in caso di terminazione o di non esecuzione di \cmd{init} infatti il kernel si blocca con un cosiddetto \textit{kernel panic}, dato che questo è un errore @@ -815,9 +817,10 @@ terminano, e come si può notare in questo caso, al contrario di quanto visto in precedenza, essi riportano 1 come \ids{PPID}. Altrettanto rilevante è il caso in cui il figlio termina prima del padre, -perché non è detto che il padre possa ricevere immediatamente lo stato di -terminazione, quindi il kernel deve comunque conservare una certa quantità di -informazioni riguardo ai processi che sta terminando. +perché non è detto che il padre sia in esecuzione e possa ricevere +immediatamente lo stato di terminazione, quindi il kernel deve comunque +conservare una certa quantità di informazioni riguardo ai processi che sta +terminando. Questo viene fatto mantenendo attiva la voce nella tabella dei processi, e memorizzando alcuni dati essenziali, come il \ids{PID}, i tempi di CPU usati @@ -986,9 +989,9 @@ sistema, \funcd{waitpid}, il cui prototipo è: La prima differenza fra le due funzioni è che con \func{waitpid} si può specificare in maniera flessibile quale processo attendere, sulla base del -valore fornito dall'argomento \param{pid}, questo può assumere diversi valori, +valore fornito dall'argomento \param{pid}. Questo può assumere diversi valori, secondo lo specchietto riportato in tab.~\ref{tab:proc_waidpid_pid}, dove si -sono riportate anche le costanti definite per indicare alcuni di essi. +sono riportate anche le costanti definite per indicare alcuni di essi. \begin{table}[!htb] \centering @@ -1025,8 +1028,8 @@ tabella si sono riportati anche alcune opzioni non standard specifiche di Linux, che consentono un controllo più dettagliato per i processi creati con la \textit{system call} generica \func{clone} (vedi sez.~\ref{sec:process_clone}) e che vengono usati principalmente per la -gestione della terminazione dei \textit{thread} (vedi -sez.~\ref{sec:thread_xxx}). +gestione della terminazione dei \textit{thread}\unavref{ (vedi +sez.~\ref{sec:thread_xxx})}. \begin{table}[!htb] \centering @@ -1041,8 +1044,7 @@ sez.~\ref{sec:thread_xxx}). \const{WUNTRACED} & Ritorna anche quando un processo figlio è stato fermato.\\ \const{WCONTINUED}& Ritorna anche quando un processo figlio che era stato - fermato ha ripreso l'esecuzione (disponibile solo a - partire dal kernel 2.6.10).\\ + fermato ha ripreso l'esecuzione (dal kernel 2.6.10).\\ \hline \constd{\_\_WCLONE}& Attende solo per i figli creati con \func{clone} (vedi sez.~\ref{sec:process_clone}), vale a dire @@ -1052,7 +1054,7 @@ sez.~\ref{sec:thread_xxx}). processi figli ordinari ignorando quelli creati da \func{clone}.\\ \constd{\_\_WALL} & Attende per qualunque figlio, sia ordinario che creato - con \func{clone}, se specificata insieme a + con \func{clone}, se specificata con \const{\_\_WCLONE} quest'ultima viene ignorata. \\ \constd{\_\_WNOTHREAD}& Non attende per i figli di altri \textit{thread} dello stesso \textit{thread group}, questo era il @@ -1088,12 +1090,12 @@ Nel caso di \const{WUNTRACED} la funzione ritorna, restituendone il \ids{PID}, quando un processo figlio entra nello stato \textit{stopped}\footnote{in realtà viene notificato soltanto il caso in cui il processo è stato fermato da un segnale di stop (vedi sez.~\ref{sec:sess_ctrl_term}), e non quello in - cui lo stato \textit{stopped} è dovuto all'uso di \func{ptrace} (vedi - sez.~\ref{sec:process_ptrace}).} (vedi tab.~\ref{tab:proc_proc_states}), -mentre con \const{WCONTINUED} la funzione ritorna quando un processo in stato -\textit{stopped} riprende l'esecuzione per la ricezione del segnale -\signal{SIGCONT} (l'uso di questi segnali per il controllo di sessione è -trattato in sez.~\ref{sec:sess_ctrl_term}). + cui lo stato \textit{stopped} è dovuto all'uso di \func{ptrace}\unavref{ + (vedi sez.~\ref{sec:process_ptrace})}.} (vedi +tab.~\ref{tab:proc_proc_states}), mentre con \const{WCONTINUED} la funzione +ritorna quando un processo in stato \textit{stopped} riprende l'esecuzione per +la ricezione del segnale \signal{SIGCONT} (l'uso di questi segnali per il +controllo di sessione è trattato in sez.~\ref{sec:sess_ctrl_term}). \constend{WUNTRACED} \constend{WCONTINUED} @@ -1103,10 +1105,10 @@ con \func{waitpid}) è chiaramente un evento asincrono rispetto all'esecuzione di un programma e può avvenire in un qualunque momento. Per questo motivo, come accennato nella sezione precedente, una delle azioni prese dal kernel alla conclusione di un processo è quella di mandare un segnale di -\signal{SIGCHLD} al padre. L'azione predefinita (si veda -sez.~\ref{sec:sig_base}) per questo segnale è di essere ignorato, ma la sua -generazione costituisce il meccanismo di comunicazione asincrona con cui il -kernel avverte il processo padre che uno dei suoi figli è terminato. +\signal{SIGCHLD} al padre. L'azione predefinita per questo segnale (si veda +sez.~\ref{sec:sig_base}) è di essere ignorato, ma la sua generazione +costituisce il meccanismo di comunicazione asincrona con cui il kernel avverte +il processo padre che uno dei suoi figli è terminato. Il comportamento delle funzioni è però cambiato nel passaggio dal kernel 2.4 al kernel 2.6, quest'ultimo infatti si è adeguato alle prescrizioni dello @@ -1140,15 +1142,15 @@ la chiamata a \func{waitpid} non si bloccherà. Come accennato sia \func{wait} che \func{waitpid} restituiscono lo stato di terminazione del processo tramite il puntatore \param{status}, e se non -interessa memorizzare lo stato si può passare un puntatore nullo. Il valore -restituito da entrambe le funzioni dipende dall'implementazione, ma -tradizionalmente gli 8 bit meno significativi sono riservati per memorizzare -lo stato di uscita del processo, e gli altri per indicare il segnale che ha -causato la terminazione (in caso di conclusione anomala), uno per indicare se -è stato generato un \textit{core dump} (vedi sez.~\ref{sec:sig_standard}), -ecc.\footnote{le definizioni esatte si possono trovare in - \file{} ma questo file non deve mai essere usato - direttamente, esso viene incluso attraverso \file{}.} +interessa memorizzarlo si può passare un puntatore nullo. Il valore restituito +da entrambe le funzioni dipende dall'implementazione, ma tradizionalmente gli +8 bit meno significativi sono riservati per memorizzare lo stato di uscita del +processo, e gli altri per indicare il segnale che ha causato la terminazione +(in caso di conclusione anomala), uno per indicare se è stato generato un +\textit{core dump} (vedi sez.~\ref{sec:sig_standard}), ecc.\footnote{le + definizioni esatte si possono trovare in \file{} ma + questo file non deve mai essere usato direttamente, esso viene incluso + attraverso \file{}.} \begin{table}[!htb] \centering @@ -1392,6 +1394,12 @@ creato un nuovo processo, la funzione semplicemente rimpiazza lo programma letto da disco, eseguendo il \textit{link-loader} con gli effetti illustrati in sez.~\ref{sec:proc_main}. +\begin{figure}[!htb] + \centering \includegraphics[width=8cm]{img/exec_rel} + \caption{La interrelazione fra le sei funzioni della famiglia \func{exec}.} + \label{fig:proc_exec_relat} +\end{figure} + Ci sono sei diverse versioni di \func{exec} (per questo la si è chiamata famiglia di funzioni) che possono essere usate per questo compito, in realtà (come mostrato in fig.~\ref{fig:proc_exec_relat}), tutte queste funzioni sono @@ -1399,7 +1407,7 @@ tutte varianti che consentono di invocare in modi diversi, semplificando il passaggio degli argomenti, la funzione di sistema \funcd{execve}, il cui prototipo è: -\begin{funcproto}{ +\begin{funcproto}{ \fhead{unistd.h} \fdecl{int execve(const char *filename, char *const argv[], char *const envp[])} \fdesc{Esegue un programma.} @@ -1411,15 +1419,18 @@ prototipo è: eseguibili, o il file è su un filesystem montato con l'opzione \cmd{noexec}, o manca il permesso di attraversamento di una delle directory del \textit{pathname}. + \item[\errcode{EAGAIN}] dopo un cambio di \ids{UID} si è ancora sopra il + numero massimo di processi consentiti per l'utente (dal kernel 3.1, per i + dettagli vedi sez.~\ref{sec:proc_setuid}). \item[\errcode{EINVAL}] l'eseguibile ELF ha più di un segmento \const{PT\_INTERP}, cioè chiede di essere eseguito da più di un interprete. \item[\errcode{ELIBBAD}] un interprete ELF non è in un formato riconoscibile. - \item[\errcode{ENOEXEC}] il file è in un formato non eseguibile o non - riconosciuto come tale, o compilato per un'altra architettura. \item[\errcode{ENOENT}] il file o una delle librerie dinamiche o l'interprete necessari per eseguirlo non esistono. + \item[\errcode{ENOEXEC}] il file è in un formato non eseguibile o non + riconosciuto come tale, o compilato per un'altra architettura. \item[\errcode{EPERM}] il file ha i bit \acr{suid} o \acr{sgid} e l'utente non è root, ed il processo viene tracciato, oppure il filesystem è montato con l'opzione \cmd{nosuid}. @@ -1445,8 +1456,8 @@ torneremo in sez.~\ref{sec:sys_res_limits}). In caso di successo la funzione non ritorna, in quanto al posto del programma chiamante viene eseguito il nuovo programma indicato da \param{filename}. Se -il processo corrente è tracciato con \func{ptrace} (vedi -sez.~\ref{sec:process_ptrace}) in caso di successo viene emesso il segnale +il processo corrente è tracciato con \func{ptrace}\unavref{ (vedi +sez.~\ref{sec:process_ptrace})} in caso di successo viene emesso il segnale \signal{SIGTRAP}. Le altre funzioni della famiglia (\funcd{execl}, \funcd{execv}, @@ -1520,12 +1531,6 @@ che deve essere terminata da un puntatore nullo. In entrambi i casi vale la convenzione che il primo argomento (\var{arg0} o \var{argv[0]}) viene usato per indicare il nome del file che contiene il programma che verrà eseguito. -\begin{figure}[!htb] - \centering \includegraphics[width=9cm]{img/exec_rel} - \caption{La interrelazione fra le sei funzioni della famiglia \func{exec}.} - \label{fig:proc_exec_relat} -\end{figure} - La seconda differenza fra le funzioni riguarda le modalità con cui si specifica il programma che si vuole eseguire. Con lo mnemonico ``\texttt{p}'' si indicano le due funzioni che replicano il comportamento della shell nello @@ -1574,10 +1579,8 @@ seguente: \item i limiti sulle risorse (vedi sez.~\ref{sec:sys_resource_limit}); \item i valori delle variabili \var{tms\_utime}, \var{tms\_stime}; \var{tms\_cutime}, \var{tms\_ustime} (vedi sez.~\ref{sec:sys_cpu_times}); -% TODO ===========Importante============= -% TODO questo sotto è incerto, verificare -% TODO ===========Importante============= -\item la maschera dei segnali (si veda sez.~\ref{sec:sig_sigmask}). +\item la maschera dei segnali (si veda sez.~\ref{sec:sig_sigmask}); +\item l'insieme dei segnali pendenti (vedi sez.~\ref{sec:sig_gen_beha}). \end{itemize*} Una serie di proprietà del processo originale, che non avrebbe senso mantenere @@ -1586,8 +1589,6 @@ indirizzi totalmente indipendente e ricreato da zero, vengono perse con l'esecuzione di una \func{exec}. Lo standard POSIX.1-2001 prevede che le seguenti proprietà non vengano preservate: \begin{itemize*} -\item l'insieme dei segnali pendenti (vedi sez.~\ref{sec:sig_gen_beha}), che - viene cancellato; \item gli eventuali stack alternativi per i segnali (vedi sez.~\ref{sec:sig_specific_features}); \item i \textit{directory stream} (vedi sez.~\ref{sec:file_dir_read}), che @@ -1621,9 +1622,9 @@ nell'esecuzione della funzione \func{exec}, queste sono: pendenti vengono cancellate; \item le \textit{capabilities} vengono modificate come illustrato in sez.~\ref{sec:proc_capabilities}; -\item tutti i \textit{thread} tranne il chiamante (vedi - sez.~\ref{sec:thread_xxx}) sono cancellati e tutti gli oggetti ad essi - relativi (vedi sez.~\ref{sec:thread_xxx}) rimossi; +\item tutti i \textit{thread} tranne il chiamante\unavref{ (vedi + sez.~\ref{sec:thread_xxx})} vengono cancellati e tutti gli oggetti ad essi + relativi\unavref{ (vedi sez.~\ref{sec:thread_xxx})} sono rimossi; \item viene impostato il flag \const{PR\_SET\_DUMPABLE} di \func{prctl} (vedi sez.~\ref{sec:process_prctl}) a meno che il programma da eseguire non sia \acr{suid} o \acr{sgid} (vedi sez.~\ref{sec:proc_access_id} e @@ -1899,31 +1900,73 @@ sez.~\ref{sec:proc_access_id} seguono la semantica POSIX che prevede l'esistenza dell'\ids{UID} salvato e del \ids{GID} salvato, sono rispettivamente \funcd{setuid} e \funcd{setgid}; i loro prototipi sono: -\begin{funcproto}{ +\begin{funcproto}{ \fhead{unistd.h} \fhead{sys/types.h} \fdecl{int setuid(uid\_t uid)} -\fdesc{Imposta l'\ids{UID} del processo corrente.} +\fdesc{Imposta l'\ids{UID} del processo corrente.} \fdecl{int setgid(gid\_t gid)} -\fdesc{Imposta il \ids{GID} del processo corrente.} +\fdesc{Imposta il \ids{GID} del processo corrente.} } {Le funzioni ritornano $0$ in caso di successo e $-1$ per un errore, nel qual -caso \var{errno} può assumere solo il valore \errcode{EPERM}. +caso \var{errno} uno dei valori: +\begin{errlist} +\item[\errcode{EAGAIN}] (solo per \func{setuid}) la chiamata cambierebbe + l'\ids{UID} reale ma il kernel non dispone temporaneamente delle risorse per + farlo, oppure, per i kernel precendenti il 3.1, il cambiamento + dell'\ids{UID} reale farebbe superare il limite per il numero dei processi + \const{RLIMIT\_NPROC} (vedi sez.~\ref{sec:sys_resource_limit}). +\item[\errcode{EINVAL}] il valore di dell'argomento non è valido per il + \textit{namespace} corrente (vedi sez.~\ref{sec:process_namespaces}). +\item[\errcode{EPERM}] non si hanno i permessi per l'operazione richiesta. +\end{errlist} } \end{funcproto} Il funzionamento di queste due funzioni è analogo, per cui considereremo solo la prima, la seconda si comporta esattamente allo stesso modo facendo -riferimento al \ids{GID} invece che all'\ids{UID}. Gli eventuali \ids{GID} +riferimento al \ids{GID} invece che all'\ids{UID}. Gli eventuali \ids{GID} supplementari non vengono modificati. L'effetto della chiamata è diverso a seconda dei privilegi del processo; se -l'\ids{UID} effettivo è zero (cioè è quello dell'amministratore di sistema) -allora tutti gli identificatori (\textit{real}, \textit{effective} e -\textit{saved}) vengono impostati al valore specificato da \param{uid}, -altrimenti viene impostato solo l'\ids{UID} effettivo, e soltanto se il valore -specificato corrisponde o all'\ids{UID} reale o all'\ids{UID} salvato. Negli -altri casi viene segnalato un errore con \errcode{EPERM}. +l'\ids{UID} effettivo è zero (cioè è quello dell'amministratore di sistema o +il processo ha la la capacità \const{CAP\_SETUID}) allora tutti gli +identificatori (\textit{real}, \textit{effective} e \textit{saved}) vengono +impostati al valore specificato da \param{uid}, altrimenti viene impostato +solo l'\ids{UID} effettivo, e soltanto se il valore specificato corrisponde o +all'\ids{UID} reale o all'\ids{UID} salvato, ottenendo un errore di +\errcode{EPERM} negli altri casi. + +E' importante notare che la funzione può fallire con \errval{EAGAIN} anche +quando viene invocata da un processo con privilegi di amministratore per +cambiare il proprio l'\ids{UID} reale, sia per una temporanea indisponibilità +di risorse del kernel, sia perché l'utente di cui si vuole assumere +l'\ids{UID} andrebbe a superare un eventuale limite sul numero di processi (il +limite \const{RLIMIT\_NPROC}, che tratteremo in +sez.~\ref{sec:sys_resource_limit}),\footnote{non affronteremo qui l'altro caso + di errore, che può avvenire solo quando si esegue la funzione all'interno di + un diverso \textit{user namespace}, argomento su cui torneremo in + sez.~\ref{sec:process_namespaces}.} pertanto occorre sempre verificare lo +stato di uscita della funzione. + +Non controllare questo tipo di errori perché si presume che la funzione abbia +sempre successo quando si hanno i privilegi di amministratore può avere +conseguente devastanti per la sicurezza, in particolare quando la si usa per +cedere i suddetti privilegi ed eseguire un programma per conto di un utente +non privilegiato. + +E' per diminuire l'impatto di questo tipo di disattenzioni che a partire dal +kernel 3.1 il comportamento di \func{setuid} e di tutte le analoghe funzioni +che tratteremo nel seguito di questa sezione è stato modificato e nel caso di +superamento del limite sulle risorse esse hanno comunque successo. Quando +questo avviene il processo assume comunque il nuovo \ids{UID} ed il controllo +sul superamento di \const{RLIMIT\_NPROC} viene posticipato ad una eventuale +successiva invocazione di \func{execve} (essendo questo poi il caso d'uso più +comune). In tal caso, se alla chiamata ancora sussiste la situazione di +superamento del limite, sarà \func{execve} a fallire con un errore di +\const{EAGAIN}.\footnote{che pertanto, a partire dal kernel 3.1, può + restituire anche questo errore, non presente in altri sistemi + \textit{unix-like}.} Come accennato l'uso principale di queste funzioni è quello di poter consentire ad un programma con i bit \acr{suid} o \acr{sgid} impostati (vedi @@ -1935,12 +1978,14 @@ Come esempio per chiarire l'uso di queste funzioni prendiamo quello con cui viene gestito l'accesso al file \sysfiled{/var/run/utmp}. In questo file viene registrato chi sta usando il sistema al momento corrente; chiaramente non può essere lasciato aperto in scrittura a qualunque utente, che potrebbe -falsificare la registrazione. Per questo motivo questo file (e l'analogo -\sysfiled{/var/log/wtmp} su cui vengono registrati login e logout) appartengono -ad un gruppo dedicato (in genere \acr{utmp}) ed i programmi che devono -accedervi (ad esempio tutti i programmi di terminale in X, o il programma -\cmd{screen} che crea terminali multipli su una console) appartengono a questo -gruppo ed hanno il bit \acr{sgid} impostato. +falsificare la registrazione. + +Per questo motivo questo file (e l'analogo \sysfiled{/var/log/wtmp} su cui +vengono registrati login e logout) appartengono ad un gruppo dedicato (in +genere \acr{utmp}) ed i programmi che devono accedervi (ad esempio tutti i +programmi di terminale in X, o il programma \cmd{screen} che crea terminali +multipli su una console) appartengono a questo gruppo ed hanno il bit +\acr{sgid} impostato. Quando uno di questi programmi (ad esempio \cmd{xterm}) viene lanciato, la situazione degli identificatori è la seguente: @@ -1982,10 +2027,10 @@ Occorre però tenere conto che tutto questo non è possibile con un processo con i privilegi di amministratore, in tal caso infatti l'esecuzione di una \func{setuid} comporta il cambiamento di tutti gli identificatori associati al processo, rendendo impossibile riguadagnare i privilegi di amministratore. -Questo comportamento è corretto per l'uso che ne fa \cmd{login} una volta che -crea una nuova shell per l'utente, ma quando si vuole cambiare soltanto -l'\ids{UID} effettivo del processo per cedere i privilegi occorre -ricorrere ad altre funzioni. +Questo comportamento è corretto per l'uso che ne fa un programma come +\cmd{login} una volta che crea una nuova shell per l'utente, ma quando si +vuole cambiare soltanto l'\ids{UID} effettivo del processo per cedere i +privilegi occorre ricorrere ad altre funzioni. Le due funzioni di sistema \funcd{setreuid} e \funcd{setregid} derivano da BSD che, non supportando (almeno fino alla versione 4.3+BSD) gli identificatori @@ -2001,7 +2046,7 @@ del gruppo \textit{saved}, le usa per poter scambiare fra di loro \fdesc{Imposta \ids{GID} reale e \ids{GID} effettivo del processo corrente.} } {Le funzioni ritornano $0$ in caso di successo e $-1$ per un errore, nel qual -caso \var{errno} può assumere solo il valore \errcode{EPERM}. +caso \var{errno} assume i valori visti per \func{setuid}/\func{setgid}. } \end{funcproto} @@ -2009,12 +2054,13 @@ Le due funzioni sono identiche, quanto diremo per la prima riguardo gli \ids{UID} si applica alla seconda per i \ids{GID}. La funzione \func{setreuid} imposta rispettivamente l'\ids{UID} reale e l'\ids{UID} effettivo del processo corrente ai valori specificati da \param{ruid} -e \param{euid}. I processi non privilegiati possono impostare solo valori che -corrispondano o al loro \ids{UID} effettivo o a quello reale o a quello -salvato, valori diversi comportano il fallimento della chiamata. -L'amministratore invece può specificare un valore qualunque. Specificando un -argomento di valore $-1$ l'identificatore corrispondente verrà lasciato -inalterato. +e \param{euid}. + +I processi non privilegiati possono impostare solo valori che corrispondano o +al loro \ids{UID} effettivo o a quello reale o a quello salvato, valori +diversi comportano il fallimento della chiamata. L'amministratore invece può +specificare un valore qualunque. Specificando un argomento di valore $-1$ +l'identificatore corrispondente verrà lasciato inalterato. Con queste funzioni si possono scambiare fra loro gli \ids{UID} reale ed effettivo, e pertanto è possibile implementare un comportamento simile a @@ -2053,7 +2099,7 @@ del gruppo \textit{effective} ed i loro prototipi sono: \fdesc{Imposta il \ids{GID} effettivo del processo corrente.} } {Le funzioni ritornano $0$ in caso di successo e $-1$ per un errore, nel qual -caso \var{errno} può assumere solo il valore \errcode{EPERM}. +caso \var{errno} assume i valori visti per \func{setuid}/\func{setgid}. } \end{funcproto} @@ -4235,6 +4281,10 @@ elenco, che illustra quelle attualmente disponibili:\footnote{si fa \end{basedescript} +\subsection{I \textit{namespace} ed i \textit{container}} +\label{sec:process_namespaces} + + %TODO sezione separata sui namespace %TODO trattare unshare, vedi anche http://lwn.net/Articles/532748/ -- 2.30.2