X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=prochand.tex;h=c92f737f780c1f6e1eb6c8070d35d1722e3b77ce;hp=9272a20e0bdb429978f21b24de0d56ca4cbbb6fd;hb=1bc54870307368cc8c74e07f7f4dd53498e09db0;hpb=b38fb9f5c8fb8360f7ac296baa8f4a0bdd692d1c diff --git a/prochand.tex b/prochand.tex index 9272a20..c92f737 100644 --- a/prochand.tex +++ b/prochand.tex @@ -126,13 +126,13 @@ struttura, alla cui base c' processi. Il kernel mantiene una tabella dei processi attivi, la cosiddetta -\textit{process table}; per ciascun processo viene mantenuta una voce, -costituita da una struttura \struct{task\_struct}, nella tabella dei processi -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 \struct{task\_struct} (che in -seguito incontreremo a più riprese), è mostrato in +\itindex{process~table} \textit{process table}; per ciascun processo viene +mantenuta una voce, costituita da una struttura \struct{task\_struct}, nella +tabella dei processi 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 \struct{task\_struct} +(che in seguito incontreremo a più riprese), è mostrato in fig.~\ref{fig:proc_task_struct}. \begin{figure}[htb] @@ -146,16 +146,18 @@ fig.~\ref{fig:proc_task_struct}. Come accennato in sez.~\ref{sec:intro_unix_struct} è lo \textit{scheduler}\itindex{scheduler} che decide quale processo mettere in esecuzione; esso viene eseguito ad ogni system call ed ad ogni -interrupt,\footnote{più in una serie di altre occasioni. NDT completare questa - parte.} (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 -\const{HZ}, definita in \file{asm/param.h}, ed il cui valore è espresso in -Hertz.\footnote{Il valore usuale di questa costante è 100, per tutte le - architetture eccetto l'alpha, per la quale è 1000. Occorre fare attenzione a - non confondere questo valore con quello dei clock tick (vedi +interrupt,\footnote{più in una serie di altre occasioni.} +% TODO completare questa parte. +(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 \const{HZ}, definita +in \file{asm/param.h}, ed il cui valore è espresso in Hertz.\footnote{Fino al + kernel 2.4 l valore usuale di questa costante era 100, per tutte le + architetture eccetto l'alpha, per la quale era 1000. Occorre fare attenzione + a non confondere questo valore con quello dei clock tick (vedi sez.~\ref{sec:sys_unix_time}).} -%Si ha cioè un interrupt dal timer ogni centesimo di secondo. +% TODO verificare gli ultimi cambiamenti del 2.6 +% Si ha cioè un interrupt dal timer ogni centesimo di secondo. Ogni volta che viene eseguito, lo \textit{scheduler}\itindex{scheduler} effettua il calcolo delle priorità dei vari processi attivi (torneremo su @@ -317,22 +319,22 @@ prototipo della funzione Dopo il successo dell'esecuzione di una \func{fork} sia il processo padre che il processo figlio continuano ad essere eseguiti normalmente a partire dall'istruzione successiva alla \func{fork}; il processo figlio è però una -copia del padre, e riceve una copia dei segmenti di testo, stack e dati (vedi -sez.~\ref{sec:proc_mem_layout}), ed esegue esattamente lo stesso codice del -padre. Si tenga presente però che la memoria è copiata, non condivisa, -pertanto padre e figlio vedono variabili diverse. - -Per quanto riguarda la gestione della memoria, in generale il segmento di -testo, che è identico per i due processi, è condiviso e tenuto in read-only -per il padre e per i figli. Per gli altri segmenti Linux utilizza la tecnica -del \textit{copy on write}\itindex{copy~on~write}; questa tecnica -comporta che una pagina di memoria viene effettivamente copiata per il nuovo -processo solo quando ci viene effettuata sopra una scrittura (e si ha quindi -una reale differenza fra padre e figlio). In questo modo si rende molto più -efficiente il meccanismo della creazione di un nuovo processo, non essendo più -necessaria la copia di tutto lo spazio degli indirizzi virtuali del padre, ma -solo delle pagine di memoria che sono state modificate, e solo al momento -della modifica stessa. +copia del padre, e riceve una copia dei segmenti di testo, \itindex{stack} +stack e dati (vedi sez.~\ref{sec:proc_mem_layout}), ed esegue esattamente lo +stesso codice del padre. Si tenga presente però che la memoria è copiata, non +condivisa, pertanto padre e figlio vedono variabili diverse. + +Per quanto riguarda la gestione della memoria, in generale +il\index{segmento!testo} segmento di testo, che è identico per i due processi, +è condiviso e tenuto in read-only per il padre e per i figli. Per gli altri +segmenti Linux utilizza la tecnica del \textit{copy on + write}\itindex{copy~on~write}; questa tecnica comporta che una pagina di +memoria viene effettivamente copiata per il nuovo processo solo quando ci +viene effettuata sopra una scrittura (e si ha quindi una reale differenza fra +padre e figlio). In questo modo si rende molto più efficiente il meccanismo +della creazione di un nuovo processo, non essendo più necessaria la copia di +tutto lo spazio degli indirizzi virtuali del padre, ma solo delle pagine di +memoria che sono state modificate, e solo al momento della modifica stessa. La differenza che si ha nei due processi è che nel processo padre il valore di ritorno della funzione \func{fork} è il \acr{pid} del processo figlio, mentre @@ -898,15 +900,17 @@ secondo lo specchietto riportato in tab.~\ref{tab:proc_waidpid_pid}. \textbf{Valore} & \textbf{Opzione} &\textbf{Significato}\\ \hline \hline - $<-1$& -- & attende per un figlio il cui \textit{process group} (vedi - sez.~\ref{sec:sess_proc_group}) è uguale al - valore assoluto di \param{pid}. \\ - $-1$ & \const{WAIT\_ANY} & attende per un figlio qualsiasi, usata in - questa maniera è equivalente a \func{wait}.\\ - $0$ & \const{WAIT\_MYPGRP} & attende per un figlio il cui \textit{process - group} è uguale a quello del processo chiamante. \\ - $>0$ & -- &attende per un figlio il cui \acr{pid} è uguale al - valore di \param{pid}.\\ + $<-1$& -- & attende per un figlio il cui + \itindex{process~group} \textit{process group} + (vedi sez.~\ref{sec:sess_proc_group}) è uguale + al valore assoluto di \param{pid}. \\ + $-1$& \const{WAIT\_ANY} & attende per un figlio qualsiasi, usata in + questa maniera è equivalente a \func{wait}.\\ + $0$ &\const{WAIT\_MYPGRP}&attende per un figlio il cui + \itindex{process~group} \textit{process group} è + uguale a quello del processo chiamante. \\ + $>0$& -- & attende per un figlio il cui \acr{pid} è uguale + al valore di \param{pid}.\\ \hline \end{tabular} \caption{Significato dei valori dell'argomento \param{pid} della funzione @@ -974,9 +978,10 @@ generato dalla terminazione di un figlio, avremo la certezza che la chiamata a valutata solo se \val{WIFSIGNALED} ha restituito un valore non nullo.\\ \macro{WCOREDUMP(s)} & Vera se il processo terminato ha generato un - file di \textit{core dump}. Può essere valutata - solo se \val{WIFSIGNALED} ha restituito un valore - non nullo.\footnotemark \\ + file di \itindex{core~dump}\textit{core + dump}. Può essere valutata solo se + \val{WIFSIGNALED} ha restituito un valore non + nullo.\footnotemark \\ \macro{WIFSTOPPED(s)} & Vera se il processo che ha causato il ritorno di \func{waitpid} è bloccato. L'uso è possibile solo avendo specificato l'opzione \const{WUNTRACED}. \\ @@ -995,15 +1000,16 @@ generato dalla terminazione di un figlio, avremo la certezza che la chiamata a presente come estensione sia in Linux che in altri Unix.} Entrambe le funzioni di attesa restituiscono lo stato di terminazione del -processo tramite il puntatore \param{status} (se non interessa memorizzare lo -stato si può passare un puntatore nullo). Il valore restituito da entrambe le -funzioni dipende dall'implementazione, e tradizionalmente alcuni bit (in -genere 8) sono riservati per memorizzare lo stato di uscita, e altri per -indicare il segnale che ha causato la terminazione (in caso di conclusione -anomala), uno per indicare se è stato generato un core file, ecc.\footnote{le - definizioni esatte si possono trovare in \file{} ma - questo file non deve mai essere usato direttamente, esso viene incluso - attraverso \file{}.} +processo tramite il puntatore \param{status} (se non interessa memorizzare +lo stato si può passare un puntatore nullo). Il valore restituito da +entrambe le funzioni dipende dall'implementazione, e tradizionalmente alcuni +bit (in genere 8) sono riservati per memorizzare lo stato di uscita, e altri +per indicare il segnale che ha causato la terminazione (in caso di +conclusione anomala), uno per indicare se è stato generato un +\itindex{core~dump}\textit{core dump}, ecc.\footnote{le definizioni esatte + si possono trovare in \file{} ma questo file non deve + mai essere usato direttamente, esso viene incluso attraverso + \file{}.} Lo standard POSIX.1 definisce una serie di macro di preprocessore da usare per analizzare lo stato di uscita. Esse sono definite sempre in @@ -1056,9 +1062,9 @@ processi in Unix fatto attraverso una delle funzioni della famiglia \func{exec}. Quando un processo chiama una di queste funzioni esso viene completamente sostituito dal nuovo programma; il \acr{pid} del processo non cambia, dato che non viene -creato un nuovo processo, la funzione semplicemente rimpiazza lo stack, lo -heap, i dati ed il testo del processo corrente con un nuovo programma letto da -disco. +creato un nuovo processo, la funzione semplicemente rimpiazza lo +\itindex{stack} stack, lo \itindex{heap} heap, i dati ed il testo del processo +corrente con un nuovo programma letto da disco. 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à @@ -1073,9 +1079,9 @@ famiglia di funzioni) che possono essere usate per questo compito, in realt \begin{errlist} \item[\errcode{EACCES}] il file non è eseguibile, oppure il filesystem è montato in \cmd{noexec}, oppure non è un file regolare o un interprete. - \item[\errcode{EPERM}] il file ha i bit \acr{suid} o \acr{sgid}, l'utente - non è root, il processo viene tracciato, o il filesystem è montato con - l'opzione \cmd{nosuid}. + \item[\errcode{EPERM}] il file ha i bit \itindex{suid~bit} \acr{suid} o + \itindex{sgid~bit} \acr{sgid}, l'utente non è root, il processo viene + tracciato, o il filesystem è montato con l'opzione \cmd{nosuid}. \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 @@ -1211,8 +1217,8 @@ la lista completa (\acr{ppid}); \item l'\textsl{user-ID reale}, il \textit{group-ID reale} ed i \textsl{group-ID supplementari} (vedi sez.~\ref{sec:proc_access_id}); -\item il \textit{session id} (\acr{sid}) ed il \textit{process group-ID} - (\acr{pgid}), vedi sez.~\ref{sec:sess_proc_group}; +\item il \textit{session ID} (\acr{sid}) ed il \itindex{process~group} + \textit{process group ID} (\acr{pgid}), vedi sez.~\ref{sec:sess_proc_group}; \item il terminale di controllo (vedi sez.~\ref{sec:sess_ctrl_term}); \item il tempo restante ad un allarme (vedi sez.~\ref{sec:sig_alarm_abort}); \item la directory radice e la directory di lavoro corrente (vedi @@ -1252,10 +1258,11 @@ Abbiamo detto che l'\textsl{user-ID reale} ed il \textsl{group-ID reale} restano gli stessi all'esecuzione di \func{exec}; lo stesso vale per l'\textsl{user-ID effettivo} ed il \textsl{group-ID effettivo} (il significato di questi identificatori è trattato in sez.~\ref{sec:proc_access_id}), tranne -quando il file che si va ad eseguire abbia o il \acr{suid} bit o lo \acr{sgid} -bit impostato, in questo caso l'\textsl{user-ID effettivo} ed il -\textsl{group-ID effettivo} vengono impostati rispettivamente all'utente o al -gruppo cui il file appartiene (per i dettagli vedi sez.~\ref{sec:proc_perms}). +quando il file che si va ad eseguire abbia o il \itindex{suid~bit}\acr{suid} +bit o lo \itindex{sgid~bit} \acr{sgid} bit impostato, in questo caso +l'\textsl{user-ID effettivo} ed il \textsl{group-ID effettivo} vengono +impostati rispettivamente all'utente o al gruppo cui il file appartiene (per i +dettagli vedi sez.~\ref{sec:proc_perms}). Se il file da eseguire è in formato \emph{a.out} e necessita di librerie condivise, viene lanciato il \textit{linker} dinamico \cmd{/lib/ld.so} prima @@ -1305,8 +1312,10 @@ problematiche connesse ad una gestione accorta dei privilegi. Come accennato in sez.~\ref{sec:intro_multiuser} il modello base\footnote{in realtà già esistono estensioni di questo modello base, che lo rendono più - flessibile e controllabile, come le \textit{capabilities}, le ACL per i file - o il \textit{Mandatory Access Control} di SELinux; inoltre basandosi sul + flessibile e controllabile, come le \itindex{capabilities} + \textit{capabilities} illustrate in sez.~\ref{sec:proc_capabilities}, le ACL + per i file o il \textit{Mandatory Access Control} + \itindex{Mandatory~Access~Control~(MAC)} di SELinux; inoltre basandosi sul lavoro effettuato con SELinux, a partire dal kernel 2.5.x, è iniziato lo sviluppo di una infrastruttura di sicurezza, il \textit{Linux Security Modules}, o LSM, in grado di fornire diversi agganci a livello del kernel @@ -1316,10 +1325,6 @@ separazione fra l'amministratore (\textsl{root}, detto spesso anche \textit{superuser}) che non è sottoposto a restrizioni, ed il resto degli utenti, per i quali invece vengono effettuati i vari controlli di accesso. -%Benché il sistema sia piuttosto semplice (è basato su un solo livello di -% separazione) il sistema permette una -%notevole flessibilità, - Abbiamo già accennato come il sistema associ ad ogni utente e gruppo due identificatori univoci, lo user-ID ed il group-ID; questi servono al kernel per identificare uno specifico utente o un gruppo di utenti, per poi poter @@ -1403,12 +1408,13 @@ sez.~\ref{sec:file_perm_overview}). Questi identificatori normalmente sono identici ai corrispondenti del gruppo \textit{real} tranne nel caso in cui, come accennato in -sez.~\ref{sec:proc_exec}, il programma che si è posto in esecuzione abbia i bit -\acr{suid} o \acr{sgid} impostati (il significato di questi bit è affrontato -in dettaglio in sez.~\ref{sec:file_suid_sgid}). In questo caso essi saranno -impostati all'utente e al gruppo proprietari del file. Questo consente, per -programmi in cui ci sia necessità, di dare a qualunque utente normale -privilegi o permessi di un altro (o dell'amministratore). +sez.~\ref{sec:proc_exec}, il programma che si è posto in esecuzione abbia i +bit \itindex{suid~bit} \acr{suid} o \itindex{sgid~bit} \acr{sgid} impostati +(il significato di questi bit è affrontato in dettaglio in +sez.~\ref{sec:file_suid_sgid}). In questo caso essi saranno impostati +all'utente e al gruppo proprietari del file. Questo consente, per programmi in +cui ci sia necessità, di dare a qualunque utente normale privilegi o permessi +di un altro (o dell'amministratore). Come nel caso del \acr{pid} e del \acr{ppid}, anche tutti questi identificatori possono essere letti attraverso le rispettive funzioni: @@ -1452,9 +1458,10 @@ L'\textsl{user-ID salvato} ed il \textsl{group-ID salvato} sono copie dell'\textsl{user-ID effettivo} e del \textsl{group-ID effettivo} del processo padre, e vengono impostati dalla funzione \func{exec} all'avvio del processo, come copie dell'\textsl{user-ID effettivo} e del \textsl{group-ID effettivo} -dopo che questi sono stati impostati tenendo conto di eventuali \acr{suid} o -\acr{sgid}. Essi quindi consentono di tenere traccia di quale fossero utente -e gruppo effettivi all'inizio dell'esecuzione di un nuovo programma. +dopo che questi sono stati impostati tenendo conto di eventuali +\itindex{suid~bit}\acr{suid} o \itindex{sgid~bit} \acr{sgid}. Essi quindi +consentono di tenere traccia di quale fossero utente e gruppo effettivi +all'inizio dell'esecuzione di un nuovo programma. L'\textsl{user-ID di filesystem} e il \textsl{group-ID di filesystem} sono un'estensione introdotta in Linux per rendere più sicuro l'uso di NFS @@ -1505,10 +1512,11 @@ all'\textsl{user-ID salvato}. Negli altri casi viene segnalato un errore (con \errcode{EPERM}). 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 -sez.~\ref{sec:file_suid_sgid}) di riportare l'\textsl{user-ID effettivo} a -quello dell'utente che ha lanciato il programma, effettuare il lavoro che non -necessita di privilegi aggiuntivi, ed eventualmente tornare indietro. +consentire ad un programma con i bit \itindex{suid~bit} \acr{suid} o +\itindex{sgid~bit} \acr{sgid} impostati (vedi sez.~\ref{sec:file_suid_sgid}) +di riportare l'\textsl{user-ID effettivo} a quello dell'utente che ha lanciato +il programma, effettuare il lavoro che non necessita di privilegi aggiuntivi, +ed eventualmente tornare indietro. Come esempio per chiarire l'uso di queste funzioni prendiamo quello con cui viene gestito l'accesso al file \file{/var/log/utmp}. In questo file viene @@ -1856,8 +1864,555 @@ compila con il flag \cmd{-ansi}, scrivere codice portabile. -%\subsection{La gestione delle capabilities} -%\label{sec:proc_capabilities} +\subsection{La gestione delle \textit{capabilities}} +\label{sec:proc_capabilities} + +\itindbeg{capabilities} + +Come accennato in sez.~\ref{sec:proc_access_id} l'architettura classica della +gestione dei privilegi in un sistema unix-like ha il sostanziale problema di +fornire all'amministratore dei poteri troppo ampi, questo comporta che anche +quando si siano predisposte delle misure di protezione per in essere in grado +di difendersi dagli effetti di una eventuale compromissione del +sistema,\footnote{come montare un filesystem in sola lettura per impedirne + modifiche, o marcare un file come immutabile.} una volta che questa sia +stata effettuata e si siano ottenuti i privilegi di amministratore, queste +potranno essere comunque rimosse.\footnote{nei casi elencati nella precedente + nota si potrà sempre rimontare il sistema in lettura-scrittura, o togliere + la marcatura di immutabilità.} + +Il problema consiste nel fatto che nell'architettura tradizionale di un +sistema unix-like i controlli di accesso sono basati su un solo livello di +separazione: per i processi normali essi sono posti in atto, mentre per i +processi con i privilegi di amministratore essi non vengono neppure eseguiti; +per questo motivo non era previsto alcun modo per evitare che un processo con +diritti di amministratore non potesse eseguire certe operazioni, o per cedere +definitivamente alcuni privilegi da un certo momento in poi. + +Per ovviare a tutto ciò, a partire dai kernel della serie 2.2, è stato +introdotto un meccanismo, detto \textit{capabilities}, che consentisse di +suddividere i vari privilegi tradizionalmente associati all'amministratore in +un insieme di \textsl{capacità} distinte. L'idea era che queste capacità +potessero essere abilitate e disabilitate in maniera indipendente per ciascun +processo con privilegi di amministratore, permettendo così una granularità +molto più fine nella distribuzione degli stessi che evitasse la originaria +situazione di \textsl{tutto o nulla}. + +Il meccanismo completo delle \textit{capabilities}\footnote{l'implementazione + di Linux si rifà ad una bozza per quello che dovrebbe divenire lo standard + POSIX.1e, che prevede questa funzionalità.} prevederebbe anche la +possibilità di associare le stesse \textit{capabilities} anche ai singoli file +eseguibili,\footnote{una descrizione sommaria di questa funzionalità è + riportata nella pagina di manuale che descrive l'implementazione delle + \textit{capabilities} con Linux (accessibile con \texttt{man capabilities}), + ma non essendo implementata non ne tratteremo qui.} in modo da poter +stabilire quali capacità possono essere utilizzate quando viene messo in +esecuzione uno specifico programma; attualmente però questa funzionalità non è +implementata.\footnote{per attualmente si intende fino al kernel 2.6.13, e + finora non è disponibile al momento neanche presente nessuna realizzazione + sperimentale delle specifiche POSIX.1e, anche se esistono dei patch di + sicurezza del kernel, come LIDS (vedi + \href{http://www.lids.org}{\texttt{http://www.lids.org/})} che realizzano + qualcosa di simile.} + + +\begin{table}[!h!bt] + \centering + \footnotesize + \begin{tabular}{|l|p{12cm}|} + \hline + \textbf{Capacità}&\textbf{Descrizione}\\ + \hline + \hline + \const{CAP\_CHOWN} & la capacità di cambiare proprietario e gruppo + proprietario di un file (vedi + sez.~\ref{sec:file_chown}).\\ + \const{CAP\_DAC\_OVERRIDE}& la capacità di evitare il controllo dei + permessi di lettura, scrittura ed esecuzione dei + file, (vedi sez.~\ref{sec:file_access_control}) + caratteristici del modello classico del + controllo di accesso chiamato + \itindex{Discrectionary~Access~Control~(DAC)} + \textit{Discrectionary Access Control} (da cui + il nome DAC).\\ + \const{CAP\_DAC\_READ\_SEARCH}& la capacità di evitare il controllo dei + permessi di lettura, scrittura ed esecuzione per + le directory (vedi + sez.~\ref{sec:file_access_control}).\\ + \const{CAP\_FOWNER} & la capacità di evitare il controllo che + l'user-ID effettivo del processo (o meglio il + \textit{filesystem user-ID}, vedi + sez.~\ref{sec:proc_setuid}) coincida con + quello del proprietario di un file per tutte + le operazioni privilegiate non coperte dalle + precedenti \const{CAP\_DAC\_OVERRIDE} e + \const{CAP\_DAC\_READ\_SEARCH}. Queste + comprendono i cambiamenti dei permessi e dei + tempi del file (vedi sez.~\ref{sec:file_chmod} e + sez.~\ref{sec:file_utime}), le impostazioni degli + attributi estesi (con il comando \cmd{chattr}) e + delle ACL, poter ignorare lo + \itindex{sticky~bit} \textit{sticky bit} nella + cancellazione dei file (vedi + sez.~\ref{sec:file_sticky}), la possibilità di + impostare il flag di \const{O\_NOATIME} con + \func{open} e \func{fcntl} (vedi + sez.~\ref{sec:file_open} e + sez.~\ref{sec:file_fcntl}).\\ + \const{CAP\_FSETID} & la capacità di evitare la cancellazione + automatica dei bit \itindex{suid~bit} \acr{suid} + e \itindex{sgid~bit} \acr{sgid} quando un file + per i quali sono impostati viene modificato da + un processo senza questa capacità e la capacità + di impostare il bit \acr{sgid} su un file anche + quando questo è relativo ad un gruppo cui non si + appartiene (vedi sez.~\ref{sec:file_chmod}).\\ + \const{CAP\_IPC\_LOCK} & la capacità di effettuare il \textit{memory + locking} \itindex{memory~locking} con le + funzioni \func{mlock}, \func{mlockall}, + \func{shmctl}, \func{mmap} (vedi + sez.~\ref{sec:proc_mem_lock} e + sez.~\ref{sec:file_memory_map}). \\ + \const{CAP\_IPC\_OWNER} & la capacità di evitare il controllo dei permessi + per le operazioni sugli oggetti di + intercomunicazione fra processi (vedi + sez.~\ref{sec:ipc_sysv}).\\ + \const{CAP\_KILL} & la capacità di mandare segnali a qualunque + processo (vedi sez.~\ref{sec:sig_kill_raise}).\\ + \const{CAP\_LEASE} & la capacità di creare dei \textit{file lease} + \index{file!lease} su di un file (vedi + sez.~\ref{sec:file_asyncronous_lease}) + indipendentemente dalla proprietà dello + stesso.\footnotemark\\ + \const{CAP\_LINUX\_IMMUTABLE}& la capacità di impostare gli attributi + \textit{immutable} e \textit{append only} per i + file su un filesystem che supporta questi + attributi estesi.\\ + \const{CAP\_MKNOD} & la capacità di creare file di dispositivo con la + funzione \func{mknod} (vedi + sez.~\ref{sec:file_mknod}).\footnotemark\\ + \const{CAP\_NET\_ADMIN} & la capacità di eseguire alcune operazioni + privilegiate sulla rete (impostare le opzioni + privilegiate dei socket, abilitare il + multicasting, impostare interfacce di rete e + tabella di instradamento).\\ + \const{CAP\_NET\_BIND\_SERVICE}& la capacità di porre in ascolto server + su porte riservate (vedi + sez.~\ref{sec:TCP_func_bind}).\\ + \const{CAP\_NET\_BROADCAST}& la capacità di consentire l'uso di socket in + broadcast e multicast.\\ + \const{CAP\_NET\_RAW} & la capacità di usare socket \texttt{RAW} e + \texttt{PACKET} (quelli che permettono di creare + pacchetti nei protocolli di basso livello).\\ + \const{CAP\_SETGID} & la capacità di manipolare i group ID dei + processi, sia il principale che i supplementari, + (vedi sez.~\ref{sec:proc_setgroups} che quelli + trasmessi tramite i \index{socket} socket + \textit{unix domain} (vedi + sez.~\ref{sec:unix_socket}).\\ + \const{CAP\_SETPCAP} & la capacità di impostare o rimuovere una capacità + (limitatamente a quelle che il processo + chiamante ha nel suo insieme di capacità + permesse) da qualunque processo.\\ + \const{CAP\_SETUID} & la capacità di manipolare gli user ID del + processo (con \func{setuid}, \func{setreuid}, + \func{setresuid}, \func{setfsuid}) e di + trasmettere un valore arbitrario + dell'\textsl{uid} nel passaggio delle + credenziali coi socket unix domain (vedi + sez.~\ref{sec:unix_socket_xxx}).\\ + \const{CAP\_SYS\_ADMIN} & la capacità di eseguire una serie di compiti + amministrativi (come impostare le quote, + attivare e disattivare la swap, montare, + rimontare e smontare filesystem, ecc.). \\ + \const{CAP\_SYS\_BOOT} & la capacità di fare eseguire un reboot del + sistema.\\ + \const{CAP\_SYS\_CHROOT}& la capacità di eseguire la funzione + \func{chroot} (vedi + sez.~\ref{sec:file_chroot}).\\ + \const{CAP\_SYS\_MODULE}& la capacità di caricare e rimuovere moduli del + kernel. \\ + \const{CAP\_SYS\_NICE} & la capacità di modificare le priorità dei + processi (vedi sez.~\ref{sec:proc_priority}). \\ + \const{CAP\_SYS\_PACCT} & la capacità di usare le funzioni di + \textit{accounting} dei processi (vedi + sez.~\ref{sec:sys_bsd_accounting}).\\ + \const{CAP\_SYS\_RAWIO} & la capacità di eseguire operazioni sulle porte + di I/O con \func{ioperm} e \func{iopl} (vedi + sez.~\ref{sec:file_io_port}).\\ + \const{CAP\_SYS\_RESOURCE}& la capacità di superare le limitazioni sulle + risorse, aumentare le quote disco, usare lo + spazio disco riservato all'amministratore.\\ + \const{CAP\_SYS\_TIME} & la capacità di modificare il tempo di sistema + (vedi sez.~\ref{sec:sys_time}).\\ + \const{CAP\_SYS\_TTY\_CONFIG}& la capacità di simulare un \textit{hangup} + della console, con la funzione + \func{vhangup}.\\ + \const{CAP\_SYS\_PTRACE}& consente di tracciare qualunque processo con + \func{ptrace} (vedi + sez.~\ref{sec:xxx_ptrace}).\\ +% TODO documentatare ptrace + \hline + \end{tabular} + \caption{Le costanti che identificano le \textit{capabilities} presenti nel + kernel.} +\label{tab:proc_capabilities} +\end{table} + +\footnotetext[21]{questa capacità è presente soltato a partire dai kernel + della serie 2.4.x.} + +\footnotetext{questa capacità è presente soltato a partire dai kernel della + serie 2.4.x.} + +Per gestire questo nuovo meccanismo ciascun processo porta con sé tre distinti +insiemi di \textit{capabilities}, che vengono denominati rispettivamente +\textit{effective}, \textit{permitted} ed \textit{inherited}. Questi insiemi +vengono mantenuti in forma di tre diverse maschere binarie,\footnote{il kernel + li mantiene, come i vari identificatori di sez.~\ref{sec:proc_setuid}, + all'interno della \struct{task\_struct} di ciascun processo (vedi + fig.~\ref{fig:proc_task_struct}), nei tre campi \texttt{cap\_effective}, + \texttt{cap\_inheritable}, \texttt{cap\_permitted} del tipo + \texttt{kernel\_cap\_t}; questo è attualmente definito come intero a 32 bit, + il che comporta un massimo di 32 \textit{capabilities} distinte.} in cui +ciascun bit corrisponde ad una capacità diversa; se ne è riportato +l'elenco,\footnote{si tenga presente che l'elenco delle \textit{capabilities} + presentato questa tabella, ripreso dalla relativa pagina di manuale + (accessibile con \texttt{man capabilities}), è quello aggiornato al kernel + 2.6.6.} con una breve descrizione, ed il nome delle costanti che +identificano i singoli bit, in tab.~\ref{tab:proc_capabilities}. + +L'utilizzo di tre distinti insiemi serve a fornire una interfaccia flessibile +per l'uso delle \textit{capabilities}, con scopi analoghi a quelli per cui +sono mantenuti i diversi insiemi di identificatori di +sez.~\ref{sec:proc_setuid}; il loro significato è il seguente: +\begin{basedescript}{\desclabelwidth{2.0cm}\desclabelstyle{\nextlinelabel}} +\item[\textit{effective}] l'insieme delle \textit{capabilities} + ``\textsl{effettive}'', cioè di quelle che vengono effettivamente usate dal + kernel quando deve eseguire il controllo di accesso per le varie operazioni + compiute dal processo. +\item[\textit{permitted}] l'insieme delle \textit{capabilities} + ``\textsl{permesse}'', cioè l'insieme di quelle capacità che un processo + \textsl{può} impostare come \textsl{effettive}. Se un processo cancella una + capacità da questo insieme non potrà più riassumerla (almeno che non esegua + un programma che è \acr{suid} di root). +\item[\textit{inherited}] l'insieme delle \textit{capabilities} + ``\textsl{ereditabili}'', cioè quelle che vengono trasmesse ad un nuovo + programma eseguito attraverso una chiamata ad \func{exec} (con l'eccezione + del caso che questo sia \acr{suid} di root). +\label{sec:capabilities_set} +\end{basedescript} + +Oltre a questi tre insiemi, che sono relativi al singolo processo, il kernel +mantiene un insieme generale valido per tutto il sistema, chiamato +\itindex{capabilities~bounding~set} \textit{capabilities bounding set}. Ogni +volta che un programma viene posto in esecuzione con \func{exec} il contenuto +degli insiemi \textit{effective} e \textit{permitted} vengono mascherati con +un \textsl{AND} binario del contenuto corrente del \textit{capabilities + bounding set}, così che il nuovo processo potrà disporre soltanto delle +capacità in esso elencate. + +Il \textit{capabilities bounding set} è un parametro di sistema, accessibile +attraverso il contenuto del file \file{/proc/sys/kernel/cap-bound}, che per +questa sua caratteristica consente di impostare un limite generale alle +capacità che possono essere accordate ai vari processi. Questo valore può +essere impostato ad un valore arbitrario esclusivamente dal primo processo +eseguito nel sistema (di norma cioè da \texttt{/sbin/init}), ogni processo +eseguito successivamente (cioè con \textsl{pid} diverso da 1) anche se +eseguito con privilegi di amministratore potrà soltanto rimuovere uno dei bit +già presenti dell'insieme: questo significa che una volta rimossa una +\textit{capability} dal \textit{capabilities bounding set} essa non sarà più +disponibile, neanche per l'amministratore, a meno di un riavvio. + +Quando un programma viene messo in esecuzione\footnote{cioè quando viene + eseguita la \func{execve} con cui lo si lancia; in corrispondenza di una + \func{fork} le \textit{capabilities} non vengono modificate.} esso eredita +(nel senso che assume negli insiemi \textit{effective} e \textit{permitted}) +le \textit{capabilities} mantenute nell'insieme \textit{inherited}, a meno che +non sia eseguito un programma \acr{suid} di root o la \func{exec} sia stata +eseguita da un programma con \textsl{uid} reale zero; in tal caso il programma +ottiene tutte le \textit{capabilities} presenti nel \textit{capabilities + bounding set}. In questo modo si può far si che ad un processo eseguito in +un secondo tempo possano essere trasmesse solo un insieme limitato di +capacità, impedendogli di recuperare quelle assenti nell'insieme +\textit{inherited}. Si tenga presente invece che attraverso una \func{fork} +vengono mantenute le stesse capacità del processo padre. + +Per la gestione delle \textit{capabilities} il kernel mette a disposizione due +funzioni che permettono rispettivamente di leggere ed impostare i valori dei +tre insiemi illustrati in precedenza. Queste due funzioni sono \funcd{capget} +e \funcd{capset} e costituiscono l'interfaccia di gestione basso livello; i +loro rispettivi prototipi sono: +\begin{functions} + \headdecl{sys/capability.h} + + \funcdecl{int capget(cap\_user\_header\_t hdrp, cap\_user\_data\_t datap)} + Legge le \textit{capabilities}. + + \funcdecl{int capset(cap\_user\_header\_t hdrp, const cap\_user\_data\_t + datap)} + Imposta le \textit{capabilities}. + + + \bodydesc{Entrambe le funzioni ritornano 0 in caso di successo e -1 in caso + di errore, nel qual caso \var{errno} può assumere i valori: + \begin{errlist} + \item[\errcode{ESRCH}] si è fatto riferimento ad un processo inesistente. + \item[\errcode{EPERM}] si è tentato di aggiungere una capacità + nell'insieme delle \textit{capabilities} permesse, o di impostare una + capacità non presente nell'insieme di quelle permesse negli insieme + delle effettive o ereditate, o si è cercato di impostare una + \textit{capability} di un altro processo senza avare + \const{CAP\_SETPCAP}. + \end{errlist} + ed inoltre \errval{EFAULT} ed \errval{EINVAL}. +} + +\end{functions} + +Queste due funzioni prendono come argomenti due tipi di dati dedicati, +definiti come puntatori a due strutture specifiche di Linux, illustrate in +fig.~\ref{fig:cap_kernel_struct}. Per poterle utilizzare occorre anche +cancellare la macro \macro{\_POSIX\_SOURCE}.\footnote{per farlo occorre + utilizzare la direttiva di preprocessore \direct{undef}; si dovrà cioè + inserire una istruzione \texttt{\#undef \_POSIX\_SOURCE} prima di includere + \texttt{sys/capability.h}.} Si tenga presente che le strutture di +fig.~\ref{fig:cap_kernel_struct}, come i prototipi delle due funzioni +\func{capget} e \func{capset}, sono soggette ad essere modificate con il +cambiamento del kernel (in particolare i tipi di dati delle strutture) ed +anche se finora l'interfaccia è risultata stabile, non c'è nessuna +assicurazione che questa venga mantenuta. Pertando se si vogliono scrivere +programmi portabili che possano essere eseguiti su qualunque versione del +kernel è opportuno utilizzare le interfacce di alto livello. + +\begin{figure}[!htb] + \footnotesize + \centering + \begin{minipage}[c]{15cm} + \includestruct{listati/cap_user_header_t.h} + \end{minipage} + \normalsize + \caption{Definizione delle strutture a cui fanno riferimento i puntatori + \structd{cap\_user\_header\_t} e \structd{cap\_user\_data\_t} usati per + l'interfaccia di gestione di basso livello delle \textit{capabilities}.} + \label{fig:cap_kernel_struct} +\end{figure} + +La struttura a cui deve puntare l'argomento \param{hdrp} serve ad indicare, +tramite il campo \var{pid}, il processo del quale si vogliono leggere o +modificare le \textit{capabilities}. Il campo \var{version} deve essere +impostato al valore della versione delle usata dal kernel (quello indicato +dalla costante \const{\_LINUX\_CAPABILITY\_VERSION} di +fig.~\ref{fig:cap_kernel_struct}) altrimenti le funzioni ritorneranno con un +errore di \errcode{EINVAL}, restituendo nel campo stesso il valore corretto +della versione in uso. La struttura a cui deve puntare l'argomento +\param{datap} invece conterrà i valori letti o da impostare per i tre insiemi +delle capacità del processo. + +Dato che le precedenti funzioni, oltre ad essere specifiche di Linux, non +garantiscono la stabilità nell'interfaccia, è sempre opportuno effettuare la +gestione delle \textit{capabilities} utilizzando le funzioni di libreria a +questo dedicate. Queste funzioni, che seguono quanto previsto nelle bozze +dello standard POSIX.1e, non fanno parte delle \acr{glibc} e sono fornite in +una libreria a parte,\footnote{la libreria è \texttt{libcap2}, nel caso di + Debian può essere installata con il pacchetto omonimo.} pertanto se un +programma le utilizza si dovrà indicare esplicitamente l'uso della suddetta +libreria attraverso l'opzione \texttt{-lcap} del compilatore. + +Le funzioni dell'interfaccia POSIX.1e prevedono l'uso di uno tipo di dato +opaco, \type{cap\_t}, come puntatore ai dati mantenuti nel cosiddetto +\textit{capability state},\footnote{si tratta in sostanza di un puntatore ad + una struttura interna utilizzata dalle librerie, i cui campi non devono mai + essere acceduti direttamente.} in sono memorizzati tutti i dati delle +\textit{capabilities}. In questo modo è possibile mascherare i dettagli della +gestione di basso livello, che potranno essere modificati senza dover cambiare +le funzioni dell'interfaccia, che faranno riferimento soltanto ad oggetti di +questo tipo. L'interfaccia pertanto non soltanto fornirà le funzioni per +modificare e leggere le \textit{capabilities}, ma anche quelle per gestire i +dati attraverso \type{cap\_t}. + +La prima funzione dell'interfaccia è allora quella che permette di +inizializzare un \textit{capability state}, allocando al contempo la memoria +necessaria per i relativi dati. La funzione è \funcd{cap\_init} ed il suo +prototipo è: +\begin{functions} + \headdecl{sys/capability.h} + + \funcdecl{cap\_t cap\_init(void)} + Crea ed inizializza un \textit{capability state}. + + \bodydesc{La funzione ritorna un valore non nullo in caso di successo e + \macro{NULL} in caso di errore, nel qual caso \var{errno} assumerà il + valore \errval{ENOMEM}. +} +\end{functions} + +La funzione restituisce il puntatore \type{cap\_t} ad uno stato inizializzato +con tutte le \textit{capabilities} azzerate. In caso di errore (cioè quando +non c'è memoria suffuciente ad allocare i dati) viene restituito \macro{NULL} +ed \var{errno} viene impostata a \errval{ENOMEM}. La memoria necessaria a +mantenere i dati viene automaticamente allocata da \func{cap\_init}, ma dovrà +essere disallocata esplicitamente quando non più necessaria utilizzando la +funzione \funcd{cap\_free}, il cui prototipo è: +\begin{functions} + \headdecl{sys/capability.h} + + \funcdecl{int cap\_free(void *obj\_d)} + Disalloca la memoria allocata per i dati delle \textit{capabilities}. + + \bodydesc{La funzione ritorna 0 in caso di successo e $-1$ in caso di + errore, nel qual caso \var{errno} assumerà il valore \errval{EINVAL}. +} +\end{functions} + +La funzione permette di liberare la memoria allocata dalle altre funzioni +della libreria sia per un \textit{capability state}, nel qual caso l'argomento +dovrà essere un dato di tipo \type{cap\_t}, che per una descrizione testuale +dello stesso,\footnote{cioè quanto ottenuto tramite la funzione + \func{cap\_to\_text}.} nel qual caso l'argomento dovrà essere di tipo +\texttt{char *}. L'argomento \param{obj\_d} deve corrispondere ad un oggetto +ottenuto tramite altre funzioni della libreria, altrimenti la funzione fallirà +con un errore di \errval{EINVAL}. + +Infine si può creare una copia di un \textit{capability state} ottenuto in +precedenza tramite la funzione \funcd{cap\_dup}, il cui prototipo è: +\begin{functions} + \headdecl{sys/capability.h} + + \funcdecl{cap\_t cap\_dup(cap\_t cap\_p)} + Duplica un \textit{capability state} restituendone una copia. + + \bodydesc{La funzione ritorna un valore non nullo in caso di successo e + \macro{NULL} in caso di errore, nel qual caso \var{errno} potrà assumere i + valori \errval{ENOMEM} o \errval{EINVAL}. +} +\end{functions} + +La funzione crea una copia del \textit{capability state} \param{cap\_p} +passato come argomento, restituendo il puntatore alla copia che conterrà gli +stessi valori delle \textit{capabilities} presenti nell'originale. La memoria +necessaria viene allocata automaticamente dalla funzione. Una volta effettuata +la copia i due \textit{capability state} potranno essere modificati in maniera +completamente indipendente. + +Una seconda classe di funzioni di servizio sono quelle per la gestione dei +dati contenuti all'interno di un \textit{capability state}; la prima di esse è +\funcd{cap\_clear}, il cui prototipo è: +\begin{functions} + \headdecl{sys/capability.h} + + \funcdecl{int cap\_clear(cap\_t cap\_p)} + Inizializza un \textit{capability state} cancellando tutte le + \textit{capabilities}. + + \bodydesc{La funzione ritorna 0 in caso di successo e $-1$ in caso di + errore, nel qual caso \var{errno} assumerà il valore \errval{EINVAL}. +} +\end{functions} + +La funzione si limita ad azzerare tutte le \textit{capabilities} presenti nel +\textit{capability state} \param{cap\_p} passato come argomento restituendo +uno stato \textsl{vuoto}, analogo a quello che si ottiene nella creazione con +\func{cap\_init}. + +Per la gestione dei valori delle \textit{capabilities} presenti in un +\textit{capability state} l'interfaccia prevede due funzioni, +\funcd{cap\_get\_flag} e \funcd{cap\_set\_flag}, che permettono +rispettivamente di leggere o impostare il valore di un flag delle +\textit{capabilities}; i rispettivi prototipi sono: +\begin{functions} + \headdecl{sys/capability.h} + + \funcdecl{int cap\_get\_flag(cap\_t cap\_p, cap\_value\_t cap, cap\_flag\_t + flag, cap\_flag\_value\_t *value\_p)} + Legge il valore di una \textit{capability}. + + \funcdecl{int cap\_set\_flag(cap\_t cap\_p, cap\_flag\_t flag, int ncap, + cap\_value\_t *caps, cap\_flag\_value\_t value)} + Imposta il valore di una \textit{capability}. + + \bodydesc{Le funzioni ritornano 0 in caso di successo e $-1$ in caso di + errore, nel qual caso \var{errno} assumerà il valore \errval{EINVAL}. +} +\end{functions} + +In entrambe le funzioni l'argomento \param{cap\_p} indica il +\textit{capability state} su cui operare, mentre l'argomento \param{flag} +indica su quale dei tre insiemi illustrati a +pag.~\pageref{sec:capabilities_set} si intende operare. Questo deve essere +specificato con una variabile di tipo \type{cap\_flag\_t} e può assumere +esclusivamente\footnote{si tratta in effetti di un tipo enumerato, come si può + verificare dalla sua definizione che si trova in + \texttt{/usr/include/sys/capability.h}.} uno dei valori illustrati in +tab.~\ref{tab:cap_set_identifier}. + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|l|} + \hline + \textbf{Valore} & \textbf{Significato} \\ + \hline + \hline + \const{CAP\_EFFECTIVE} & Capacità dell'insieme \textsl{effettivo}.\\ + \const{CAP\_PERMITTED} & Capacità dell'insieme \textsl{permesso}.\\ + \const{CAP\_INHERITABLE}& Capacità dell'insieme \textsl{ereditabile}.\\ + \hline + \end{tabular} + \caption{Valori possibili per il tipo di dato \type{cap\_flag\_t} che + identifica gli insiemi delle \textit{capabilities}.} + \label{tab:cap_set_identifier} +\end{table} + +La capacità che si intende controllare o impostare deve essere specificata +attraverso una variabile di tipo \type{cap\_value\_t}, che può prendere come +valore uno qualunque di quelli riportati in tab.~\ref{tab:proc_capabilities}, +in questo caso però non è possibile combinare diversi valori in una maschera +binaria, una variabile di tipo \type{cap\_value\_t} deve indicare una sola +\textit{capabilities}.\footnote{nel file di header citato nella nota + precedente il tipo \type{cap\_value\_t} è definito come \ctyp{int}, ma i + valori validi sono soltanto quelli di tab.~\ref{tab:proc_capabilities}.} +Infine lo stato di una \textit{capabilities} è descritto ad una variabile di +tipo \type{cap\_flag\_value\_t}, che a sua volta può assumere soltanto +uno\footnote{anche questo è un tipo enumerato.} dei valori di +tab.~\ref{tab:cap_value_type}. + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|l|} + \hline + \textbf{Valore} & \textbf{Significato} \\ + \hline + \hline + \const{CAP\_CLEAR}& La capacità non è impostata.\\ + \const{CAP\_SET} & La capacità è impostata.\\ + \hline + \end{tabular} + \caption{Valori possibili per il tipo di dato \type{cap\_flag\_value\_t} che + indica lo stato di una capacità.} + \label{tab:cap_value_type} +\end{table} + +La funzione \func{cap\_get\_flag} legge lo stato della capacità indicata +dall'argomento \param{cap} all'interno dell'insieme indicato dall'argomento +\param{flag} e ne restituisce il valore nella variabile posta all'indirizzo +puntato dall'argomento \param{value\_p}; è possibile cioè leggere soltanto uno +stato di una \textit{capability} alla volta. + +La funzione \func{cap\_set\_flag} può invece impostare in una sola chiamata +più capacità, anche se solo all'interno dello stesso insieme; per questo essa +prende un vettore di valori di tipo \type{cap\_value\_t} nell'argomento +\param{caps}, la cui dimensione è specificata dall'argomento \param{ncap}. Il +tipo di impostazione da eseguire (cancellazione o impostazione) viene indicato +dall'argomento \param{value}. + + + + + + +\itindend{capabilities} @@ -1866,10 +2421,10 @@ scrivere codice portabile. \label{sec:proc_priority} In questa sezione tratteremo più approfonditamente i meccanismi con il quale -lo \textit{scheduler}\itindex{scheduler} assegna la CPU ai vari -processi attivi. In particolare prenderemo in esame i vari meccanismi con cui -viene gestita l'assegnazione del tempo di CPU, ed illustreremo le varie -funzioni di gestione. +lo \textit{scheduler}\itindex{scheduler} assegna la CPU ai vari processi +attivi. In particolare prenderemo in esame i vari meccanismi con cui viene +gestita l'assegnazione del tempo di CPU, ed illustreremo le varie funzioni di +gestione. \subsection{I meccanismi di \textit{scheduling}} @@ -2102,9 +2657,10 @@ l'utente correnti. \param{which} & \param{who} & \textbf{Significato} \\ \hline \hline - \const{PRIO\_PROCESS} & \type{pid\_t} & processo \\ - \const{PRIO\_PRGR} & \type{pid\_t} & process group \\ - \const{PRIO\_USER} & \type{uid\_t} & utente \\ + \const{PRIO\_PROCESS} & \type{pid\_t} & processo \\ + \const{PRIO\_PRGR} & \type{pid\_t} & \itindex{process~group} + \textit{process group} \\ + \const{PRIO\_USER} & \type{uid\_t} & utente \\ \hline \end{tabular} \caption{Legenda del valore dell'argomento \param{which} e del tipo @@ -2184,7 +2740,7 @@ eseguito per primo quello con priorit processi con la stessa priorità assoluta questi vengono tenuti in una coda e tocca al kernel decidere quale deve essere eseguito. Il meccanismo con cui vengono gestiti questi processi dipende dalla politica di scheduling che si è -scelto; lo standard ne prevede due: +scelta; lo standard ne prevede due: \begin{basedescript}{\desclabelwidth{1.2cm}\desclabelstyle{\nextlinelabel}} \item[\textit{FIFO}] \textit{First In First Out}. Il processo viene eseguito fintanto che non cede volontariamente la CPU (con \func{sched\_yield}), si @@ -2716,10 +3272,11 @@ multi-thread, ma si hanno gli stessi problemi quando si vogliono chiamare delle funzioni all'interno dei gestori dei segnali. Fintanto che una funzione opera soltanto con le variabili locali è rientrante; -queste infatti vengono allocate nello stack, e un'altra invocazione non fa -altro che allocarne un'altra copia. Una funzione può non essere rientrante -quando opera su memoria che non è nello stack. Ad esempio una funzione non è -mai rientrante se usa una variabile globale o statica. +queste infatti vengono allocate nello \itindex{stack} stack, e un'altra +invocazione non fa altro che allocarne un'altra copia. Una funzione può non +essere rientrante quando opera su memoria che non è nello \itindex{stack} +stack. Ad esempio una funzione non è mai rientrante se usa una variabile +globale o statica. Nel caso invece la funzione operi su un oggetto allocato dinamicamente, la cosa viene a dipendere da come avvengono le operazioni: se l'oggetto è creato