X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=blobdiff_plain;f=prochand.tex;h=c2af15d637ce024f93bd9c344060da9445b84e20;hb=738b2fb622cc473e18d536f5a797233f4ec8a783;hp=9eb7912a0ddd47eb9c4a3b8b2db8ecafca1156d8;hpb=e6ae2ca5d94550028d23c73974f336291beeb876;p=gapil.git diff --git a/prochand.tex b/prochand.tex index 9eb7912..c2af15d 100644 --- a/prochand.tex +++ b/prochand.tex @@ -8,16 +8,20 @@ base per l'allocazione e l'uso delle risorse del sistema. Nel precedente capitolo abbiamo visto come funziona un singolo processo, in questo capitolo affronteremo i dettagli della creazione e della distruzione dei processi, della gestione dei loro attributi e privilegi, e di tutte le -funzioni a questo connesse. +funzioni a questo connesse. Infine nella sezione finale affronteremo alcune +problematiche generiche della programmazione in ambiente multitasking. + \section{Introduzione} \label{sec:proc_gen} Partiremo con una introduzione generale ai concetti che stanno alla base della -gestione dei processi in unix. Introdurremo in questa sezione l'architettura -della gestione dei processi e le sue principali caratteristiche, e daremo una -panoramica sull'uso delle principali funzioni per la gestione dei processi. +gestione dei processi in un sitema unix-like. Introdurremo in questa sezione +l'architettura della gestione dei processi e le sue principali +caratteristiche, e daremo una panoramica sull'uso delle principali funzioni +per la gestione dei processi. + \subsection{La gerarchia dei processi} \label{sec:proc_hierarchy} @@ -533,8 +537,8 @@ sequenza impredicibile. Le modalit \end{enumerate} Oltre ai file aperti i processi figli ereditano dal padre una serie di altre -proprietà comuni; in dettaglio avremo che dopo l'esecuzione di una \func{fork} -padre e figlio avranno in comune: +proprietà; la lista dettagliata delle proprietà che padre e figlio hanno in +comune dopo l'esecuzione di una \func{fork} è la seguente: \begin{itemize*} \item i file aperti (e gli eventuali flag di \textit{close-on-exec} se settati). @@ -554,7 +558,7 @@ padre e figlio avranno in comune: \item i limiti sulle risorse \item le variabili di ambiente (vedi \secref{sec:proc_environ}). \end{itemize*} -le differenze invece sono: +le differenze fra padree figlio dopo la \func{fork} invece sono: \begin{itemize*} \item il valore di ritorno di \func{fork}. \item il \textit{process id}. @@ -756,7 +760,7 @@ di terminare il processo che li ha generati, in modo che \cmd{init} possa adottarli e provvedere a concludere la terminazione. -\subsection{Le funzioni \texttt{wait} e \texttt{waitpid}} +\subsection{Le funzioni \func{wait} e \func{waitpid}} \label{sec:proc_wait} Abbiamo già accennato come uno degli usi possibili delle capacità multitasking @@ -787,6 +791,7 @@ caso di errore; \var{errno} pu \item \macro{EINTR} la funzione è stata interrotta da un segnale. \end{errlist} \end{functions} + è presente fin dalle prime versioni di unix; la funzione ritorna alla conclusione del primo figlio (o immediatamente se un figlio è già uscito). Nel caso un processo abbia più figli il valore di ritorno permette di identificare @@ -959,6 +964,7 @@ accessibili definendo la costante \macro{\_USE\_BSD}, sono: Prima versione, equivalente a \func{wait4(-1, \&status, opt, rusage)} è ormai deprecata in favore di \func{wait4}. \end{functions} +\noindent la struttura \type{rusage} è definita in \file{sys/resource.h}, e viene utilizzata anche dalla funzione \func{getrusage} per ottenere le risorse di sistema usate dal processo; in Linux è definita come: @@ -988,7 +994,7 @@ struct rusage { \end{lstlisting} \end{minipage} \normalsize - \caption{La struttura \texttt{rusage} per la lettura delle informazioni dei + \caption{La struttura \var{rusage} per la lettura delle informazioni dei delle risorse usate da un processo.} \label{fig:proc_rusage_struct} \end{figure} @@ -1000,7 +1006,7 @@ sono mantenuti sono: \var{ru\_utime}, \var{ru\_stime}, \var{ru\_minflt}, \var{ru\_majflt}, e \var{ru\_nswap}. -\subsection{Le funzioni \texttt{exec}} +\subsection{Le funzioni \func{exec}} \label{sec:proc_exec} Abbiamo già detto che una delle modalità principali con cui si utilizzano i @@ -1360,8 +1366,11 @@ servano di nuovo. Questo in Linux viene fatto usando altri due gruppi di identificatori, il \textit{saved} ed il \textit{filesystem}, analoghi ai precedenti. Il primo gruppo è lo stesso usato in SVr4, e previsto dallo standard POSIX quando è -definita la costante \macro{\_POSIX\_SAVED\_IDS}, il secondo gruppo è -specifico di Linux e viene usato per migliorare la sicurezza con NFS. +definita la costante \macro{\_POSIX\_SAVED\_IDS}\footnote{in caso si abbia a + cuore la portabilità del programma su altri unix è buona norma controllare + sempre la disponibilità di queste funzioni controllando se questa costante è + definita}, il secondo gruppo è specifico di Linux e viene usato per +migliorare la sicurezza con NFS. Il \textit{saved user id} e il \textit{saved group id} sono copie dell'\textit{effective user id} e dell'\textit{effective group id} del @@ -1478,14 +1487,14 @@ avr \end{eqnarray*} consentendo l'accesso a \file{/var/log/utmp}. -Occorre però tenere conto che tutto questo non è possibile con root, in tal -caso infatti l'esecuzione 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'\textit{effective user id} del processo per cedere i -privilegi occorre ricorrere ad altre funzioni (si veda ad esempio -\secref{sec:proc_seteuid}). +Occorre però tenere conto che tutto questo non è possibile con un processo con +i privilegi di root, in tal caso infatti l'esecuzione 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'\textit{effective user id} del processo per cedere i privilegi occorre +ricorrere ad altre funzioni (si veda ad esempio \secref{sec:proc_seteuid}). \subsection{Le funzioni \func{setreuid} e \func{setresuid}} @@ -1512,11 +1521,13 @@ Le funzioni restituiscono 0 in caso di successo e -1 in caso di fallimento: l'unico errore possibile è \macro{EPERM}. \end{functions} -Gli utenti normali possono settare gli identificatori soltanto ai valori del -loro \textit{effective id} o \textit{real id}, valori diversi comportano il -fallimento della chiamata; l'amministratore invece può specificare un valore -qualunque. Specificando -1 come valore l'identificatore corrispondente viene -lasciato inalterato. +I processi non privileguiati possono settare i \textit{real id} soltanto ai +valori dei loro \textit{effective id} o \textit{real id} e gli +\textit{effective id} ai valori dei loro \textit{real id}, \textit{effective + id} o \textit{saved id}; valori diversi comportano il fallimento della +chiamata; l'amministratore invece può specificare un valore qualunque. +Specificando un valore di -1 l'identificatore corrispondente viene lasciato +inalterato. Con queste funzione si possono scambiare fra loro \textit{real id} e \textit{effective id}, e pertanto è possibile implementare un comportamento @@ -1525,24 +1536,61 @@ un primo scambio, e recuperandoli, eseguito il lavoro non privilegiato, con un secondo scambio. In questo caso però occorre porre molta attenzione quando si creano nuovi -processi nella fase intermedia, questi infatti avranno un \textit{real id} -privilegiato, che dovrà essere esplicitamente eliminato prima di porre in -esecuzione un nuovo processo, che altrimenti potrebbero riottenere detti -privilegi. +processi nella fase intermedia in cui si sono scambiati gli identificatori, in +questo caso infatti essi avranno un \textit{real id} privilegiato, che dovrà +essere esplicitamente eliminato prima di porre in esecuzione un nuovo +programma (occorrerà cioè eseguire un'altra chiamata dopo la \func{fork}, e +prima della \func{exec} per uniformare i \textit{real id} agli +\textit{effective id}) in caso contrario quest'ultimo potrebbe a sua volta +effettuare uno scambio e riottenere privilegi non previsti. + +Lo stesso problema di propagazione dei privilegi ad eventuali processi figli +si porrebbe per i \textit{saved id}. Queste funzioni derivano da +un'implementazione che non ne prevede la presenza, e quindi non è possibile +usarle per correggere la situazione come nel caso precedente, per questo +motivo tutte le volte che uno degli identificatori viene modificato ad un +valore diverso dal precedente \textit{real id}, il \textit{saved id} viene +sempre settato al valore dell'\textit{effective id}. + + +\subsection{Le funzioni \func{setresuid} e \func{setresgid}} +\label{sec:proc_setresuid} + +Queste due funzioni sono una estensione introdotta in Linux dal kernel 2.1.44, +e permettono un completo controllo su tutti gli identificatori (\textit{real}, +\textit{effective} e \textit{saved}), i prototipi sono: + +\begin{functions} +\headdecl{unistd.h} +\headdecl{sys/types.h} + +\funcdecl{int setresuid(uid\_t ruid, uid\_t euid, uid\_t suid)} setta il +\textit{real user ID}, l'\textit{effective user ID} e il \textit{saved user + ID} del processo corrente ai valori specificati rispettivamente da +\var{ruid}, \var{euid} e \var{suid}. + +\funcdecl{int setresgid(gid\_t rgid, gid\_t egid, gid\_t sgid)} setta il +\textit{real group ID}, l'\textit{effective group ID} e il \textit{saved group + ID} del processo corrente ai valori specificati rispettivamente da +\var{rgid}, \var{egid} e \var{sgid}. + +Le funzioni restituiscono 0 in caso di successo e -1 in caso di fallimento: +l'unico errore possibile è \macro{EPERM}. +\end{functions} + +I processi non privilegiati possono cambiare uno qualunque degli +identificatori usando uno qualunque dei valori correnti di \textit{real id}, +\textit{effective id} o \textit{saved id}, l'ammnistratore può specificare i +valori che vuole; un valore di -1 per un qualunque parametro lascia inalterato +l'dentificatore corrispondente. -Come accennato le funzioni derivano da un'implementazione che non prevedeva la -presenza di \textit{saved id}, per evitare che questo possa essere -riutilizzato nella fase intermedia per recuperare un \textit{effective id} -(privilegiato) originale, tutte le volte che uno degli identificatori viene -modificato da una di queste funzioni, il \textit{saved id} viene sempre -settato al nuovo valore che viene ad assumere l'\textit{effective id}. \subsection{Le funzioni \func{seteuid} e \func{setegid}} \label{sec:proc_seteuid} Queste funzioni sono un'estensione allo standard POSIX.1 (ma sono comunque -supportate dalla maggior parte degli unix) usate per cambiare gli +supportate dalla maggior parte degli unix) e usate per cambiare gli \textit{effective id}; i loro prototipi sono: \begin{functions} @@ -1550,47 +1598,87 @@ supportate dalla maggior parte degli unix) usate per cambiare gli \headdecl{sys/types.h} \funcdecl{int seteuid(uid\_t uid)} setta l'\textit{effective user ID} del -processo corrente. +processo corrente a \var{uid}. \funcdecl{int setegid(gid\_t gid)} setta l'\textit{effective group ID} del -processo corrente. +processo corrente a \var{gid}. Le funzioni restituiscono 0 in caso di successo e -1 in caso di fallimento: l'unico errore possibile è \macro{EPERM}. \end{functions} +Gli utenti normali possono settare l'\textit{effective id} solo al valore del +\textit{real id} o del \textit{saved id}, l'amministratore può specificare +qualunque valore. Queste funzioni sono usate per permettere a root di settare +solo l'\textit{effective id}, dato che l'uso normale di \func{setuid} comporta +il settaggio di tutti gli identificatori. + +\subsection{Le funzioni \func{setfsuid} e \func{setfsgid}} +\label{sec:proc_setfsuid} - -\subsection{Le funzioni \func{setresuid} e \func{setresgid}} -\label{sec:proc_setresuid} - -Queste due funzioni sono una estensione introdotta in Linux dal kernel 2.1.44, -e permettono un completo controllo su tutti gli identificatori (\textit{real}, -\textit{effective} e \textit{saved}), i prototipi sono: +Queste funzioni sono usate per settare gli identificatori usati da Linux per +il controllo dell'accesso ai file. Come già accennato in +\secref{sec:proc_user_group} in Linux è definito questo ulteriore gruppo di +identificatori, che di norma sono assolutamente equivalenti agli +\textit{effective id}, dato che ogni cambiamento di questi ultimi viene +immediatamente riportato sui \textit{filesystem id}. + +C'è un solo caso in cui si ha necessità di introdurre una differenza fra +\textit{effective id} e \textit{filesystem id}, ed è per ovviare ad un +problema di sicurezza che si presenta quando si deve implementare un server +NFS. Il server NFS infatti deve poter cambiare l'identificatore con cui accede +ai file per assumere l'identità del singolo utente remoto, ma se questo viene +fatto cambiando l'\textit{effective id} o il \textit{real id} il server si +espone alla ricezione di eventuali segnali ostili da parte dell'utente di cui +ha temporaneamente assunto l'identità. Cambiando solo il \textit{filesystem + id} si ottengono i privilegi necessari per accedere ai file, mantenendo +quelli originari per quanto riguarda tutti gli altri controlli di accesso. + +Le due funzioni usate per cambiare questi identificatori sono \func{setfsuid} +e \func{setfsgid}, ovviamenete sono specifiche di Linux e non devono essere +usate se si intendono scrivere programmi portabili; i loro prototipi sono: \begin{functions} -\headdecl{unistd.h} -\headdecl{sys/types.h} +\headdecl{sys/fsuid.h} -\funcdecl{int setresuid(uid\_t ruid, uid\_t euid, uid\_t suid)} setta il -\textit{real user ID}, l'\textit{effective user ID} e il \textit{saved user - ID} del processo corrente ai valori specificati rispettivamente da -\var{ruid}, \var{euid} e \var{suid}. - -\funcdecl{int setresgid(gid\_t rgid, gid\_t egid, gid\_t sgid)} setta il -\textit{real group ID}, l'\textit{effective group ID} e il \textit{saved group - ID} del processo corrente ai valori specificati rispettivamente da -\var{rgid}, \var{egid} e \var{sgid}. +\funcdecl{int setfsuid(uid\_t fsuid)} setta il \textit{filesystem user ID} del +processo corrente a \var{fsuid}. + +\funcdecl{int setfsgid(gid\_t fsgid)} setta l'\textit{filesystem group ID} del +processo corrente a \var{fsgid}. Le funzioni restituiscono 0 in caso di successo e -1 in caso di fallimento: l'unico errore possibile è \macro{EPERM}. \end{functions} +Queste funzioni hanno successo solo se il processo chiamante ha i privilegi di +amministratore o, per gli altri utenti, se il valore specificato coincide con +uno dei \textit{real}, \textit{effective} o \textit{saved id}. -\subsection{Le funzioni \func{setfsuid} e \func{setfsgid}} -\label{sec:proc_setfsuid} +\section{Problematiche di programmazione multitasking} +\label{sec:proc_multi_prog} + +Benché i processi siano strutturati in modo da apparire il più possibile come +indipendenti l'uno dall'altro, nella programmazione in un sistema multiutente +occorre tenere conto di tutta una serie di problematiche che normalmente non +esistono quando si ha a che fare con un sistema in cui viene eseguito un solo +programma alla volta. + +Pur non essendo tutto questo direttamente legato alla modalità specifica in +cui il multitasking è implementato in un sistema unix-like, siccome la +gestione dei processi è stata affrontata in questo capitolo, tratteremo in +questa sezione conclusiva anche queste problematiche, esaminandone le +caratteristiche fondamentali e le modalità con cui si affrontano. + + +\subsection{Le funzioni rientranti} +\label{sec:proc_reentrant} + + +\subsection{Le operazioni atomiche} +\label{sec:proc_atom_oper} \subsection{Le \textit{race condition}} @@ -1603,3 +1691,8 @@ l'ordine di esecuzione di un processo, senza appositi meccanismi di sincronizzazione, non è assolutamente prevedibile, queste situazioni sono fonti di errori molto subdoli, che possono verificarsi solo in condizioni particolari e quindi difficilmente riproducibili. + + +\subsection{I \textit{deadlock}} +\label{sec:proc_deadlock} +