From: Simone Piccardi Date: Fri, 28 Dec 2001 10:58:49 +0000 (+0000) Subject: Finiti file temporanei e iniziata chroot, inserita sezione sullo scheduler X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=b72f18d024a942eca58a8109c60479d835ee7350 Finiti file temporanei e iniziata chroot, inserita sezione sullo scheduler e il controllo delle priorita` dei processi --- diff --git a/filedir.tex b/filedir.tex index 3553486..5d1c21e 100644 --- a/filedir.tex +++ b/filedir.tex @@ -718,9 +718,155 @@ 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 \textit{race condition} (si ricordi quanto visto in \secref{sec:proc_race_cond}). -Per questo motivo il kernel le \acr{glibc} provvedono una serie di funzioni da -utilizzare per la gestione dei file temporanei. +Le \acr{glibc} provvedono varie funzioni per generare nomi di file temporanei, +di cui si abbia certezza di unicità (al momento della generazione); la prima +di queste funzioni è \func{tmpnam} il cui prototipo è: +\begin{prototype}{stdio.h}{char *tmpnam(char *string)} + Restituisce il puntatore ad una stringa contente un nome di file valido e + non esistente al momento dell'invocazione. + + \bodydesc{La funzione ritorna il puntatore alla stringa con il nome o + \macro{NULL} in caso di fallimento. Non sono definiti errori.} +\end{prototype} +\noindent se si è passato un puntatore \param{string} non nullo questo deve +essere di dimensione \macro{L\_tmpnam} (costante definita in \file{stdio.h}, +come \macro{P\_tmpdir} e \macro{TMP\_MAX}) 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 \macro{TMP\_MAX} volte. Al nome viene automaticamente aggiunto come +prefisso la directory specificata da \macro{P\_tmpdir}. + +Di questa funzione esiste una versione rientrante, \func{tmpnam\_r}, che non +fa nulla quando si passa \macro{NULL} come parametro. Una funzione simile, +\func{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)} + Restituisce il puntatore ad una stringa contente un nome di file valido e + non esistente al momento dell'invocazione. + + \bodydesc{La funzione ritorna il puntatore alla stringa con il nome o + \macro{NULL} in caso di fallimento, \var{errno} viene settata a + \macro{ENOMEM} qualora fallisca l'allocazione della stringa.} +\end{prototype} +La funzione alloca con \code{malloc} la stringa in cui resituisce il nome, per +cui è sempre rientrante, occorre però ricordarsi di disallocare 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 accessibili), la prima valida +delle seguenti: +\begin{itemize*} +\item La variabile di ambiente \macro{TMPNAME} (non ha effetto se non è + definita o se il programma chiamante è \acr{suid} o \acr{sgid}, vedi + \secref{sec:file_suid_sgid}). +\item il valore dell'argomento \param{dir} (se diverso da \macro{NULL}). +\item Il valore della costante \macro{P\_tmpdir}. +\item la directory \file{/tmp}. +\end{itemize*} + +In ogni caso, anche se la generazione del nome è casuale, ed è molto difficile +ottere 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 \macro{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 \func{tempfile}, il cui 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 \macro{NULL} in caso di errore, nel qual + caso \var{errno} viene settata a + \begin{errlist} + \item[\macro{EINTR}] La funzione è stata interrotta da un segnale. + \item[\macro{EEXIST}] Non è stato possibile generare un nome univoco. + \end{errlist} + ed inoltre \macro{EFAULT}, \macro{EMFILE}, \macro{ENFILE}, \macro{ENOSPC}, + \macro{EROFS} e \macro{EACCESS}.} +\end{prototype} +\noindent restituisce direttamente uno stream già aperto (in modalità +\code{r+b}, si veda \secref{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 \acr{glibc} +prima tentano con \macro{P\_tmpdir} e poi con \file{/tmp}. Questa funzione è +rientrante e non soffre di problemi di \textit{race condition}. + +Alcune versioni meno recenti di Unix non supportano queste funzioni; in questo +caso si possono usare le vecchie funzioni \func{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 filename univoco sostituendo le \code{XXXXXX} finali di + \param{template}. + + \bodydesc{La funzione ritorna il puntatore \param{template} in caso di + successo e \macro{NULL} in caso di errore, nel qual caso \var{errno} viene + settata a: + \begin{errlist} + \item[\macro{EINVAL}] \param{template} non termina con \code{XXXXXX}. + \end{errlist}} +\end{prototype} +\noindent dato che \param{template} deve poter essere modificata dalla +funzione non si può usare una stringa costante. Tutte le avvertenze riguardo +alle possibili \textit{race condition} date per \func{tmpnam} continuano a +valere; inoltre in alcune vecchie implementazioni il valore di usato per +sostituire le \code{XXXXXX} viene formato con il \acr{pid} del processo più +una lettera, il che mette a disposizione solo 26 possibilità, e rende il nome +temporaneo facile da indovinare. Per tutti questi motivi la funzione è +deprecata e non dovrebbe mai essere usata. + + + +La seconda funzione, \func{mkstemp} è sostanzialmente equivalente a +\func{tmpfile}, ma restituisce un file descriptor invece di uno stream; il suo +prototipo è: +\begin{prototype}{stlib.h}{int mkstemp(char *template)} + Genera un file temporaneo con un nome ottenuto sostituendo le \code{XXXXXX} + finali di \param{template}. + + \bodydesc{La funzione ritorna il file descriptor in caso successo e + -1 in caso di errore, nel qual caso \var{errno} viene settata a: + \begin{errlist} + \item[\macro{EINVAL}] \param{template} non termina con \code{XXXXXX}. + \item[\macro{EEXIST}] non è riuscita a creare un file temporano, il + contenuto di \param{template} è indefinito. + \end{errlist}} +\end{prototype} +\noindent come per \func{mktemp} \param{template} non può essere una stringa +costante. La funzione apre un file in lettura/scrittura con la funzione +\func{open}, usando l'opzione \macro{O\_EXCL} (si veda +\secref{sec:file_open}), in questo modo al ritorno della funzione si ha la +certezza di essere i soli utenti del file. I permessi sono settati al valore +\code{0600}\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 i + contenuti del file.} (si veda \secref{sec:file_perm_overview}). + +In OpenBSD è stata introdotta un'altra funzione\footnote{introdotta anche in + Linux a partire dalle \acr{glibc} 2.1.91.} simile alle precedenti, +\func{mkdtemp}, che crea una directory temporanea; il suo prototipo è: +\begin{prototype}{stlib.h}{char *mkdtemp(char *template)} + Genera una directory temporaneo il cui nome è ottenuto sostituendo le + \code{XXXXXX} finali di \param{template}. + + \bodydesc{La funzione ritorna il puntatore al nome della directory in caso + successo e \macro{NULL} in caso di errore, nel qual caso \var{errno} viene + settata a: + \begin{errlist} + \item[\macro{EINVAL}] \param{template} non termina con \code{XXXXXX}. + \end{errlist} + più gli altri eventuali codici di errore di \func{mkdir}.} +\end{prototype} +\noindent la directory è creata con permessi \code{0700} (al solito si veda +\capref{cha:file_unix_interface} per i dettagli); dato che la creazione della +directory è sempre esclusiva i precedenti problemi di \textit{race condition} +non si pongono. \section{La manipolazione delle caratteristiche dei files} @@ -1744,11 +1890,43 @@ che per il file \label{sec:file_chroot} Benché non abbia niente a che fare con permessi, utenti e gruppi, questa -funzione viene usata spesso per limitare le capacità dei programmi, ed è -pertanto pertinente al controllo di accesso. Come accennato in -\secref{sec:proc_fork} ogni processo oltre ad una directory di lavoro -corrente, ha anche una directory radice, cioè una directory che per il -processo costituisce la radice dell'albero del filesystem. +funzione viene usata spesso per restringere le capacità di acccesso di un +programma ad una sezione limitata del filesystem, per cui ne parleremo in +questa sezione. + +Come accennato in \secref{sec:proc_fork} ogni processo oltre ad una directory +di lavoro corrente, ha anche una directory radice, cioè una directory che per +il processo costituisce la radice dell'albero del filesystem. Questa viene +eredidata dal padre per ogni processo figlio, (come si può vedere da +\figref{fig:proc_task_struct} è tenuta nella struttura \type{fs\_struct} +insieme alla directory di lavoro corrente e alla \var{umask}) e quindi di +norma coincide con la \file{/} del sistema. + +In certe situazioni però per motivi di sicurezza non si vuole che un processo +possa accedere a tutto il filesystem; per questo si può cambiare la directory +radice con la funzione \func{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 \texttt{errno} viene settato ai valori: + \begin{errlist} + \item[\macro{EPERM}] L'\textit{effective user id} non è zero. + \end{errlist} + ed inoltre \macro{EFAULT}, \macro{ENAMETOOLONG}, \macro{ENOENT}, + \macro{ENOMEM}, \macro{ENOTDIR}, \macro{EACCES}, \macro{ELOOP}; + \macro{EROFS} e \macro{EIO}.} +\end{prototype} + + + + + +un caso tipico è quello di un server +ftp che dovrebbe limitarsi + -In generale questa directory coincide con la +Il sistema però consente di cambiare questa directory con la funzione +\func{chroot} diff --git a/macro.tex b/macro.tex index 7045267..9854b62 100644 --- a/macro.tex +++ b/macro.tex @@ -121,7 +121,7 @@ tab.~\thechapter.\theusercount} \newcommand{\cmd}[1]{\texttt{#1}} % shell command \newcommand{\code}[1]{\texttt{#1}} % for simple code \newcommand{\func}[1]{% -\index{\texttt{#1}}\texttt{#1}% +\index{#1@{\tt {#1}}}\texttt{#1}% } % library function (or system call) \newcommand{\macro}[1]{\texttt{#1}} % macro constant \newcommand{\var}[1]{\texttt{#1}} % variable diff --git a/prochand.tex b/prochand.tex index adf67a3..579ab48 100644 --- a/prochand.tex +++ b/prochand.tex @@ -25,7 +25,7 @@ caratteristiche, dando una panoramica sull'uso delle principali funzioni di gestione. -\subsection{La gerarchia dei processi} +\subsection{L'architettura della gestione dei processi} \label{sec:proc_hierarchy} A differenza di quanto avviene in altri sistemi (ad esempio nel VMS la @@ -114,7 +114,40 @@ risultato del comando \cmd{pstree} che permette di mostrare questa struttura, alla cui base c'è \cmd{init} che è progenitore di tutti gli altri processi. -\subsection{Una panoramica sulle funzioni di gestione} +Il kernel mantiene una tabella dei processi attivi, la cosiddetta +\textit{process table}; per ciascun processo viene mantenuta una voce nella +tabella dei processi costituita da una struttura \type{task\_struct}, che +contiene tutte le informazioni rilevanti per quel processo. Tutte le strutture +usate a questo scopo sono dichiarate nell'header file \file{linux/sched.h}, ed +uno schema semplificato che riporta la struttura delle principali informazioni +contenute nella \type{task\_struct} (che in seguito incontreremo a più +riprese), è mostrato in \nfig. + +\begin{figure}[htb] + \centering + \includegraphics[width=13cm]{img/task_struct} + \caption{Schema semplificato dell'architettura delle strutture usate dal + kernel nella gestione dei processi.} + \label{fig:proc_task_struct} +\end{figure} + + +Come accennato in \secref{sec:intro_unix_struct} è lo \textit{scheduler} che +decide quale processo mettere in esecuzione; esso viene eseguito ad ogni +system call ed ad ogni interrupt, (ma può essere anche attivato +esplicitamente). Il timer di sistema provvede comunque a che esso sia invocato +periodicamente, generando un interrupt periodico secondo la frequenza +specificata dalla costante \macro{HZ}, definita in \file{asm/param.h} Il +valore usuale è 100 (è espresso in Hertz), si ha cioè un interrupt dal timer +ogni centesimo di secondo. + +Ogni volta che viene eseguito, lo \textit{scheduler} effettua il calcolo delle +priorità dei vari processi attivi (torneremo su questo in +\secref{sec:proc_priority}) e stabilisce quale di essi debba essere posto in +esecuzione fino alla successiva invocazione. + + +\subsection{Una panoramica sulle funzioni fondamentali} \label{sec:proc_handling_intro} I processi vengono creati dalla funzione \func{fork}; in molti unix questa è @@ -160,15 +193,15 @@ non ritorna mai (in quanto con essa viene eseguito un altro programma). -\section{La gestione dei processi} +\section{Le funzioni di base}% della gestione dei processi} \label{sec:proc_handling} In questa sezione tratteremo le problematiche della gestione dei processi all'interno del sistema, illustrandone tutti i dettagli. Inizieremo con le funzioni elementari che permettono di leggerne gli identificatori, per poi -passare alla spiegazione delle funzioni fondamentali che si usano per la -creazione e la terminazione dei processi, e per la messa in esecuzione degli -altri programmi. +passare alla spiegazione delle funzioni base che si usano per la creazione e +la terminazione dei processi, e per la messa in esecuzione degli altri +programmi. \subsection{Gli identificatori dei processi} @@ -555,7 +588,8 @@ comune dopo l'esecuzione di una \func{fork} \item gli identificatori per il controllo di sessione: il \textit{process group id} e il \textit{session id} ed il terminale di controllo (vedi \secref{sec:sess_xxx} e \secref{sec:sess_xxx}). -\item i flag di \acr{suid} e \acr{sgid} (vedi \secref{sec:file_suid_sgid}). +\item gli identificatori per il controllo di accesso (vedi + \secref{sec:proc_user_group}). \item la directory di lavoro e la directory radice (vedi \secref{sec:file_work_dir} e \secref{sec:file_chroot}). \item la maschera dei permessi di creazione (vedi \secref{sec:file_umask}). @@ -792,13 +826,11 @@ prototipo Sospende il processo corrente finché un figlio non è uscito, o finché un segnale termina il processo o chiama una funzione di gestione. -\bodydesc{ -La funzione restituisce il \acr{pid} del figlio in caso di successo e -1 in -caso di errore; \var{errno} può assumere i valori: +\bodydesc{La funzione restituisce il \acr{pid} del figlio in caso di successo + e -1 in caso di errore; \var{errno} può assumere i valori: \begin{errlist} \item[\macro{EINTR}] la funzione è stata interrotta da un segnale. - \end{errlist} -} + \end{errlist}} \end{functions} \noindent è presente fin dalle prime versioni di unix; la funzione ritorna non appena un @@ -980,38 +1012,9 @@ definendo la costante \macro{\_USE\_BSD}, sono: \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; la sua definizione è riportata in \nfig. -\begin{figure}[!htb] - \footnotesize - \centering - \begin{minipage}[c]{15cm} - \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{} -struct rusage { - struct timeval ru_utime; /* user time used */ - struct timeval ru_stime; /* system time used */ - long ru_maxrss; /* maximum resident set size */ - long ru_ixrss; /* integral shared memory size */ - long ru_idrss; /* integral unshared data size */ - long ru_isrss; /* integral unshared stack size */ - long ru_minflt; /* page reclaims */ - long ru_majflt; /* page faults */ - long ru_nswap; /* swaps */ - long ru_inblock; /* block input operations */ - long ru_oublock; /* block output operations */ - long ru_msgsnd; /* messages sent */ - long ru_msgrcv; /* messages received */ - long ru_nsignals; ; /* signals received */ - long ru_nvcsw; /* voluntary context switches */ - long ru_nivcsw; /* involuntary context switches */ -}; - \end{lstlisting} - \end{minipage} - \normalsize - \caption{La struttura \var{rusage} per la lettura delle informazioni dei - delle risorse usate da un processo.} - \label{fig:proc_rusage_struct} -\end{figure} +utilizzata anche dalla funzione \func{getrusage} (vedi \secref{sec:sys_xxx}) +per ottenere le risorse di sistema usate dal processo; la sua definizione è +riportata in \figref{fig:sys_rusage_struct}. In genere includere esplicitamente \file{} non è più necessario, ma aumenta la portabilità, e serve in caso si debba accedere @@ -1177,12 +1180,12 @@ Oltre a mantenere lo stesso \acr{pid}, il nuovo programma fatto partire da \func{exec} assume anche una serie di altre proprietà del processo chiamante; la lista completa è la seguente: \begin{itemize*} -\item il \textit{process ID} (\acr{pid}) ed il \textit{parent process ID} +\item il \textit{process id} (\acr{pid}) ed il \textit{parent process id} (\acr{ppid}). -\item il \textit{real user ID} ed il \textit{real group ID} (vedi +\item il \textit{real user id} ed il \textit{real group id} (vedi \secref{sec:proc_user_group}). -\item i \textit{supplementary group ID} (vedi \secref{sec:proc_user_group}). -\item il \textit{session ID} ed il \textit{process group ID} (vedi +\item i \textit{supplementary group id} (vedi \secref{sec:proc_user_group}). +\item il \textit{session id} ed il \textit{process group id} (vedi \secref{sec:sess_xxx}). \item il terminale di controllo (vedi \secref{sec:sess_xxx}). \item il tempo restante ad un allarme (vedi \secref{sec:sig_xxx}). @@ -1218,12 +1221,12 @@ attraverso una \func{exec}, in genere questo settaggio del flag di \textit{close-on-exec} sulle directory che apre, in maniera trasparente all'utente. -Abbiamo detto che il \textit{real user ID} ed il \textit{real group ID} +Abbiamo detto che il \textit{real user id} ed il \textit{real group id} restano gli stessi all'esecuzione di \func{exec}; lo stesso vale per -l'\textit{effective user ID} ed l'\textit{effective group ID}, tranne il caso +l'\textit{effective user id} ed l'\textit{effective group id}, tranne il caso in cui il file che si va ad eseguire ha o il \acr{suid} bit o lo \acr{sgid} -bit settato, nel qual caso \textit{effective user ID} e \textit{effective - group ID} vengono settati rispettivamente all'utente o al gruppo cui il file +bit settato, nel qual caso \textit{effective user id} e \textit{effective + group id} vengono settati rispettivamente all'utente o al gruppo cui il file appartiene (per i dettagli vedi \secref{sec:proc_perms}). Se il file da eseguire è in formato \emph{a.out} e necessita di librerie @@ -1329,8 +1332,8 @@ identificatori, chiamati rispettivamente \textit{real} ed \textit{effective}. \label{tab:proc_uid_gid} \end{table} -Al primo gruppo appartengono il \textit{real user ID} e il \textit{real group - ID}: questi vengono settati al login ai valori corrispondenti all'utente con +Al primo gruppo appartengono il \textit{real user id} e il \textit{real group + id}: questi vengono settati al login ai valori corrispondenti all'utente con cui si accede al sistema (e relativo gruppo di default). Servono per l'identificazione dell'utente e normalmente non vengono mai cambiati. In realtà vedremo (in \secref{sec:proc_setuid}) che è possibile modificarli, ma @@ -1339,8 +1342,8 @@ possibilit procedura di autenticazione lancia una shell per la quale setta questi identificatori ai valori corrispondenti all'utente che entra nel sistema. -Al secondo gruppo appartengono l'\textit{effective user ID} e -l'\textit{effective group ID} (a cui si aggiungono gli eventuali +Al secondo gruppo appartengono l'\textit{effective user id} e +l'\textit{effective group id} (a cui si aggiungono gli eventuali \textit{supplementary group id} dei gruppi dei quale l'utente fa parte). Questi sono invece gli identificatori usati nella verifiche dei permessi del processo e per il controllo di accesso ai file (argomento affrontato in @@ -1361,16 +1364,16 @@ prototipi sono i seguenti: \begin{functions} \headdecl{unistd.h} \headdecl{sys/types.h} - \funcdecl{uid\_t getuid(void)} Restituisce il \textit{real user ID} del + \funcdecl{uid\_t getuid(void)} Restituisce il \textit{real user id} del processo corrente. - \funcdecl{uid\_t geteuid(void)} Restituisce l'\textit{effective user ID} del + \funcdecl{uid\_t geteuid(void)} Restituisce l'\textit{effective user id} del processo corrente. - \funcdecl{gid\_t getgid(void)} Restituisce il \textit{real group ID} del + \funcdecl{gid\_t getgid(void)} Restituisce il \textit{real group id} del processo corrente. - \funcdecl{gid\_t getegid(void)} Restituisce l'\textit{effective group ID} del + \funcdecl{gid\_t getegid(void)} Restituisce l'\textit{effective group id} del processo corrente. \bodydesc{Queste funzioni non riportano condizioni di errore.} @@ -1528,11 +1531,11 @@ e \textit{real id}. I loro prototipi sono: \headdecl{sys/types.h} \funcdecl{int setreuid(uid\_t ruid, uid\_t euid)} Setta il \textit{real user - ID} e l'\textit{effective user ID} del processo corrente ai valori + id} e l'\textit{effective user id} del processo corrente ai valori specificati da \var{ruid} e \var{euid}. \funcdecl{int setregid(gid\_t rgid, gid\_t egid)} Setta il \textit{real group - ID} e l'\textit{effective group ID} del processo corrente ai valori + id} e l'\textit{effective group id} del processo corrente ai valori specificati da \var{rgid} e \var{egid}. \bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso @@ -1571,6 +1574,34 @@ identificatori ad un valore diverso dal \textit{real id} precedente, il \textit{saved id} viene sempre settato al valore dell'\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) e usate per cambiare gli +\textit{effective id}; i loro prototipi sono: +\begin{functions} +\headdecl{unistd.h} +\headdecl{sys/types.h} + +\funcdecl{int seteuid(uid\_t uid)} Setta l'\textit{effective user id} del +processo corrente a \var{uid}. + +\funcdecl{int setegid(gid\_t gid)} Setta l'\textit{effective group id} del +processo corrente a \var{gid}. + +\bodydesc{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{setresuid} e \func{setresgid}} \label{sec:proc_setresuid} @@ -1582,13 +1613,13 @@ e permettono un completo controllo su tutti gli identificatori (\textit{real}, \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 +\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 +\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}. \bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso @@ -1601,34 +1632,32 @@ identificatori usando uno qualunque dei valori correnti di \textit{real id}, valori che vuole; un valore di -1 per un qualunque parametro lascia inalterato l'identificatore corrispondente. - - -\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) e usate per cambiare gli -\textit{effective id}; i loro prototipi sono: +Per queste funzioni esistono anche due controparti che permettono di leggere +in blocco i vari identificatori: \func{getresuid} e \func{getresgid}; i loro +prototipi sono: \begin{functions} \headdecl{unistd.h} \headdecl{sys/types.h} -\funcdecl{int seteuid(uid\_t uid)} Setta l'\textit{effective user ID} del -processo corrente a \var{uid}. - -\funcdecl{int setegid(gid\_t gid)} Setta l'\textit{effective group ID} del -processo corrente a \var{gid}. +\funcdecl{int getresuid(uid\_t *ruid, uid\_t *euid, uid\_t *suid)} Legge il +\textit{real user id}, l'\textit{effective user id} e il \textit{saved user + id} del processo corrente. + +\funcdecl{int getresgid(gid\_t *rgid, gid\_t *egid, gid\_t *sgid)} Legge il +\textit{real group id}, l'\textit{effective group id} e il \textit{saved group + id} del processo corrente. -\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso - di fallimento: l'unico errore possibile è \macro{EPERM}.} +\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso di + fallimento: l'unico errore possibile è \macro{EFAULT} se gli indirizzi delle + variabili di ritorno non sono validi.} \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. - +Anche queste funzioni sono una estensione specifica di Linux, e non richiedono +nessun privilegio. I valori sono restituiti negli argomenti, che vanno +specificati come puntatori (è un'altro esempio di \textit{value result + argument}). Si noti che queste funzioni sono le uniche in grado di leggere i +\textit{saved id}. + \subsection{Le funzioni \func{setfsuid} e \func{setfsgid}} \label{sec:proc_setfsuid} @@ -1658,10 +1687,10 @@ usate se si intendono scrivere programmi portabili; i loro prototipi sono: \begin{functions} \headdecl{sys/fsuid.h} -\funcdecl{int setfsuid(uid\_t fsuid)} Setta il \textit{filesystem user ID} del +\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 +\funcdecl{int setfsgid(gid\_t fsgid)} Setta l'\textit{filesystem group id} del processo corrente a \var{fsgid}. \bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso @@ -1672,23 +1701,130 @@ 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{setgroups} e \func{getgroups}} +\label{sec:proc_setgroups} + +Le ultime funzioni che esamineremo sono quelle sono quelle che permettono di +operare sui gruppi supplementari. Ogni processo può avere fino a +\macro{NGROUPS\_MAX} gruppi supplementari in aggiunta al gruppo primario, +questi vengono ereditati dal processo padre e possono essere cambiati con +queste funzioni. + +La funzione che permette di leggere i gruppi supplementari è \func{getgroups}; +questa funzione è definita nello standard POSIX ed il suo prototipo è: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{unistd.h} + + \funcdecl{int getgroups(int size, gid\_t list[])} Legge gli identificatori + dei gruppi supplementari del processo sul vettore \param{list} di dimensione + \param{size}. + + \bodydesc{La funzione restituisce il numero di gruppi letti in caso di + successo e -1 in caso di fallimento, nel qual caso \var{errno} viene + settata a: + \begin{errlist} + \item[\macro{EFAULT}] \param{list} non ha un indirizzo valido. + \item[\macro{EINVAL}] il valore di \param{size} è diverso da zero ma + minore del numero di gruppi supplementari del processo. + \end{errlist}} +\end{functions} +\noindent non è specificato se la funzione inserisca o meno nella lista +l'\textit{effective user id} del processo. Se si specifica un valore di +\param{size} uguale a 0 \param{list} non viene modificato, ma si ottiene il +numero di gruppi supplementari. + +Una seconda funzione, \func{getgrouplist}, può invece essere usata per +ottenere tutti i gruppi a cui appartiene un utente; il suo prototipo è: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{grp.h} + + \funcdecl{int getgrouplist(const char *user, gid\_t group, gid\_t *groups, + int *ngroups)} Legge i gruppi supplementari dell'utente \param{user}. + + \bodydesc{La funzione legge fino ad un massimo di \param{ngroups} valori, + restituisce 0 in caso di successo e -1 in caso di fallimento.} +\end{functions} +\noindent la funzione esegue una scansione del database dei gruppi (si veda +\secref{sec:sys_xxx}) e ritorna in \param{groups} la lista di quelli a cui +l'utente appartiene. Si noti che \param{ngroups} è passato come puntatore +perché qualora il valore specificato sia troppo piccolo la funzione ritorna -1 +e passando indietro il numero dei gruppi trovati. + +Per settare i gruppi supplementari di un processo ci sono due funzioni, che +possono essere usate solo se si hanno i privilegi di amministratore. La prima +delle due è \func{setgroups}, ed il suo prototipo è: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{grp.h} + + \funcdecl{int setgroups(size\_t size, gid\_t *list)} Setta i gruppi + supplementari del processo ai valori specificati in \param{list}. + + \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di + fallimento, nel qual caso \var{errno} viene settata a: + \begin{errlist} + \item[\macro{EFAULT}] \param{list} non ha un indirizzo valido. + \item[\macro{EPERM}] il processo non ha i privilegi di amministratore. + \item[\macro{EINVAL}] il valore di \param{size} è maggiore del valore + massimo (\macro{NGROUPS}, che per Linux è 32). + \end{errlist}} +\end{functions} + +Se invece si vogliono settare i gruppi supplementari del processo a quelli di +un utente specifico si può usare \func{initgroups} il cui prototipo è: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{grp.h} + + \funcdecl{int initgroups(const char *user, gid\_t group)} Setta i gruppi + supplementari del processo a quelli di cui è membro l'utente \param{user}, + aggiungendo il gruppo addizionale \param{group}. + + \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di + fallimento, nel qual caso \var{errno} viene settata agli stessi valori di + \func{setgroups} più \macro{ENOMEM} quando non c'è memoria sufficiente per + allocare lo spazio per informazioni dei gruppi.} +\end{functions} + +La funzione esegue la scansione del database dei gruppi (usualmente +\file{/etc/groups}) cercando i gruppi di cui è membro \param{user} costruendo +una lista di gruppi supplementari a cui aggiunge \param{group}, che poi setta +usando \func{setgroups}. + +Si tenga presente che sia \func{setgroups} che \func{initgroups} non sono +definite nello standard POSIX.1 e che pertanto non è possibile utilizzarle +quando si definisce \macro{\_POSIX\_SOURCE} o si compila con il flag +\cmd{-ansi}. + + +\section{La gestione della priorità di esecuzione} +\label{sec:proc_priority} + +In questa sezione tratteremo più approfonditamente i meccanismi con il quale +lo \textit{scheduler} assegna la CPU ai vari processi attivi, illustrando le +varie funzioni che permettono di leggere e modificare le priorità di +esecuzione dei programmi. + + + + + \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 +indipendenti l'uno dall'altro, nella programmazione in un sistema multitasking +occorre tenere conto di 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. +programma alla volta. -Pur non essendo tutto questo direttamente legato alla modalità specifica in -cui il multitasking è implementato in un sistema unix-like, né al solo -concetto di multitasking (le stesse problematiche si presentano ad esempio -nella gestione degli interrupt hardware), in questa sezione conclusiva del -capitolo in cui abbiamo affrontato la gestione dei processi, introdurremo -sinteticamente queste problematiche, che ritroveremo a più riprese in capitoli -successivi, con una breve definizione della terminologia e delle loro -caratteristiche di fondo. +Pur essendo questo argomento di carattere generale, in questa sezione +conclusiva del capitolo in cui abbiamo affrontato la gestione dei processi ci +è parso opportuno introdurre sinteticamente queste problematiche, che +ritroveremo a più riprese in capitoli successivi, dando una breve descrizione +delle loro caratteristiche principali e della terminologia relativa. \subsection{Le operazioni atomiche} @@ -1818,5 +1954,3 @@ varie funzioni di libreria, che sono identificate aggiungendo il suffisso \code{\_r} al nome della versione normale. - - diff --git a/system.tex b/system.tex index d82687e..e8bd370 100644 --- a/system.tex +++ b/system.tex @@ -32,6 +32,41 @@ In questa sezione esamimeremo le funzioni che permettono di gestire le varie risorse associate ad un processo ed i relativi limiti, e quelle relatica al sistema in quanto tale. + +\begin{figure}[!htb] + \footnotesize + \centering + \begin{minipage}[c]{15cm} + \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{} +struct rusage { + struct timeval ru_utime; /* user time used */ + struct timeval ru_stime; /* system time used */ + long ru_maxrss; /* maximum resident set size */ + long ru_ixrss; /* integral shared memory size */ + long ru_idrss; /* integral unshared data size */ + long ru_isrss; /* integral unshared stack size */ + long ru_minflt; /* page reclaims */ + long ru_majflt; /* page faults */ + long ru_nswap; /* swaps */ + long ru_inblock; /* block input operations */ + long ru_oublock; /* block output operations */ + long ru_msgsnd; /* messages sent */ + long ru_msgrcv; /* messages received */ + long ru_nsignals; ; /* signals received */ + long ru_nvcsw; /* voluntary context switches */ + long ru_nivcsw; /* involuntary context switches */ +}; + \end{lstlisting} + \end{minipage} + \normalsize + \caption{La struttura \var{rusage} per la lettura delle informazioni dei + delle risorse usate da un processo.} + \label{fig:sys_rusage_struct} +\end{figure} + + + + \var{tms\_utime}, \var{tms\_stime}, \var{tms\_cutime}, \var{tms\_uetime}