X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=procadv.tex;h=d44570f022db1b78063b008b41eabee32c627d86;hp=4b83f8e3b6c9b194f7b1cbd16e9449fb8c813c5c;hb=0e932d7963332ca87688c3695d7386d45ddcc46a;hpb=9b4e35959dc9df4830ce828e462893d4a776ced9 diff --git a/procadv.tex b/procadv.tex index 4b83f8e..d44570f 100644 --- a/procadv.tex +++ b/procadv.tex @@ -1,21 +1,1500 @@ \chapter{La gestione avanzata dei processi} \label{cha:proc_advanced} -In questo capitolo affronteremo le tematiche relative alla gestione avanzata -dei processi, trattando le \textit{system call} dedicate alle funzionalità più -specifiche ed avanzate, il cui uso è in genere piuttosto ridotto. Inizieremo -con le funzioni che attengono agli aspetti di controllo, passando alle -gestione delle modalità di creazione ed alle funzionalità attinenti i -\textit{namespace} e le funzionalità avanzate relative alla gestione della -sicurezza. Infine affronteremo le funzioni di gestione per una serie di -funzionalità specialistiche come la gestione della virgola mobile, le porte di -I/O ecc. +In questo capitolo affronteremo gli argomenti relativi alla gestione avanzata +dei processi. Inizieremo con le funzioni che attengono alla gestione avanzata +della sicurezza, passando poi a quelle relative all'analisi ed al controllo +dell'esecuzione, e alle funzioni per le modalità avanzate di creazione dei +processi e l'uso dei cosiddetti \textit{namespace}. Infine affronteremo le +\textit{sytem call} attinenti ad una serie di funzionalità specialistiche come +la gestione della virgola mobile, le porte di I/O ecc. + +\section{La gestione avanzata della sicurezza} +\label{sec:process_security} + +Tratteremo in questa sezione le funzionalità più avanzate relative alla +gestione della sicurezza ed il controllo degli accessi all'interno dei +processi, a partire dalle \textit{capabilities} e dalle funzionalità del +cosiddetto \textit{Secure Computing}. Esamineremo inoltre le altre +funzionalità relative alla sicurezza come la gestione delle chiavi +crittografiche e varie estensioni e funzionalità disponibili su questo +argomento. + + +\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, il che 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 (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 misure potranno essere comunque +rimosse (nei casi elencati nella precedente nota si potrà sempre rimontare il +sistema in lettura-scrittura, o togliere l'attributo 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 risolvere questo problema sono possibili varie soluzioni, ad esempio dai +kernel della serie 2.5 è stata introdotta la struttura dei +\itindex{Linux~Security~Modules~(LSM)} \textit{Linux Security Modules} che han +permesso di aggiungere varie forme di \itindex{Mandatory~Access~Control~(DAC)} +\textit{Mandatory Access Control} (MAC), in cui si potessero parcellizzare e +controllare nei minimi dettagli tutti i privilegi e le modalità in cui questi +possono essere usati dai programmi e trasferiti agli utenti, con la creazione +di varie estensioni (come \textit{SELinux}, \textit{Smack}, \textit{Tomoyo}, +\textit{AppArmor}) che consentono di superare l'architettura tradizionale dei +permessi basati sul modello classico del controllo di accesso chiamato +\itindex{Discrectionary~Access~Control~(DAC)} \textit{Discrectionary Access + Control} (DAC). + +Ma già in precedenza, a partire dai kernel della serie 2.2, era stato +introdotto un meccanismo, detto \textit{capabilities}, per consentire 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 situazione +originaria di ``\textsl{tutto o nulla}''. + +\itindbeg{file~capabilities} + +Il meccanismo completo delle \textit{capabilities} (l'implementazione si rifà +ad una bozza di quello che doveva diventare lo standard POSIX.1e, poi +abbandonato) prevede inoltre la possibilità di associare le stesse ai singoli +file eseguibili, in modo da poter stabilire quali capacità possono essere +utilizzate quando viene messo in esecuzione uno specifico programma; ma il +supporto per questa funzionalità, chiamata \textit{file capabilities}, è stato +introdotto soltanto a partire dal kernel 2.6.24. Fino ad allora doveva essere +il programma stesso ad eseguire una riduzione esplicita delle sue capacità, +cosa che ha reso l'uso di questa funzionalità poco diffuso, vista la presenza +di meccanismi alternativi per ottenere limitazioni delle capacità +dell'amministratore a livello di sistema operativo, come \textit{SELinux}. + +Con questo supporto e con le ulteriori modifiche introdotte con il kernel +2.6.25 il meccanismo delle \textit{capabilities} è stato totalmente +rivoluzionato, rendendolo più aderente alle intenzioni originali dello +standard POSIX, rimuovendo il significato che fino ad allora aveva avuto la +capacità \const{CAP\_SETPCAP}, e cambiando le modalità di funzionamento del +cosiddetto \textit{capabilities bounding set}. Ulteriori modifiche sono state +apportate con il kernel 2.6.26 per consentire la rimozione non ripristinabile +dei privilegi di amministratore. Questo fa sì che il significato ed il +comportamento del kernel finisca per dipendere dalla versione dello stesso e +dal fatto che le nuove \textit{file capabilities} siano abilitate o meno. Per +capire meglio la situazione e cosa è cambiato conviene allora spiegare con +maggiori dettagli come funziona il meccanismo delle \textit{capabilities}. + +Il primo passo per frazionare i privilegi garantiti all'amministratore, +supportato fin dalla introduzione iniziale del kernel 2.2, è stato quello in +cui a ciascun processo sono stati associati tre distinti insiemi di +\textit{capabilities}, denominati rispettivamente \textit{permitted}, +\textit{inheritable} ed \textit{effective}. 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 + \texttt{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 era, fino al kernel 2.6.25 definito come + intero a 32 bit per un massimo di 32 \textit{capabilities} distinte, + attualmente è stato aggiornato ad un vettore in grado di mantenerne fino a + 64.} in cui ciascun bit corrisponde ad una capacità diversa. + +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, che è rimasto sostanzialmente +lo stesso anche dopo le modifiche seguite alla introduzione delle +\textit{file capabilities} è il seguente: +\begin{basedescript}{\desclabelwidth{2.1cm}\desclabelstyle{\nextlinelabel}} +\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} o come + \textsl{ereditabili}. Se un processo cancella una capacità da questo insieme + non potrà più riassumerla.\footnote{questo nei casi ordinari, sono + previste però una serie di eccezioni, dipendenti anche dal tipo di + supporto, che vedremo meglio in seguito dato il notevole intreccio nella + casistica.} +\item[\textit{inheritable}] l'insieme delle \textit{capabilities} + ``\textsl{ereditabili}'', cioè di quelle che verranno trasmesse come insieme + delle \textsl{permesse} ad un nuovo programma eseguito attraverso una + chiamata ad \func{exec}. +\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. +\label{sec:capabilities_set} +\end{basedescript} + +Con l'introduzione delle \textit{file capabilities} sono stati introdotti +altri tre insiemi associabili a ciascun file.\footnote{la realizzazione viene + eseguita con l'uso di uno specifico attributo esteso, + \texttt{security.capability}, la cui modifica è riservata, (come illustrato + in sez.~\ref{sec:file_xattr}) ai processi dotato della capacità + \const{CAP\_SYS\_ADMIN}.} Le \textit{file capabilities} hanno effetto +soltanto quando il file che le porta viene eseguito come programma con una +\func{exec}, e forniscono un meccanismo che consente l'esecuzione dello stesso +con maggiori privilegi; in sostanza sono una sorta di estensione del +\acr{suid} bit limitato ai privilegi di amministratore. Anche questi tre +insiemi sono identificati con gli stessi nomi di quello dei processi, ma il +loro significato è diverso: +\begin{basedescript}{\desclabelwidth{2.1cm}\desclabelstyle{\nextlinelabel}} +\item[\textit{permitted}] (chiamato originariamente \textit{forced}) l'insieme + delle capacità che con l'esecuzione del programma verranno aggiunte alle + capacità \textsl{permesse} del processo. +\item[\textit{inheritable}] (chiamato originariamente \textit{allowed}) + l'insieme delle capacità che con l'esecuzione del programma possono essere + ereditate dal processo originario (che cioè non vengono tolte + dall'\textit{inheritable set} del processo originale all'esecuzione di + \func{exec}). +\item[\textit{effective}] in questo caso non si tratta di un insieme ma di un + unico valore logico; se attivo all'esecuzione del programma tutte le + capacità che risulterebbero \textsl{permesse} verranno pure attivate, + inserendole automaticamente nelle \textsl{effettive}, se disattivato nessuna + capacità verrà attivata (cioè l'\textit{effective set} resterà vuoto). +\end{basedescript} + +\itindbeg{capabilities~bounding~set} + +Infine come accennato, esiste un ulteriore insieme, chiamato +\textit{capabilities bounding set}, il cui scopo è quello di costituire un +limite alle capacità che possono essere attivate per un programma. Il suo +funzionamento però è stato notevolmente modificato con l'introduzione delle +\textit{file capabilities} e si deve pertanto prendere in considerazione una +casistica assai complessa. + +Per i kernel fino al 2.6.25, o se non si attiva il supporto per le +\textit{file capabilities}, il \textit{capabilities bounding set} è un +parametro generale di sistema, il cui valore viene riportato nel file +\sysctlfiled{kernel/cap-bound}. Il suo valore iniziale è definito in sede di +compilazione del kernel, e da sempre ha previsto come default la presenza di +tutte le \textit{capabilities} eccetto \const{CAP\_SETPCAP}. In questa +situazione solo il primo processo eseguito nel sistema (quello con +\textsl{pid} 1, di norma \texttt{/sbin/init}) ha la possibilità di +modificarlo; ogni processo eseguito successivamente, se dotato dei privilegi +di amministratore, è in grado soltanto di rimuovere una delle +\textit{capabilities} già presenti dell'insieme.\footnote{per essere precisi + occorre la capacità \const{CAP\_SYS\_MODULE}.} + +In questo caso l'effetto complessivo del \textit{capabilities bounding set} è +che solo le capacità in esso presenti possono essere trasmesse ad un altro +programma attraverso una \func{exec}. Questo in sostanza significa che se un +qualunque programma elimina da esso una capacità, considerato che +\texttt{init} (almeno nelle versioni ordinarie) non supporta la reimpostazione +del \textit{bounding set}, questa non sarà più disponibile per nessun processo +a meno di un riavvio, eliminando così in forma definitiva quella capacità per +tutti, compreso l'amministratore.\footnote{la qual cosa, visto il default + usato per il \textit{capabilities bounding set}, significa anche che + \const{CAP\_SETPCAP} non è stata praticamente mai usata nella sua forma + originale.} + +Con il kernel 2.6.25 e le \textit{file capabilities} il \textit{bounding set} +è diventato una proprietà di ciascun processo, che viene propagata invariata +sia attraverso una \func{fork} che una \func{exec}. In questo caso il file +\sysctlfile{kernel/cap-bound} non esiste e \texttt{init} non ha nessun +ruolo speciale, inoltre in questo caso all'avvio il valore iniziale prevede la +presenza di tutte le capacità (compresa \const{CAP\_SETPCAP}). + +Con questo nuovo meccanismo il \textit{bounding set} continua a ricoprire un +ruolo analogo al precedente nel passaggio attraverso una \func{exec}, come +limite alle capacità che possono essere aggiunte al processo in quanto +presenti nel \textit{permitted set} del programma messo in esecuzione, in +sostanza il nuovo programma eseguito potrà ricevere una capacità presente nel +suo \textit{permitted set} (quello del file) solo se questa è anche nel +\textit{bounding set} (del processo). In questo modo si possono rimuovere +definitivamente certe capacità da un processo, anche qualora questo dovesse +eseguire un programma privilegiato che prevede di riassegnarle. + +Si tenga presente però che in questo caso il \textit{bounding set} blocca +esclusivamente le capacità indicate nel \textit{permitted set} del programma +che verrebbero attivate in caso di esecuzione, e non quelle eventualmente già +presenti nell'\textit{inheritable set} del processo (ad esempio perché +presenti prima di averle rimosse dal \textit{bounding set}). In questo caso +eseguendo un programma che abbia anche lui dette capacità nel suo +\textit{inheritable set} queste verrebbero assegnate. + +In questa seconda versione inoltre il \textit{bounding set} costituisce anche +un limite per le capacità che possono essere aggiunte all'\textit{inheritable + set} del processo stesso con \func{capset}, sempre nel senso che queste +devono essere presenti nel \textit{bounding set} oltre che nel +\textit{permitted set} del processo. Questo limite vale anche per processi con +i privilegi di amministratore,\footnote{si tratta sempre di avere la + \textit{capability} \const{CAP\_SETPCAP}.} per i quali invece non vale la +condizione che le \textit{capabilities} da aggiungere nell'\textit{inheritable + set} debbano essere presenti nel proprio \textit{permitted set}.\footnote{lo + scopo anche in questo caso è ottenere una rimozione definitiva della + possibilità di passare una capacità rimossa dal \textit{bounding set}.} + +Come si può notare per fare ricorso alle \textit{capabilities} occorre +comunque farsi carico di una notevole complessità di gestione, aggravata dalla +presenza di una radicale modifica del loro funzionamento con l'introduzione +delle \textit{file capabilities}. Considerato che il meccanismo originale era +incompleto e decisamente problematico nel caso di programmi che non ne +sapessero tener conto,\footnote{il problema di sicurezza originante da questa + caratteristica venne alla ribalta con \texttt{sendmail}, in cui, riuscendo a + rimuovere \const{CAP\_SETGID} dall'\textit{inheritable set} di un processo, + si ottenne di far fallire \func{setuid} in maniera inaspettata per il + programma (che aspettandosi sempre il successo della funzione non ne + controllava lo stato di uscita) con la conseguenza di fargli fare come + amministratore operazioni che altrimenti sarebbero state eseguite, senza + poter apportare danni, da utente normale.} ci soffermeremo solo sulla +implementazione completa presente a partire dal kernel 2.6.25, tralasciando +ulteriori dettagli riguardo la versione precedente. + +Riassumendo le regole finora illustrate tutte le \textit{capabilities} vengono +ereditate senza modifiche attraverso una \func{fork} mentre, indicati con +\texttt{orig\_*} i valori degli insiemi del processo chiamante, con +\texttt{file\_*} quelli del file eseguito e con \texttt{bound\_set} il +\textit{capabilities bounding set}, dopo l'invocazione di \func{exec} il +processo otterrà dei nuovi insiemi di capacità \texttt{new\_*} secondo la +formula espressa dal seguente pseudo-codice C: + +\includecodesnip{listati/cap-results.c} + +% \begin{figure}[!htbp] +% \footnotesize \centering +% \begin{minipage}[c]{12cm} +% \includecodesnip{listati/cap-results.c} +% \end{minipage} +% \caption{Espressione della modifica delle \textit{capabilities} attraverso +% una \func{exec}.} +% \label{fig:cap_across_exec} +% \end{figure} + +\noindent e si noti come in particolare il \textit{capabilities bounding set} +non venga comunque modificato e resti lo stesso sia attraverso una \func{fork} +che attraverso una \func{exec}. + + +\itindend{capabilities~bounding~set} + +A queste regole se ne aggiungono delle altre che servono a riprodurre il +comportamento tradizionale di un sistema unix-like in tutta una serie di +circostanze. La prima di queste è relativa a quello che avviene quando si +esegue un file senza \textit{capabilities}; se infatti si considerasse questo +equivalente al non averne assegnata alcuna, non essendo presenti capacità né +nel \textit{permitted set} né nell'\textit{inheritable set} del file, +nell'esecuzione di un qualunque programma l'amministratore perderebbe tutti i +privilegi originali dal processo. + +Per questo motivo se un programma senza \textit{capabilities} assegnate viene +eseguito da un processo con \ids{UID} reale 0, esso verrà trattato come +se tanto il \textit{permitted set} che l'\textit{inheritable set} fossero con +tutte le \textit{capabilities} abilitate, con l'\textit{effective set} attivo, +col risultato di fornire comunque al processo tutte le capacità presenti nel +proprio \textit{bounding set}. Lo stesso avviene quando l'eseguibile ha attivo +il \acr{suid} bit ed appartiene all'amministratore, in entrambi i casi si +riesce così a riottenere il comportamento classico di un sistema unix-like. + +Una seconda circostanza è quella relativa a cosa succede alle +\textit{capabilities} di un processo nelle possibili transizioni da \ids{UID} +nullo a \ids{UID} non nullo o viceversa (corrispondenti rispettivamente a +cedere o riottenere i privilegi di amministratore) che si possono effettuare +con le varie funzioni viste in sez.~\ref{sec:proc_setuid}. In questo caso la +casistica è di nuovo alquanto complessa, considerata anche la presenza dei +diversi gruppi di identificatori illustrati in tab.~\ref{tab:proc_uid_gid}, si +avrà allora che: +\begin{enumerate*} +\item se si passa da \ids{UID} effettivo nullo a non nullo + l'\textit{effective set} del processo viene totalmente azzerato, se + viceversa si passa da \ids{UID} effettivo non nullo a nullo il + \textit{permitted set} viene copiato nell'\textit{effective set}; +\item se si passa da \textit{file system} \ids{UID} nullo a non nullo verranno + cancellate dall'\textit{effective set} del processo tutte le capacità + attinenti i file, e cioè \const{CAP\_LINUX\_IMMUTABLE}, \const{CAP\_MKNOD}, + \const{CAP\_DAC\_OVERRIDE}, \const{CAP\_DAC\_READ\_SEARCH}, + \const{CAP\_MAC\_OVERRIDE}, \const{CAP\_CHOWN}, \const{CAP\_FSETID} e + \const{CAP\_FOWNER} (le prime due a partire dal kernel 2.2.30), nella + transizione inversa verranno invece inserite nell'\textit{effective set} + quelle capacità della precedente lista che sono presenti nel suo + \textit{permitted set}. +\item se come risultato di una transizione riguardante gli identificativi dei + gruppi \textit{real}, \textit{saved} ed \textit{effective} in cui si passa + da una situazione in cui uno di questi era nullo ad una in cui sono tutti + non nulli,\footnote{in sostanza questo è il caso di quando si chiama + \func{setuid} per rimuovere definitivamente i privilegi di amministratore + da un processo.} verranno azzerati completamente sia il \textit{permitted + set} che l'\textit{effective set}. +\end{enumerate*} +\label{sec:capability-uid-transition} + +La combinazione di tutte queste regole consente di riprodurre il comportamento +ordinario di un sistema di tipo Unix tradizionale, ma può risultare +problematica qualora si voglia passare ad una configurazione di sistema +totalmente basata sull'applicazione delle \textit{capabilities}; in tal caso +infatti basta ad esempio eseguire un programma con \acr{suid} bit di proprietà +dell'amministratore per far riottenere ad un processo tutte le capacità +presenti nel suo \textit{bounding set}, anche se si era avuta la cura di +cancellarle dal \textit{permitted set}. + +\itindbeg{securebits} + +Per questo motivo a partire dal kernel 2.6.26, se le \textit{file + capabilities} sono abilitate, ad ogni processo viene stata associata una +ulteriore maschera binaria, chiamata \textit{securebits flags}, su cui sono +mantenuti una serie di flag (vedi tab.~\ref{tab:securebits_values}) il cui +valore consente di modificare queste regole speciali che si applicano ai +processi con \ids{UID} nullo. La maschera viene sempre mantenuta +attraverso una \func{fork}, mentre attraverso una \func{exec} viene sempre +cancellato il flag \const{SECURE\_KEEP\_CAPS}. + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}{|l|p{10cm}|} + \hline + \textbf{Flag} & \textbf{Descrizione} \\ + \hline + \hline + \constd{SECURE\_KEEP\_CAPS}&Il processo non subisce la cancellazione delle + sue \textit{capabilities} quando tutti i suoi + \ids{UID} passano ad un valore non + nullo (regola di compatibilità per il cambio + di \ids{UID} n.~3 del precedente + elenco), sostituisce il precedente uso + dell'operazione \const{PR\_SET\_KEEPCAPS} di + \func{prctl}.\\ + \constd{SECURE\_NO\_SETUID\_FIXUP}&Il processo non subisce le modifiche + delle sue \textit{capabilities} nel passaggio + da nullo a non nullo degli \ids{UID} + dei gruppi \textit{effective} e + \textit{file system} (regole di compatibilità + per il cambio di \ids{UID} nn.~1 e 2 del + precedente elenco).\\ + \constd{SECURE\_NOROOT} & Il processo non assume nessuna capacità + aggiuntiva quando esegue un programma, anche + se ha \ids{UID} nullo o il programma ha + il \acr{suid} bit attivo ed appartiene + all'amministratore (regola di compatibilità + per l'esecuzione di programmi senza + \textit{capabilities}).\\ + \hline + \end{tabular} + \caption{Costanti identificative dei flag che compongono la maschera dei + \textit{securebits}.} + \label{tab:securebits_values} +\end{table} + +A ciascuno dei flag di tab.~\ref{tab:securebits_values} è inoltre abbinato un +corrispondente flag di blocco, identificato da una costante omonima con +l'estensione \texttt{\_LOCKED}, la cui attivazione è irreversibile ed ha +l'effetto di rendere permanente l'impostazione corrente del corrispondente +flag ordinario; in sostanza con \constd{SECURE\_KEEP\_CAPS\_LOCKED} si rende +non più modificabile \const{SECURE\_KEEP\_CAPS}, ed analogamente avviene con +\constd{SECURE\_NO\_SETUID\_FIXUP\_LOCKED} per +\const{SECURE\_NO\_SETUID\_FIXUP} e con \constd{SECURE\_NOROOT\_LOCKED} per +\const{SECURE\_NOROOT}. + +Per l'impostazione di questi flag sono state predisposte due specifiche +operazioni di \func{prctl} (vedi sez.~\ref{sec:process_prctl}), +\const{PR\_GET\_SECUREBITS}, che consente di ottenerne il valore, e +\const{PR\_SET\_SECUREBITS}, che consente di modificarne il valore; per +quest'ultima sono comunque necessari i privilegi di amministratore ed in +particolare la capacità \const{CAP\_SETPCAP}. Prima dell'introduzione dei +\textit{securebits} era comunque possibile ottenere lo stesso effetto di +\const{SECURE\_KEEP\_CAPS} attraverso l'uso di un'altra operazione di +\func{prctl}, \const{PR\_SET\_KEEPCAPS}. + +\itindend{securebits} + +Oltre alla gestione dei \textit{securebits} la nuova versione delle +\textit{file capabilities} prevede l'uso di \func{prctl} anche per la gestione +del \textit{capabilities bounding set}, attraverso altre due operazioni +dedicate, \const{PR\_CAPBSET\_READ} per controllarne il valore e +\const{PR\_CAPBSET\_DROP} per modificarlo; quest'ultima di nuovo è una +operazione privilegiata che richiede la capacità \const{CAP\_SETPCAP} e che, +come indica chiaramente il nome, permette solo la rimozione di una +\textit{capability} dall'insieme; per i dettagli sull'uso di tutte queste +operazioni si rimanda alla rilettura di sez.~\ref{sec:process_prctl}. + +\itindend{file~capabilities} + + +% NOTE per dati relativi al process capability bounding set, vedi: +% http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=3b7391de67da515c91f48aa371de77cb6cc5c07e + +% NOTE riferimenti ai vari cambiamenti vedi: +% http://lwn.net/Articles/280279/ +% http://lwn.net/Articles/256519/ +% http://lwn.net/Articles/211883/ + + +Un elenco delle \textit{capabilities} disponibili su Linux, con una breve +descrizione ed il nome delle costanti che le identificano, è riportato in +tab.~\ref{tab:proc_capabilities};\footnote{l'elenco presentato questa tabella, + ripreso dalla pagina di manuale (accessibile con \texttt{man capabilities}) + e dalle definizioni in \texttt{include/linux/capabilities.h}, è aggiornato + al kernel 3.2.} la tabella è divisa in due parti, la prima riporta le +\textit{capabilities} previste anche nella bozza dello standard POSIX1.e, la +seconda quelle specifiche di Linux. Come si può notare dalla tabella alcune +\textit{capabilities} attengono a singole funzionalità e sono molto +specializzate, mentre altre hanno un campo di applicazione molto vasto, che è +opportuno dettagliare maggiormente. + +\begin{table}[!hbtp] + \centering + \footnotesize + \begin{tabular}{|l|p{10cm}|} + \hline + \textbf{Capacità}&\textbf{Descrizione}\\ + \hline + \hline +% +% POSIX-draft defined capabilities. +% + \constd{CAP\_AUDIT\_CONTROL}& Abilitare e disabilitare il + controllo dell'auditing (dal kernel 2.6.11).\\ + \constd{CAP\_AUDIT\_WRITE}&Scrivere dati nel giornale di + auditing del kernel (dal kernel 2.6.11).\\ + % TODO verificare questa roba dell'auditing + \constd{CAP\_BLOCK\_SUSPEND}&Utilizzare funzionalità che possono bloccare + la sospensione del sistema (dal kernel 3.5).\\ + \constd{CAP\_CHOWN} & Cambiare proprietario e gruppo + proprietario di un file (vedi + sez.~\ref{sec:file_ownership_management}).\\ + \constd{CAP\_DAC\_OVERRIDE}& Evitare il controllo dei + permessi di lettura, scrittura ed esecuzione dei + file, (vedi sez.~\ref{sec:file_access_control}).\\ + \constd{CAP\_DAC\_READ\_SEARCH}& Evitare il controllo dei + permessi di lettura ed esecuzione per + le directory (vedi + sez.~\ref{sec:file_access_control}).\\ + \const{CAP\_FOWNER} & Evitare il controllo della proprietà di un file + per tutte le operazioni privilegiate non coperte + dalle precedenti \const{CAP\_DAC\_OVERRIDE} e + \const{CAP\_DAC\_READ\_SEARCH}.\\ + \constd{CAP\_FSETID} & Evitare la cancellazione automatica dei bit + \acr{suid} e \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_perm_management}).\\ + \constd{CAP\_KILL} & Mandare segnali a qualunque + processo (vedi sez.~\ref{sec:sig_kill_raise}).\\ + \constd{CAP\_SETFCAP} & Impostare le \textit{capabilities} di un file + (dal kernel 2.6.24).\\ + \constd{CAP\_SETGID} & Manipolare i group ID dei + processi, sia il principale che i supplementari, + (vedi sez.~\ref{sec:proc_setgroups}) che quelli + trasmessi tramite i socket \textit{unix domain} + (vedi sez.~\ref{sec:unix_socket}).\\ + \constd{CAP\_SETUID} & Manipolare gli user ID del + processo (vedi sez.~\ref{sec:proc_setuid}) e di + trasmettere un user ID arbitrario nel passaggio + delle credenziali coi socket \textit{unix + domain} (vedi sez.~\ref{sec:unix_socket}).\\ +% +% Linux specific capabilities +% +\hline + \constd{CAP\_IPC\_LOCK} & Effettuare il \textit{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}). \\ +% TODO verificare l'interazione con SHM_HUGETLB + \constd{CAP\_IPC\_OWNER}& Evitare il controllo dei permessi + per le operazioni sugli oggetti di + intercomunicazione fra processi (vedi + sez.~\ref{sec:ipc_sysv}).\\ + \constd{CAP\_LEASE} & Creare dei \textit{file lease} (vedi + sez.~\ref{sec:file_asyncronous_lease}) + pur non essendo proprietari del file (dal kernel + 2.4).\\ + \constd{CAP\_LINUX\_IMMUTABLE}& Impostare sui file gli attributi + \textit{immutable} e \textit{append-only} (vedi + sez.~\ref{sec:file_perm_overview}) se + supportati.\\ + \constd{CAP\_MAC\_ADMIN}& Amministrare il \textit{Mandatory + Access Control} di \textit{Smack} (dal kernel + 2.6.25).\\ + \constd{CAP\_MAC\_OVERRIDE}& Evitare il \textit{Mandatory + Access Control} di \textit{Smack} (dal kernel + 2.6.25).\\ + \constd{CAP\_MKNOD} & Creare file di dispositivo con \func{mknod} (vedi + sez.~\ref{sec:file_mknod}) (dal kernel 2.4).\\ + \const{CAP\_NET\_ADMIN} & Eseguire alcune operazioni + privilegiate sulla rete.\\ + \constd{CAP\_NET\_BIND\_SERVICE}& Porsi in ascolto su porte riservate (vedi + sez.~\ref{sec:TCP_func_bind}).\\ + \constd{CAP\_NET\_BROADCAST}& Consentire l'uso di socket in + \textit{broadcast} e \textit{multicast}.\\ + \constd{CAP\_NET\_RAW} & Usare socket \texttt{RAW} e \texttt{PACKET} + (vedi sez.~\ref{sec:sock_type}).\\ + \const{CAP\_SETPCAP} & Effettuare modifiche privilegiate alle + \textit{capabilities}.\\ + \const{CAP\_SYS\_ADMIN} & Eseguire una serie di compiti amministrativi.\\ + \constd{CAP\_SYS\_BOOT} & Eseguire un riavvio del sistema (vedi + sez.~\ref{sec:sys_reboot}).\\ + \constd{CAP\_SYS\_CHROOT}& Eseguire la funzione \func{chroot} (vedi + sez.~\ref{sec:file_chroot}).\\ + \constd{CAP\_SYS\_MODULE}& Caricare e rimuovere moduli del kernel.\\ + \const{CAP\_SYS\_NICE} & Modificare le varie priorità dei processi (vedi + sez.~\ref{sec:proc_priority}).\\ + \constd{CAP\_SYS\_PACCT}& Usare le funzioni di \textit{accounting} dei + processi (vedi + sez.~\ref{sec:sys_bsd_accounting}).\\ + \constd{CAP\_SYS\_PTRACE}& La capacità di tracciare qualunque processo con + \func{ptrace} (vedi + sez.~\ref{sec:process_ptrace}).\\ + \constd{CAP\_SYS\_RAWIO}& Operare sulle porte di I/O con \func{ioperm} e + \func{iopl} (vedi + sez.~\ref{sec:process_io_port}).\\ + \const{CAP\_SYS\_RESOURCE}& Superare le varie limitazioni sulle risorse.\\ + \constd{CAP\_SYS\_TIME} & Modificare il tempo di sistema (vedi + sez.~\ref{sec:sys_time}).\\ + \constd{CAP\_SYS\_TTY\_CONFIG}&Simulare un \textit{hangup} della console, + con la funzione \func{vhangup}.\\ + \constd{CAP\_SYSLOG} & Gestire il buffer dei messaggi + del kernel, (vedi sez.~\ref{sec:sess_daemon}), + introdotta dal kernel 2.6.38 come capacità + separata da \const{CAP\_SYS\_ADMIN}.\\ + \constd{CAP\_WAKE\_ALARM}&Usare i timer di tipo + \const{CLOCK\_BOOTTIME\_ALARM} e + \const{CLOCK\_REALTIME\_ALARM}, vedi + sez.~\ref{sec:sig_timer_adv} (dal kernel 3.0).\\ + \hline + \end{tabular} + \caption{Le costanti che identificano le \textit{capabilities} presenti nel + kernel.} +\label{tab:proc_capabilities} +\end{table} + +\constbeg{CAP\_SETPCAP} + +Prima di dettagliare il significato della capacità più generiche, conviene +però dedicare un discorso a parte a \const{CAP\_SETPCAP}, il cui significato è +stato completamente cambiato con l'introduzione delle \textit{file + capabilities} nel kernel 2.6.24. In precedenza questa capacità era quella +che permetteva al processo che la possedeva di impostare o rimuovere le +\textit{capabilities} presenti nel suo \textit{permitted set} su un qualunque +altro processo. In realtà questo non è mai stato l'uso inteso nelle bozze +dallo standard POSIX, ed inoltre, come si è già accennato, dato che questa +capacità è sempre stata assente (a meno di specifiche ricompilazioni del +kernel) nel \textit{capabilities bounding set} usato di default, essa non è +neanche mai stata realmente disponibile. + +Con l'introduzione \textit{file capabilities} e il cambiamento del significato +del \textit{capabilities bounding set} la possibilità di modificare le +capacità di altri processi è stata completamente rimossa, e +\const{CAP\_SETPCAP} ha acquisito quello che avrebbe dovuto essere il suo +significato originario, e cioè la capacità del processo di poter inserire nel +suo \textit{inheritable set} qualunque capacità presente nel \textit{bounding + set}. Oltre a questo la disponibilità di \const{CAP\_SETPCAP} consente ad un +processo di eliminare una capacità dal proprio \textit{bounding set} (con la +conseguente impossibilità successiva di eseguire programmi con quella +capacità), o di impostare i \textit{securebits} delle \textit{capabilities}. + +\constend{CAP\_SETPCAP} +\constbeg{CAP\_FOWNER} + +La prima fra le capacità ``\textsl{ampie}'' che occorre dettagliare +maggiormente è \const{CAP\_FOWNER}, che rimuove le restrizioni poste ad un +processo che non ha la proprietà di un file in un vasto campo di +operazioni;\footnote{vale a dire la richiesta che l'\ids{UID} effettivo del + processo (o meglio l'\ids{UID} di filesystem, vedi + sez.~\ref{sec:proc_setuid}) coincida con quello del proprietario.} queste +comprendono i cambiamenti dei permessi e dei tempi del file (vedi +sez.~\ref{sec:file_perm_management} e sez.~\ref{sec:file_file_times}), le +impostazioni degli attributi dei file e delle ACL (vedi +sez.~\ref{sec:file_xattr} e \ref{sec:file_ACL}), poter ignorare lo +\textit{sticky bit} nella cancellazione dei file (vedi +sez.~\ref{sec:file_special_perm}), la possibilità di impostare il flag di +\const{O\_NOATIME} con \func{open} e \func{fcntl} (vedi +sez.~\ref{sec:file_open_close} e sez.~\ref{sec:file_fcntl_ioctl}) senza +restrizioni. + +\constend{CAP\_FOWNER} +\constbeg{CAP\_NET\_ADMIN} + +Una seconda capacità che copre diverse operazioni, in questo caso riguardanti +la rete, è \const{CAP\_NET\_ADMIN}, che consente di impostare le opzioni +privilegiate dei socket (vedi sez.~\ref{sec:sock_generic_options}), abilitare +il \textit{multicasting} (vedi sez.\ref{sec:sock_ipv4_options}), eseguire la +configurazione delle interfacce di rete (vedi +sez.~\ref{sec:sock_ioctl_netdevice}) ed impostare la tabella di instradamento. + +\constend{CAP\_NET\_ADMIN} +\constbeg{CAP\_SYS\_ADMIN} + +Una terza \textit{capability} con vasto campo di applicazione è +\const{CAP\_SYS\_ADMIN}, che copre una serie di operazioni amministrative, +come impostare le quote disco (vedi sez.\ref{sec:disk_quota}), attivare e +disattivare la \textit{swap}, montare, rimontare e smontare filesystem (vedi +sez.~\ref{sec:filesystem_mounting}), effettuare operazioni di controllo su +qualunque oggetto dell'IPC di SysV (vedi sez.~\ref{sec:ipc_sysv}), operare +sugli attributi estesi dei file di classe \texttt{security} o \texttt{trusted} +(vedi sez.~\ref{sec:file_xattr}), specificare un \ids{UID} arbitrario nella +trasmissione delle credenziali dei socket (vedi +sez.~\ref{sec:socket_credential_xxx}), assegnare classi privilegiate +(\const{IOPRIO\_CLASS\_RT} e prima del kernel 2.6.25 anche +\const{IOPRIO\_CLASS\_IDLE}) per lo scheduling dell'I/O (vedi +sez.~\ref{sec:io_priority}), superare il limite di sistema sul numero massimo +di file aperti,\footnote{quello indicato da \sysctlfiled{fs/file-max}.} +effettuare operazioni privilegiate sulle chiavi mantenute dal kernel (vedi +sez.~\ref{sec:keyctl_management}), usare la funzione \func{lookup\_dcookie}, +usare \const{CLONE\_NEWNS} con \func{unshare} e \func{clone}, (vedi +sez.~\ref{sec:process_clone}). + +\constend{CAP\_SYS\_ADMIN} +\constbeg{CAP\_SYS\_NICE} + +Originariamente \const{CAP\_SYS\_NICE} riguardava soltanto la capacità di +aumentare le priorità di esecuzione dei processi, come la diminuzione del +valore di \textit{nice} (vedi sez.~\ref{sec:proc_sched_stand}), l'uso delle +priorità \textit{real-time} (vedi sez.~\ref{sec:proc_real_time}), o +l'impostazione delle affinità di processore (vedi +sez.~\ref{sec:proc_sched_multiprocess}); ma con l'introduzione di priorità +anche riguardo le operazioni di accesso al disco, e, nel caso di sistemi NUMA, +alla memoria, essa viene a coprire anche la possibilità di assegnare priorità +arbitrarie nell'accesso a disco (vedi sez.~\ref{sec:io_priority}) e nelle +politiche di allocazione delle pagine di memoria ai nodi di un sistema NUMA. + +\constend{CAP\_SYS\_NICE} +\constbeg{CAP\_SYS\_RESOURCE} + +Infine la \textit{capability} \const{CAP\_SYS\_RESOURCE} attiene alla +possibilità di superare i limiti imposti sulle risorse di sistema, come usare +lo spazio disco riservato all'amministratore sui filesystem che lo supportano, +usare la funzione \func{ioctl} per controllare il \textit{journaling} sul +filesystem \acr{ext3}, non subire le quote disco, aumentare i limiti sulle +risorse di un processo (vedi sez.~\ref{sec:sys_resource_limit}) e quelle sul +numero di processi, ed i limiti sulle dimensioni dei messaggi delle code del +SysV IPC (vedi sez.~\ref{sec:ipc_sysv_mq}). + +\constend{CAP\_SYS\_RESOURCE} + +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 di sistema sono +\funcd{capget} e \funcd{capset} e costituiscono l'interfaccia di gestione +basso livello; i loro rispettivi prototipi sono: + +\begin{funcproto}{ +\fhead{sys/capability.h} +\fdecl{int capget(cap\_user\_header\_t hdrp, cap\_user\_data\_t datap)} +\fdesc{Legge le \textit{capabilities}.} +\fdecl{int capset(cap\_user\_header\_t hdrp, const cap\_user\_data\_t datap)} +\fdesc{Imposta le \textit{capabilities}.} +} + +{Le funzioni ritornano $0$ in caso di successo e $-1$ per un errore, nel qual + caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{EFAULT}] si è indicato un puntatore sbagliato o nullo + per \param{hdrp} o \param{datap} (quest'ultimo può essere nullo solo se si + usa \func{capget} per ottenere la versione delle \textit{capabilities} + usata dal kernel). + \item[\errcode{EINVAL}] si è specificato un valore non valido per uno dei + campi di \param{hdrp}, in particolare una versione non valida della + versione delle \textit{capabilities}. + \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}. + \item[\errcode{ESRCH}] si è fatto riferimento ad un processo inesistente. + \end{errlist} +} +\end{funcproto} + +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 un certo periodo di tempo era anche +indicato che per poterle utilizzare fosse necessario che la macro +\macro{\_POSIX\_SOURCE} risultasse non definita (ed era richiesto di inserire +una istruzione \texttt{\#undef \_POSIX\_SOURCE} prima di includere +\headfiled{sys/capability.h}) requisito che non risulta più +presente.\footnote{e non è chiaro neanche quanto sia mai stato davvero + necessario.} + +\begin{figure}[!htb] + \footnotesize + \centering + \begin{minipage}[c]{0.8\textwidth} + \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} + +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,\footnote{viene però + garantito che le vecchie funzioni continuino a funzionare.} Pertanto se si +vogliono scrivere programmi portabili che possano essere eseguiti senza +modifiche o adeguamenti su qualunque versione del kernel è opportuno +utilizzare le interfacce di alto livello che vedremo più avanti. + +La struttura a cui deve puntare l'argomento \param{hdrp} serve ad indicare, +tramite il campo \var{pid}, il \ids{PID} del processo del quale si vogliono +leggere o modificare le \textit{capabilities}. Con \func{capset} questo, se si +usano le \textit{file capabilities}, può essere solo 0 o il \ids{PID} del +processo chiamante, che sono equivalenti. Non tratteremo, essendo comunque di +uso irrilevante, il caso in cui, in mancanza di tale supporto, la funzione può +essere usata per modificare le \textit{capabilities} di altri processi, per il +quale si rimanda, se interessati, alla lettura della pagina di manuale. + +Il campo \var{version} deve essere impostato al valore della versione delle +stesse usata dal kernel (quello indicato da una delle costanti +\texttt{\_LINUX\_CAPABILITY\_VERSION\_n} 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 +versione due è comunque deprecata e non deve essere usata, ed il kernel +stamperà un avviso se lo si fa. + +I valori delle \textit{capabilities} devono essere passati come maschere +binarie;\footnote{e si tenga presente che i valori di + tab.~\ref{tab:proc_capabilities} non possono essere combinati direttamente, + indicando il numero progressivo del bit associato alla relativa capacità.} +con l'introduzione delle \textit{capabilities} a 64 bit inoltre il +puntatore \param{datap} non può essere più considerato come relativo ad una +singola struttura, ma ad un vettore di due strutture.\footnote{è questo cambio + di significato che ha portato a deprecare la versione 2, che con + \func{capget} poteva portare ad un buffer overflow per vecchie applicazioni + che continuavano a considerare \param{datap} come puntatore ad una singola + struttura.} + +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 della \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 al compilatore l'uso +della suddetta libreria attraverso l'opzione \texttt{-lcap}. + +\itindbeg{capability~state} + +Le funzioni dell'interfaccia alle \textit{capabilities} definite nelle bozze +dello standard POSIX.1e prevedono l'uso di un tipo di dato opaco, +\typed{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 fanno riferimento soltanto ad oggetti di questo tipo. +L'interfaccia pertanto non soltanto fornisce le funzioni per modificare e +leggere le \textit{capabilities}, ma anche quelle per gestire i dati +attraverso i \textit{capability state}, che presentano notevoli affinità, +essendo parte di bozze dello stesso standard, con quelle già viste per le ACL. + +La prima funzione dell'interfaccia è 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{funcproto}{ +\fhead{sys/capability.h} +\fdecl{cap\_t cap\_init(void)} +\fdesc{Crea ed inizializza un \textit{capability state}.} +} + +{La funzione ritorna un \textit{capability state} in caso di successo e + \val{NULL} per un errore, nel qual caso \var{errno} potrà assumere solo il + valore \errval{ENOMEM}. } +\end{funcproto} + +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 sufficiente ad allocare i dati) viene restituito \val{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, per questo l'interfaccia fornisce una apposita +funzione, \funcd{cap\_free}, il cui prototipo è: + +\begin{funcproto}{ +\fhead{sys/capability.h} +\fdecl{int cap\_free(void *obj\_d)} +\fdesc{Disalloca la memoria allocata per i dati delle \textit{capabilities}..} +} + +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual + caso \var{errno} potrà assumere solo il valore \errval{EINVAL}. +} +\end{funcproto} + + +La funzione permette di liberare la memoria allocata dalle altre funzioni +della libreria sia per un \textit{capability state}, nel qual caso l'argomento +sarà 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 sarà un dato di tipo +\texttt{char *}. Per questo motivo l'argomento \param{obj\_d} è dichiarato +come \texttt{void *}, per evitare la necessità di eseguire un \textit{cast}, +ma dovrà comunque corrispondere ad un puntatore ottenuto tramite le 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{funcproto}{ +\fhead{sys/capability.h} +\fdecl{cap\_t cap\_dup(cap\_t cap\_p)} +\fdesc{Duplica un \textit{capability state} restituendone una copia.} +} + +{La funzione ritorna un \textit{capability state} in caso di successo e + \val{NULL} per un errore, nel qual caso \var{errno} assumerà i valori + \errval{ENOMEM} o \errval{EINVAL} nel loro significato generico.} +\end{funcproto} + + +La funzione crea una copia del \textit{capability state} posto all'indirizzo +\param{cap\_p} che si è 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, ed alla fine +delle operazioni si dovrà disallocare anche la copia, oltre all'originale. + +Una seconda classe di funzioni di servizio previste dall'interfaccia sono +quelle per la gestione dei dati contenuti all'interno di un \textit{capability + state}; la prima di queste è \funcd{cap\_clear}, il cui prototipo è: + +\begin{funcproto}{ +\fhead{sys/capability.h} +\fdecl{int cap\_clear(cap\_t cap\_p)} +\fdesc{Inizializza un \textit{capability state} cancellando tutte le + \textit{capabilities}.} +} + +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual + caso \var{errno} potrà assumere solo il valore \errval{EINVAL}. +} +\end{funcproto} + +La funzione si limita ad azzerare tutte le \textit{capabilities} presenti nel +\textit{capability state} all'indirizzo \param{cap\_p} passato come argomento, +restituendo uno stato \textsl{vuoto}, analogo a quello che si ottiene nella +creazione con \func{cap\_init}. + +Una variante di \func{cap\_clear} è \funcd{cap\_clear\_flag} che cancella da +un \textit{capability state} tutte le \textit{capabilities} di un certo +insieme fra quelli elencati a pag.~\pageref{sec:capabilities_set}, il suo +prototipo è: + +\begin{funcproto}{ +\fhead{sys/capability.h} +\fdecl{int cap\_clear\_flag(cap\_t cap\_p, cap\_flag\_t flag)} +\fdesc{Cancella delle \textit{capabilities} da un \textit{capability state}.} +} + +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual + caso \var{errno} potrà assumere solo il valore \errval{EINVAL}. +} +\end{funcproto} + +La funzione richiede che si indichi quale degli insiemi si intente cancellare +da \param{cap\_p} con l'argomento \param{flag}. Questo deve essere specificato +con una variabile di tipo \type{cap\_flag\_t} che può assumere +esclusivamente\footnote{si tratta in effetti di un tipo enumerato, come si può + verificare dalla sua definizione che si trova in + \headfile{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 + \constd{CAP\_EFFECTIVE} & Capacità dell'insieme \textsl{effettivo}.\\ + \constd{CAP\_PERMITTED} & Capacità dell'insieme \textsl{permesso}.\\ + \constd{CAP\_INHERITABLE}& Capacità dell'insieme \textsl{ereditabile}.\\ + \hline + \end{tabular} + \caption{Valori possibili per il tipo di dato \typed{cap\_flag\_t} che + identifica gli insiemi delle \textit{capabilities}.} + \label{tab:cap_set_identifier} +\end{table} + +Si possono inoltre confrontare in maniera diretta due diversi +\textit{capability state} con la funzione \funcd{cap\_compare}; il suo +prototipo è: + +\begin{funcproto}{ +\fhead{sys/capability.h} +\fdecl{int cap\_compare(cap\_t cap\_a, cap\_t cap\_b)} +\fdesc{Confronta due \textit{capability state}.} +} + +{La funzione ritorna $0$ se i \textit{capability state} sono identici + ed un valore positivo se differiscono, non sono previsti errori.} +\end{funcproto} + + +La funzione esegue un confronto fra i due \textit{capability state} passati +come argomenti e ritorna in un valore intero il risultato, questo è nullo se +sono identici o positivo se vi sono delle differenze. Il valore di ritorno +della funzione consente inoltre di per ottenere ulteriori informazioni su +quali sono gli insiemi di \textit{capabilities} che risultano differenti. Per +questo si può infatti usare la apposita macro \macro{CAP\_DIFFERS}: + +{\centering +\vspace{3pt} +\begin{funcbox}{ +\fhead{sys/capability.h} +\fdecl{int \macrod{CAP\_DIFFERS}(value, flag)} +\fdesc{Controlla lo stato di eventuali differenze delle \textit{capabilities} + nell'insieme \texttt{flag}.} +} +\end{funcbox} +} + +La macro richiede che si passi nell'argomento \texttt{value} il risultato +della funzione \func{cap\_compare} e in \texttt{flag} l'indicazione (coi +valori di tab.~\ref{tab:cap_set_identifier}) dell'insieme che si intende +controllare; restituirà un valore diverso da zero se le differenze rilevate da +\func{cap\_compare} sono presenti nell'insieme indicato. + +Per la gestione dei singoli valori delle \textit{capabilities} presenti in un +\textit{capability state} l'interfaccia prevede due funzioni specifiche, +\funcd{cap\_get\_flag} e \funcd{cap\_set\_flag}, che permettono +rispettivamente di leggere o impostare il valore di una capacità all'interno +in uno dei tre insiemi già citati; i rispettivi prototipi sono: + +\begin{funcproto}{ +\fhead{sys/capability.h} +\fdecl{int cap\_get\_flag(cap\_t cap\_p, cap\_value\_t cap, cap\_flag\_t +flag,\\ +\phantom{int cap\_get\_flag(}cap\_flag\_value\_t *value\_p)} +\fdesc{Legge il valore di una \textit{capability}.} +\fdecl{int cap\_set\_flag(cap\_t cap\_p, cap\_flag\_t flag, int ncap, + cap\_value\_t *caps, \\ +\phantom{int cap\_set\_flag(}cap\_flag\_value\_t value)} +\fdesc{Imposta il valore di una \textit{capability}.} +} + +{Le funzioni ritornano $0$ in caso di successo e $-1$ per un errore, nel qual + caso \var{errno} potrà assumere solo il valore \errval{EINVAL}. +} +\end{funcproto} + +In entrambe le funzioni l'argomento \param{cap\_p} indica il puntatore al +\textit{capability state} su cui operare, mentre l'argomento \param{flag} +indica su quale dei tre insiemi si intende operare, sempre con i valori di +tab.~\ref{tab:cap_set_identifier}. La capacità che si intende controllare o +impostare invece deve essere specificata attraverso una variabile di tipo +\typed{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} può indicare una sola capacità.\footnote{in + \headfile{sys/capability.h} 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 capacità è 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 + \constd{CAP\_CLEAR}& La capacità non è impostata.\\ + \constd{CAP\_SET} & La capacità è impostata.\\ + \hline + \end{tabular} + \caption{Valori possibili per il tipo di dato \typed{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 lo restituisce come \textit{value result argument} nella +variabile puntata dall'argomento \param{value\_p}. Questa deve essere di tipo +\type{cap\_flag\_value\_t} ed assumerà uno dei valori di +tab.~\ref{tab:cap_value_type}. La funzione consente pertanto di leggere solo +lo stato di una capacità alla volta. + +La funzione \func{cap\_set\_flag} può invece impostare in una sola chiamata +più \textit{capabilities}, anche se solo all'interno dello stesso insieme ed +allo stesso valore. Per questo motivo essa prende un vettore di valori di tipo +\type{cap\_value\_t} nell'argomento \param{caps}, la cui dimensione viene +specificata dall'argomento \param{ncap}. Il tipo di impostazione da eseguire +(cancellazione o attivazione) per le capacità elencate in \param{caps} viene +indicato dall'argomento \param{value} sempre con i valori di +tab.~\ref{tab:cap_value_type}. + +Per semplificare la gestione delle \textit{capabilities} l'interfaccia prevede +che sia possibile utilizzare anche una rappresentazione testuale del contenuto +di un \textit{capability state} e fornisce le opportune funzioni di +gestione;\footnote{entrambe erano previste dalla bozza dello standard + POSIX.1e.} la prima di queste, che consente di ottenere la rappresentazione +testuale, è \funcd{cap\_to\_text}, il cui prototipo è: + +\begin{funcproto}{ +\fhead{sys/capability.h} +\fdecl{char *cap\_to\_text(cap\_t caps, ssize\_t *length\_p)} +\fdesc{Genera una visualizzazione testuale delle \textit{capabilities}.} +} + +{La funzione ritorna un puntatore alla stringa con la descrizione delle + \textit{capabilities} in caso di successo e \val{NULL} per un errore, nel + qual caso \var{errno} assumerà i valori \errval{EINVAL} o \errval{ENOMEM} + nel loro significato generico.} +\end{funcproto} + +La funzione ritorna l'indirizzo di una stringa contente la descrizione +testuale del contenuto del \textit{capability state} \param{caps} passato come +argomento, e, qualora l'argomento \param{length\_p} sia diverso da \val{NULL}, +restituisce come \textit{value result argument} nella variabile intera da +questo puntata la lunghezza della stringa. La stringa restituita viene +allocata automaticamente dalla funzione e pertanto dovrà essere liberata con +\func{cap\_free}. + +La rappresentazione testuale, che viene usata anche dai programmi di gestione a +riga di comando, prevede che lo stato venga rappresentato con una stringa di +testo composta da una serie di proposizioni separate da spazi, ciascuna delle +quali specifica una operazione da eseguire per creare lo stato finale. Nella +rappresentazione si fa sempre conto di partire da uno stato in cui tutti gli +insiemi sono vuoti e si provvede a impostarne i contenuti. + +Ciascuna proposizione è nella forma di un elenco di capacità, espresso con i +nomi di tab.~\ref{tab:proc_capabilities} separati da virgole, seguito da un +operatore, e dall'indicazione degli insiemi a cui l'operazione si applica. I +nomi delle capacità possono essere scritti sia maiuscoli che minuscoli, viene +inoltre riconosciuto il nome speciale \texttt{all} che è equivalente a +scrivere la lista completa. Gli insiemi sono identificati dalle tre lettere +iniziali: ``\texttt{p}'' per il \textit{permitted}, ``\texttt{i}'' per +l'\textit{inheritable} ed ``\texttt{e}'' per l'\textit{effective} che devono +essere sempre minuscole, e se ne può indicare più di uno. + +Gli operatori possibili sono solo tre: ``\texttt{+}'' che aggiunge le capacità +elencate agli insiemi indicati, ``\texttt{-}'' che le toglie e ``\texttt{=}'' +che le assegna esattamente. I primi due richiedono che sia sempre indicato sia +un elenco di capacità che gli insiemi a cui esse devono applicarsi, e +rispettivamente attiveranno o disattiveranno le capacità elencate nell'insieme +o negli insiemi specificati, ignorando tutto il resto. I due operatori possono +anche essere combinati nella stessa proposizione, per aggiungere e togliere le +capacità dell'elenco da insiemi diversi. + +L'assegnazione si applica invece su tutti gli insiemi allo stesso tempo, +pertanto l'uso di ``\texttt{=}'' è equivalente alla cancellazione preventiva +di tutte le capacità ed alla impostazione di quelle elencate negli insiemi +specificati, questo significa che in genere lo si usa una sola volta +all'inizio della stringa. In tal caso l'elenco delle capacità può non essere +indicato e viene assunto che si stia facendo riferimento a tutte quante senza +doverlo scrivere esplicitamente. + +Come esempi avremo allora che un processo non privilegiato di un utente, che +non ha nessuna capacità attiva, avrà una rappresentazione nella forma +``\texttt{=}'' che corrisponde al fatto che nessuna capacità viene assegnata a +nessun insieme (vale la cancellazione preventiva), mentre un processo con +privilegi di amministratore avrà una rappresentazione nella forma +``\texttt{=ep}'' in cui tutte le capacità vengono assegnate agli insiemi +\textit{permitted} ed \textit{effective} (e l'\textit{inheritable} è ignorato +in quanto per le regole viste a pag.~\ref{sec:capability-uid-transition} le +capacità verranno comunque attivate attraverso una \func{exec}). Infine, come +esempio meno banale dei precedenti, otterremo per \texttt{init} una +rappresentazione nella forma ``\texttt{=ep cap\_setpcap-e}'' dato che come +accennato tradizionalmente \const{CAP\_SETPCAP} è sempre stata rimossa da +detto processo. + +Viceversa per ottenere un \textit{capability state} dalla sua rappresentazione +testuale si può usare la funzione \funcd{cap\_from\_text}, il cui prototipo è: + +\begin{funcproto}{ +\fhead{sys/capability.h} +\fdecl{cap\_t cap\_from\_text(const char *string)} +\fdesc{Crea un \textit{capability state} dalla sua rappresentazione testuale.} +} + +{La funzione ritorna un \textit{capability state} in caso di successo e + \val{NULL} per un errore, nel qual caso \var{errno} assumerà i valori + \errval{EINVAL} o \errval{ENOMEM} nel loro significato generico.} +\end{funcproto} + + +La funzione restituisce il puntatore ad un \textit{capability state} +inizializzato con i valori indicati nella stringa \param{string} che ne +contiene la rappresentazione testuale. La memoria per il \textit{capability + state} viene allocata automaticamente dalla funzione e dovrà essere liberata +con \func{cap\_free}. + +Alle due funzioni citate se ne aggiungono altre due che consentono di +convertire i valori delle costanti di tab.~\ref{tab:proc_capabilities} nelle +stringhe usate nelle rispettive rappresentazioni e viceversa. Le due funzioni, +\funcd{cap\_to\_name} e \funcd{cap\_from\_name}, sono estensioni specifiche di +Linux ed i rispettivi prototipi sono: + +\begin{funcproto}{ +\fhead{sys/capability.h} +\fdecl{char *cap\_to\_name(cap\_value\_t cap)} +\fdesc{Converte il valore numerico di una \textit{capabilities} alla sua + rappresentazione testuale.} +\fdecl{int cap\_from\_name(const char *name, cap\_value\_t *cap\_p)} + +\fdesc{Converte la rappresentazione testuale di una \textit{capabilities} al + suo valore numerico.} +} + +{La funzione \func{cap\_to\_name} ritorna un puntatore ad una stringa in caso + di successo e \val{NULL} per un errore, mentre \func{cap\_to\_name} ritorna + $0$ in caso di successo e $-1$ per un errore, per entrambe in caso di errore + \var{errno} assumerà i valori \errval{EINVAL} o \errval{ENOMEM} nel loro + significato generico. +} +\end{funcproto} + +La prima funzione restituisce la stringa (allocata automaticamente e che dovrà +essere liberata con \func{cap\_free}) che corrisponde al valore della +capacità \param{cap}, mentre la seconda restituisce nella variabile puntata +da \param{cap\_p}, come \textit{value result argument}, il valore della +capacità rappresentata dalla stringa \param{name}. + +Fin quei abbiamo trattato solo le funzioni di servizio relative alla +manipolazione dei \textit{capability state} come strutture di dati; +l'interfaccia di gestione prevede però anche le funzioni per trattare le +\textit{capabilities} presenti nei processi. La prima di queste funzioni è +\funcd{cap\_get\_proc} che consente la lettura delle \textit{capabilities} del +processo corrente, il suo prototipo è: + +\begin{funcproto}{ +\fhead{sys/capability.h} +\fdecl{cap\_t cap\_get\_proc(void)} +\fdesc{Legge le \textit{capabilities} del processo corrente.} +} + +{La funzione ritorna un \textit{capability state} in caso di successo e + \val{NULL} per un errore, nel qual caso \var{errno} assumerà i valori + \errval{EINVAL}, \errval{EPERM} o \errval{ENOMEM} nel loro significato + generico.} +\end{funcproto} + +La funzione legge il valore delle \textit{capabilities} associate al processo +da cui viene invocata, restituendo il risultato tramite il puntatore ad un +\textit{capability state} contenente tutti i dati che provvede ad allocare +autonomamente e che di nuovo occorrerà liberare con \func{cap\_free} quando +non sarà più utilizzato. + +Se invece si vogliono leggere le \textit{capabilities} di un processo +specifico occorre usare la funzione \funcd{cap\_get\_pid}, il cui +prototipo\footnote{su alcune pagine di manuale la funzione è descritta con un + prototipo sbagliato, che prevede un valore di ritorno di tipo \type{cap\_t}, + ma il valore di ritorno è intero, come si può verificare anche dalla + dichiarazione della stessa in \headfile{sys/capability.h}.} è: + +\begin{funcproto}{ +\fhead{sys/capability.h} +\fdecl{cap\_t cap\_get\_pid(pid\_t pid)} +\fdesc{Legge le \textit{capabilities} di un processo.} +} + +{La funzione ritorna un \textit{capability state} in caso di successo e + \val{NULL} per un errore, nel qual caso \var{errno} assumerà i valori + \errval{ESRCH} o \errval{ENOMEM} nel loro significato generico. } +\end{funcproto} + +La funzione legge il valore delle \textit{capabilities} del processo indicato +con l'argomento \param{pid}, e restituisce il risultato tramite il puntatore +ad un \textit{capability state} contenente tutti i dati che provvede ad +allocare autonomamente e che al solito deve essere disallocato con +\func{cap\_free}. Qualora il processo indicato non esista si avrà un errore di +\errval{ESRCH}. Gli stessi valori possono essere letti direttamente nel +filesystem \textit{proc}, nei file \texttt{/proc//status}; ad esempio per +\texttt{init} si otterrà qualcosa del tipo: +\begin{Console} +piccardi@hain:~/gapil$ \textbf{cat /proc/1/status} +... +CapInh: 0000000000000000 +CapPrm: 00000000fffffeff +CapEff: 00000000fffffeff +... +\end{Console} +%$ + +\itindend{capability~state} + +Infine per impostare le \textit{capabilities} del processo corrente (nella +bozza dello standard POSIX.1e non esiste una funzione che permetta di cambiare +le \textit{capabilities} di un altro processo) si deve usare la funzione +\funcd{cap\_set\_proc}, il cui prototipo è: + +\begin{funcproto}{ +\fhead{sys/capability.h} +\fdecl{int cap\_set\_proc(cap\_t cap\_p)} +\fdesc{Imposta le \textit{capabilities} del processo corrente.} +} + +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual + caso \var{errno} assumerà i valori: + \begin{errlist} + \item[\errcode{EPERM}] si è cercato di attivare una capacità non permessa. + \end{errlist} ed inoltre \errval{EINVAL} nel suo significato generico.} +\end{funcproto} + +La funzione modifica le \textit{capabilities} del processo corrente secondo +quanto specificato con l'argomento \param{cap\_p}, posto che questo sia +possibile nei termini spiegati in precedenza (non sarà ad esempio possibile +impostare capacità non presenti nell'insieme di quelle permesse). + +In caso di successo i nuovi valori saranno effettivi al ritorno della +funzione, in caso di fallimento invece lo stato delle capacità resterà +invariato. Si tenga presente che \textsl{tutte} le capacità specificate +tramite \param{cap\_p} devono essere permesse; se anche una sola non lo è la +funzione fallirà, e per quanto appena detto, lo stato delle +\textit{capabilities} non verrà modificato (neanche per le parti eventualmente +permesse). + +Oltre a queste funzioni su Linux sono presenti due ulteriori funzioni, +\funcm{capgetp} e \funcm{capsetp}, che svolgono un compito analogo. Queste +funzioni risalgono alla implementazione iniziale delle \textit{capabilities} +ed in particolare \funcm{capsetp} consentirebbe anche, come possibile in quel +caso, di cambiare le capacità di un altro processo. Le due funzioni oggi sono +deprecate e pertanto eviteremo di trattarle, per chi fosse interessato si +rimanda alla lettura della loro pagina di manuale. + +Come esempio di utilizzo di queste funzioni nei sorgenti allegati alla guida +si è distribuito il programma \texttt{getcap.c}, che consente di leggere le +\textit{capabilities} del processo corrente\footnote{vale a dire di sé stesso, + quando lo si lancia, il che può sembrare inutile, ma serve a mostrarci quali + sono le \textit{capabilities} standard che ottiene un processo lanciato + dalla riga di comando.} o tramite l'opzione \texttt{-p}, quelle di un +processo qualunque il cui \ids{PID} viene passato come parametro dell'opzione. + +\begin{figure}[!htbp] + \footnotesize \centering + \begin{minipage}[c]{\codesamplewidth} + \includecodesample{listati/getcap.c} + \end{minipage} + \normalsize + \caption{Corpo principale del programma \texttt{getcap.c}.} + \label{fig:proc_getcap} +\end{figure} + +La sezione principale del programma è riportata in fig.~\ref{fig:proc_getcap}, +e si basa su una condizione sulla variabile \var{pid} che se si è usato +l'opzione \texttt{-p} è impostata (nella sezione di gestione delle opzioni, +che si è tralasciata) al valore del \ids{PID} del processo di cui si vuole +leggere le \textit{capabilities} e nulla altrimenti. Nel primo caso +(\texttt{\small 1-6}) si utilizza (\texttt{\small 2}) \func{cap\_get\_proc} +per ottenere lo stato delle capacità del processo, nel secondo (\texttt{\small + 7-13}) si usa invece \func{cap\_get\_pid} (\texttt{\small 8}) per leggere +il valore delle capacità del processo indicato. + +Il passo successivo è utilizzare (\texttt{\small 15}) \func{cap\_to\_text} per +tradurre in una stringa lo stato, e poi (\texttt{\small 16}) stamparlo; infine +(\texttt{\small 18-19}) si libera la memoria allocata dalle precedenti +funzioni con \func{cap\_free} per poi ritornare dal ciclo principale della +funzione. + +\itindend{capabilities} + +% TODO vedi http://lwn.net/Articles/198557/ e +% http://www.madore.org/~david/linux/newcaps/ + + + + +\subsection{La gestione del \textit{Secure Computing}.} +\label{sec:procadv_seccomp} + +\itindbeg{secure~computing~mode} + +Il \textit{secure computing mode} è un meccanismo ideato per fornire un +supporto per l'esecuzione di codice esterno non fidato e non verificabile a +scopo di calcolo. L'idea era quella di disporre di una modalità di esecuzione +dei programmi che permettesse di vendere la capacità di calcolo della propria +macchina ad un qualche servizio di calcolo distribuito, senza comprometterne +la sicurezza eseguendo codice non sotto il proprio controllo. + +La prima versione del meccanismo è stata introdotta con il kernel +2.6.23,\footnote{e disponibile solo avendo abilitato il supporto nel kernel + con l'opzione di configurazione \texttt{CONFIG\_SECCOMP}.} è molto semplice, +il \textit{secure computing mode} viene attivato con \func{prctl} usando +l'opzione \const{PR\_SET\_SECCOMP}, ed indicando \const{SECCOMP\_MODE\_STRICT} +come valore per \param{arg2} (all'epoca unico valore possibile). Una volta +abilitato in questa modalità (in seguito denominata \textit{strict mode}) il +processo o il \textit{thread} chiamante potrà utilizzare soltanto un insieme +estremamente limitato di \textit{system call}: \func{read}, \func{write}, +\func{\_exit} e \funcm{sigreturn}; l'esecuzione di qualsiasi altra +\textit{system call} comporta l'emissione di un \signal{SIGKILL} e conseguente +terminazione immediata del processo. + +Si tenga presente che in questo caso, con versioni recenti della \acr{glibc} +(il comportamento è stato introdotto con la 2.3), diventa impossibile usare +anche \func{\_exit} in \textit{strict mode}, in quanto questa funzione viene +intercettata ed al suo posto viene chiamata \func{exit\_group} (vedi +sez.~\ref{sec:pthread_management}) che non è consentita e comporta un +\signal{SIGKILL}. + +Si tenga presente che, non essendo \func{execve} fra le funzioni permesse, per +poter eseguire un programma terzo essendo in \textit{strict mode} questo dovrà +essere fornito in una forma di codice interpretabile fornito attraverso un +socket o una \textit{pipe}, creati prima di lanciare il processo che eseguirà +il codice non fidato. + + +% TODO a partire dal kernel 3.5 è stato introdotto la possibilità di usare un +% terzo argomento se il secondo è SECCOMP_MODE_FILTER, vedi +% Documentation/prctl/seccomp_filter.txt +% vedi anche http://lwn.net/Articles/600250/ + +% TODO documentare PR_SET_SECCOMP introdotto a partire dal kernel 3.5. Vedi: +% * Documentation/prctl/seccomp_filter.txt +% * http://lwn.net/Articles/475043/ + +% TODO a partire dal kernel 3.17 è stata introdotta la nuova syscall seccomp, +% vedi http://lwn.net/Articles/600250/ e http://lwn.net/Articles/603321/ + + +\itindend{secure~computing~mode} + +\subsection{Altre funzionalità di sicurezza.} +\label{sec:procadv_security_misc} + +Oltre alle funzionalità specifiche esaminate nelle sezioni precedenti, il +kernel supporta una varietà di ulteriori impostazioni di sicurezza, +accessibili nelle maniere più varie, che abbiamo raccolto in questa sezione. + +Una serie di modalità di sicurezza sono attivabili a richiesta attraverso +alcune opzioni di controllo attivabili via \func{sysctl} o il filesystem +\texttt{/proc}, un elenco delle stesse e dei loro effetti è il seguente: + +\begin{basedescript}{\desclabelwidth{1cm}\desclabelstyle{\nextlinelabel}} +\item[\sysctlrelfiled{fs}{protected\_hardlinks}] Un valore nullo, il default, + mantiene il comportamento standard che non pone restrizioni alla creazione + di \textit{hard link}. Se il valore viene posto ad 1 vengono invece attivate + una serie di restrizioni protettive, denominate + \itindex{protected~hardlinks} \textit{protected hardlinks}, che se non + soddisfatte causano il fallimento di \func{link} con un errore di + \errval{EPERM}. Perché questo non avvenga almeno una delle seguenti + condizioni deve essere soddisfatta: + \begin{itemize*} + \item il chiamante deve avere privilegi amministrativi (la + \textit{capability} \const{CAP\_FOWNER}). In caso di utilizzo + dell'\textit{user namespace} oltre a possedere \const{CAP\_FOWNER} è + necessario che l'\ids{UID} del proprietario del file sia mappato nel + \textit{namespace}. + \item il \textit{filesystem} \ids{UID} del chiamante (normalmente + equivalente all'\ids{UID} effettivo) deve corrispondere a quello del + proprietario del file a cui si vuole effettuare il collegamento. + \item devono essere soddisfatte tutte le seguenti condizioni: + \begin{itemize*} + \item il file è un file ordinario + \item il file non ha il \acr{suid} bit attivo + \item il file non ha lo \acr{sgid} bit attivo ed il permesso di esecuzione + per il gruppo + \item il chiamante ha i permessi di lettura e scrittura sul file + \end{itemize*} + \end{itemize*} + + In sostanza in questo caso un utente potrà creare un collegamento diretto ad + un altro file solo se ne è il proprietario o se questo è un file ordinario + senza permessi speciali ed a cui ha accesso in lettura e scrittura. + + Questa funzionalità fornisce una protezione generica che non inficia l'uso + ordinario di \func{link}, ma rende impraticabili una serie di possibili + abusi della stessa; oltre ad impedire l'uso di un \textit{hard link} come + variante in un attacco di \textit{symlink race} (eludendo i + \textit{protected symlinks} di cui al punto successivo), evita anche che si + possa lasciare un riferimento ad un eventuale programma \acr{suid} + vulnerabile, creando un collegamento diretto allo stesso. + + +\item[\sysctlrelfiled{fs}{protected\_symlinks}] Un valore nullo, il default, + mantiene il comportamento standard che non pone restrizioni nel seguire i + link simbolici. Se il valore viene posto ad 1 vengono attivate delle + restrizioni protettive, denominate \itindex{protected~symlinks} + \textit{protected symlinks}. Quando vengono attivate una qualunque funzione + che esegua la risoluzione di un \textit{pathname} contenente un link + simbolico non conforme alle restrizioni fallirà con un errore di + \errval{EACCESS}. Per evitare l'errore deve essere soddisfatta una delle + seguenti condizioni: + \begin{itemize*} + \item il link non è in una directory con permessi analoghi a \file{/tmp} + (scrivibile a tutti e con lo \textit{sticky bit} attivo); + \item il link è in una directory con permessi analoghi a \file{/tmp} ma è + soddisfatta una delle condizioni seguenti: + \begin{itemize*} + \item il link simbolico appartiene al chiamante: il controllo viene fatto + usando il \textit{filesystem} \ids{UID} (che normalmente corrisponde + all'\ids{UID} effettivo). + \item il link simbolico ha lo stesso proprietario della directory. + \end{itemize*} + \end{itemize*} + + Questa funzionalità consente di rendere impraticabili alcuni attacchi in cui + si approfitta di una differenza di tempo fra il controllo e l'uso di un + file, ed in particolare quella classe di attacchi viene usualmente chiamati + \textit{symlink attack},\footnote{si tratta di un sottoinsieme di quella + classe di attacchi chiamata genericamente \textit{TOCTTOU}, acronimo + appunto di \textit{Time of check to time of use}.} di cui abbiamo parlato + in sez.~\ref{sec:file_temp_file}. + + Un possibile esempio di questo tipo di attacco è quello contro un programma + che viene eseguito per conto di un utente privilegiato (ad esempio un + programma con il \acr{suid} o lo \acr{sgid} bit attivi) che prima controlla + l'esistenza di un file e se non esiste lo crea. Se questa procedura, che è + tipica della creazione di file temporanei sotto \file{/tmp}, non viene + eseguita in maniera corretta,\footnote{ad esempio con le modalità che + abbiamo trattato in sez.~\ref{sec:file_temp_file}, che per quanto note da + tempo continuano ad essere ignorate.} un attaccante ha una finestra di + tempo in cui può creare prima del programma un \textit{link simbolico} ad un + file di sua scelta, compresi file di dispositivo o file a cui non avrebbe + accesso, facendolo poi utilizzare al programma. + + Attivando la funzionalità si rende impossibile seguire un link simbolico in + una directory temporanea come \texttt{/tmp}, a meno che questo non sia di + proprietà del chiamante, o che questo non appartenga al proprietario della + directory. Questo impedisce che i link simbolici creati da un attaccante + possano essere seguiti da un programma privilegiato (perché apparterranno + all'attaccante) mentre quelli creati dall'amministratore (che i genere è il + proprietario di \texttt{/tmp}) saranno seguiti comunque. + +\end{basedescript} + + +% TODO: trattare pure protected_regular e protected_fifos introdotti con il +% 4.19 (vedi https://lwn.net/Articles/763106/) + + + +% TODO: trattare keyctl (man 2 keyctl) + + + +% TODO trattare le funzioni di protezione della memoria pkey_alloc, pkey_free, +% pkey_mprotect, introdotte con il kernel 4.8, vedi +% http://lwn.net/Articles/689395/ e Documentation/x86/protection-keys.txt \section{Funzioni di gestione e controllo} \label{sec:proc_manage_control} -In questa sezione prenderemo in esame alcune specifice \textit{system call} -dedicate al controllo processi sia per quanto riguarda l'impostazione di +In questa sezione prenderemo in esame alcune specifiche \textit{system call} +dedicate al controllo dei processi sia per quanto riguarda l'impostazione di caratteristiche specialistiche, che per quanto riguarda l'analisi ed il controllo della loro esecuzione. @@ -25,7 +1504,7 @@ controllo della loro esecuzione. Benché la gestione ordinaria dei processi possa essere effettuata attraverso le funzioni che abbiamo già esaminato nei capitoli \ref{cha:process_interface} e \ref{cha:process_handling}, esistono una serie di proprietà e -caratteristiche specifiche dei proecessi per la cui gestione è stata +caratteristiche specifiche dei processi per la cui gestione è stata predisposta una apposita \textit{system call} che fornisce una interfaccia generica per tutte le operazioni specialistiche. La funzione di sistema è \funcd{prctl} ed il suo prototipo è:\footnote{la funzione non è standardizzata @@ -213,8 +1692,8 @@ Introdotta a partire dal kernel 2.4.21, solo su PowerPC. ``\textit{tracer process}''. Questa è una funzionalità fornita da \textit{``Yama''}, uno specifico \textit{Linux Security Modules}, e serve a consentire al processo indicato, quando le restrizioni introdotte da questo - modulo sono attive, di usare \func{ptrace}\unavref{ (vedi - sez.\ref{sec:process_ptrace})} sul processo chiamante, anche se quello + modulo sono attive, di usare \func{ptrace} (vedi + sez.~\ref{sec:process_ptrace}) sul processo chiamante, anche se quello indicato non ne è un progenitore. Il valore \constd{PR\_SET\_PTRACER\_ANY} consente a tutti i processi l'uso di \func{ptrace}. L'uso si \textit{Yama} attiene alla gestione della sicurezza dei processi, e consente di introdurre @@ -223,44 +1702,29 @@ Introdotta a partire dal kernel 2.4.21, solo su PowerPC. scopo di queste dispense, per i dettagli si consulti la documentazione su \textit{Yama} nei sorgenti del kernel. Introdotta a partire dal kernel 3.4. -\itindbeg{secure~computing~mode} -\item[\constd{PR\_SET\_SECCOMP}] Imposta il cosiddetto \textit{secure computing - mode} per il processo corrente. Prevede come unica possibilità - che \param{arg2} sia impostato ad 1. Una volta abilitato il \textit{secure - computing mode} il processo potrà utilizzare soltanto un insieme - estremamente limitato di \textit{system call}: \func{read}, \func{write}, - \func{\_exit} e \funcm{sigreturn}. Ogni altra \textit{system call} porterà - all'emissione di un \signal{SIGKILL} (vedi sez.~\ref{sec:sig_termination}). - Il \textit{secure computing mode} è stato ideato per fornire un supporto per - l'esecuzione di codice esterno non fidato e non verificabile a scopo di - calcolo;\footnote{lo scopo è quello di poter vendere la capacità di calcolo - della proprio macchina ad un qualche servizio di calcolo distribuito senza - comprometterne la sicurezza eseguendo codice non sotto il proprio - controllo.} in genere i dati vengono letti o scritti grazie ad un socket o - una \textit{pipe}, e per evitare problemi di sicurezza non sono possibili - altre operazioni se non quelle citate. Introdotta a partire dal kernel - 2.6.23, disponibile solo se si è abilitato il supporto nel kernel con - \texttt{CONFIG\_SECCOMP}. - -% TODO a partire dal kernel 3.5 è stato introdotto la possibilità di usare un -% terzo argomento se il secondo è SECCOMP_MODE_FILTER, vedi -% Documentation/prctl/seccomp_filter.txt -% vedi anche http://lwn.net/Articles/600250/ - -% TODO documentare PR_SET_SECCOMP introdotto a partire dal kernel 3.5. Vedi: -% * Documentation/prctl/seccomp_filter.txt -% * http://lwn.net/Articles/475043/ - -% TODO a partire dal kernel 3.17 è stata introdotta la nuova syscall seccomp, -% vedi http://lwn.net/Articles/600250/ e http://lwn.net/Articles/603321/ +\item[\constd{PR\_SET\_SECCOMP}] Attiva il \textit{secure computing mode} per + il processo corrente. Introdotta a partire dal kernel 2.6.23 la funzionalità + è stata ulteriormente estesa con il kernel 3.5, salvo poi diventare un + sottoinsieme della \textit{system call} \func{seccomp} a partire dal kernel + 3.17. Prevede che si indichi per \param{arg2} il valore + \const{SECCOMP\_MODE\_STRICT} (unico possibile fino al kernel 2.6.23) per + selezionare il cosiddetto \textit{strict mode} o, dal kernel 3.5, + \const{SECCOMP\_MODE\_FILTER} per usare il \textit{filter mode}. Tratteremo + questa opzione nei dettagli più avanti, in sez.~\ref{sec:procadv_seccomp}, + quando affronteremo l'argomento del \textit{Secure Computing}. \item[\constd{PR\_GET\_SECCOMP}] Ottiene come valore di ritorno della funzione - lo stato corrente del \textit{secure computing mode}, al momento attuale la - funzione è totalmente inutile in quanto l'unico valore ottenibile è 0, dato - che la chiamata di questa funzione in \textit{secure computing mode} - comporterebbe l'emissione di \signal{SIGKILL}, è stata comunque definita per - eventuali estensioni future. Introdotta a partire dal kernel 2.6.23. -\itindend{secure~computing~mode} + lo stato corrente del \textit{secure computing mode}. Fino al kernel 3.5, + quando era possibile solo lo \textit{strict mode}, la funzione era + totalmente inutile in quanto l'unico valore ottenibile era 0 in assenza di + \textit{secure computing}, dato che la chiamata di questa funzione in + \textit{strict mode} avrebbe comportato l'emissione di \signal{SIGKILL} per + il chiamante. La funzione però, a partire dal kernel 2.6.23, era stata + comunque definita per eventuali estensioni future, ed infatti con + l'introduzione del \textit{filter mode} con il kernel 3.5, se essa viene + inclusa nelle funzioni consentite restituisce il valore 2 quando il + \textit{secure computing mode} è attivo (se non inclusa si avrà di nuovo un + \signal{SIGKILL}). \item[\constd{PR\_SET\_SECUREBITS}] Imposta i \textit{securebits} per il processo chiamante al valore indicato da \param{arg2}; per i dettagli sul @@ -296,8 +1760,8 @@ Introdotta a partire dal kernel 2.4.21, solo su PowerPC. generazione di un segnale di \signal{SIGSEGV} (vedi sez.~\ref{sec:sig_prog_error}). La lettura viene automaticamente disabilitata se si attiva il \textit{secure computing mode} (vedi - \const{PR\_SET\_SECCOMP}). Introdotta a partire dal kernel - 2.6.26, solo su x86. + \const{PR\_SET\_SECCOMP} e sez.~\ref{sec:procadv_seccomp}). Introdotta a + partire dal kernel 2.6.26, solo su x86. \item[\constd{PR\_GET\_TSC}] Ottiene il valore del flag che controlla la lettura del contattore dei \textit{timestamp}, salvato all'indirizzo @@ -405,12 +1869,16 @@ Introdotta a partire dal kernel 2.4.21, solo su PowerPC. % TODO documentare ARCH_SET_CPUID e ARCH_GET_CPUID, introdotte con il kernel % 4.12, vedi https://lwn.net/Articles/721182/ + +% TODO documentare PR_SPEC_DISABLE_NOEXEC in 5.1, vedi +% https://lwn.net/Articles/782511/ + \label{sec:prctl_operation} \end{basedescript} -%\subsection{La funzione \func{ptrace}} -%\label{sec:process_ptrace} +\subsection{La funzione \func{ptrace}} +\label{sec:process_ptrace} %Da fare @@ -422,6 +1890,14 @@ Introdotta a partire dal kernel 2.4.21, solo su PowerPC. % TODO: trattare PTRACE_O_SUSPEND_SECCOMP, aggiunta con il kernel 4.3, vedi % http://lwn.net/Articles/656675/ +\subsection{La funzione \func{kcmp}} +\label{sec:process_kcmp} + +% TODO: trattare kcmp aggiunta con il kernel 3.5, vedi +% https://lwn.net/Articles/478111/ +% vedi man kcmp e man 2 open + + \section{La gestione avanzata della creazione dei processi} \label{sec:process_adv_creation} @@ -429,7 +1905,7 @@ Introdotta a partire dal kernel 2.4.21, solo su PowerPC. In questa sezione tratteremo le funzionalità avanzate relative alla creazione dei processi e del loro ambiente, sia per quanto riguarda l'utilizzo delle stesse per la creazione dei \textit{thread} che per la gestione dei -\textit{namespace} che sono alla base dei cosidetti \textit{container}. +\textit{namespace} che sono alla base dei cosiddetti \textit{container}. \subsection{La \textit{system call} \func{clone}} @@ -465,6 +1941,9 @@ si intende creare un \textit{thread}. L'esecuzione del programma creato da \func{sys\_clone} riprende, come per \func{fork}, da dopo l'esecuzione della stessa. +% TODO trattare anche clone3 (vedi https://lwn.net/Articles/792628/), aggiunta +% con il kernel 5.3 + La necessità di avere uno \textit{stack} alternativo c'è solo quando si intende creare un \textit{thread}, in tal caso infatti il nuovo \textit{task} vede esattamente la stessa memoria del \textit{task} @@ -606,10 +2085,10 @@ elenco, che illustra quelle attualmente disponibili:\footnote{si fa informazioni, che saranno così indipendenti per i due processi, come avviene nel comportamento ordinario di un sistema unix-like. -\item[\constd{CLONE\_IO}] se questo flag viene impostato il nuovo il nuovo - processo condividerà con il padre il contesto dell'I/O, altrimenti, come - come avviene nel comportamento ordinario con una \func{fork} otterrà un suo - contesto dell'I/O. +\item[\constd{CLONE\_IO}] se questo flag viene impostato il nuovo processo + condividerà con il padre il contesto dell'I/O, altrimenti, come avviene nel + comportamento ordinario con una \func{fork} otterrà un suo contesto + dell'I/O. Il contesto dell'I/O viene usato dagli \textit{scheduler} di I/O (visti in sez.~\ref{sec:io_priority}) e se questo è lo stesso per diversi processi @@ -647,6 +2126,9 @@ elenco, che illustra quelle attualmente disponibili:\footnote{si fa \item[\constd{CLONE\_PARENT\_SETTID}] \item[\constd{CLONE\_PID}] +% TODO trattare CLONE_PIDFD introdotto con il kernel 5.2, vedi +% https://lwn.net/Articles/787963/ e anche https://lwn.net/Articles/789023/ + \item[\constd{CLONE\_PTRACE}] se questo flag viene impostato ed il processo chiamante viene tracciato (vedi sez.~\ref{sec:process_ptrace}) anche il figlio viene tracciato. @@ -712,29 +2194,18 @@ degli altri gruppi, che costituisce poi quello che viene chiamato un % http://lwn.net/Articles/531498/ -\section{La gestione avanzata della sicurezza} -\label{sec:process_security} - -Tratteremo in questa sezione le funzionalità più avanzate relative alla -gestione della sicurezza, a partire dalle \textit{capabilities} e dalle -funzionalità di \textit{Secure Computing}, fino alle funzionalità relative -alla gestione delle chiavi crittografiche. - - -% TODO: trattare keyctl (man 2 keyctl) - -% TODO trattare le funzioni di protezione della memoria pkey_alloc, pkey_free, -% pkey_mprotect, introdotte con il kernel 4.8, vedi -% http://lwn.net/Articles/689395/ e Documentation/x86/protection-keys.txt - -%TODO trattare kcmp aggiunta con il kernel 3.5, vedi -% https://lwn.net/Articles/478111/ - \section{Funzionalità avanzate e specialistiche} \label{sec:process_special} +% TODO: trattare userfaultfd, introdotta con il 4.23, vedi +% http://man7.org/linux/man-pages/man2/userfaultfd.2.html + +% TODO: trattare process_vm_readv/process_vm_writev introdotte con il kernel +% 3.2, vedi http://man7.org/linux/man-pages/man2/process_vm_readv.2.html e i +% precedenti tentativi https://lwn.net/Articles/405346/ + \subsection{La gestione delle operazioni in virgola mobile} \label{sec:process_fenv} @@ -794,3 +2265,40 @@ Da fare %%% mode: latex %%% TeX-master: "gapil" %%% End: + +% LocalWords: system call namespace prctl IRIX kernel sys int option long +% LocalWords: unsigned arg errno EACCESS EBADF EBUSY EFAULT EINVAL ENXIO PR +% LocalWords: EOPNOTSUPP EPERM CAPBSET READ capability sez tab capabilities +% LocalWords: bounding CAP SETPCAP DUMPABLE dump suid sgid UID DISABLE GET +% LocalWords: ENDIAN endianness BIG big endian LITTLE little PPC PowerPC ia +% LocalWords: FPEMU NOPRINT SIGFPE FPEXC point exception FP EXC SW ENABLE +% LocalWords: OVF overflow UND underflow RES INV DISABLED NONRECOV ASYNC AO +% LocalWords: KEEPCAPS pag exec SECURE KEEP CAPS securebits LOCKED NAME NUL +% LocalWords: char PDEATHSIG SIGCHLD fork PTRACER PID tracer process ptrace +% LocalWords: Security Modules ANY Yama SECCOMP secure computing seccomp vm +% LocalWords: STRICT strict FILTER filter SIGKILL TIMING STATISTICAL TSC fn +% LocalWords: TIMESTAMP timestamp Stamp Counter SIGSEGV UNALIGN SIGBUS MCE +% LocalWords: KILL siginfo MCEERR memory failure early kill CLEAR child cap +% LocalWords: reaper SUBREAPER init value result thread like flags stack FS +% LocalWords: race condition malloc NULL copy write glibc vsyscall sched RT +% LocalWords: void pid ptid struct desc tls ctid EAGAIN ENOMEM exit Posix +% LocalWords: Library PARENT SETTID SETTLS TID CLEARTID futex FILES table +% LocalWords: descriptor umask dell'I scheduler SIGHAND STOPPED SYSVSEM IPC +% LocalWords: UNTRACED VFORK vfork mount filesystem LSM Mandatory Access fs +% LocalWords: Control DAC MAC SELinux Smack Tomoyo AppArmor Discrectionary +% LocalWords: permitted inheritable effective fig security ADMIN forced new +% LocalWords: allowed dall' bound MODULE nell' all' capset sendmail SETGID +% LocalWords: setuid orig IMMUTABLE MKNOD OVERRIDE SEARCH CHOWN FSETID LOCK +% LocalWords: FOWNER saved FIXUP NOROOT AUDIT BLOCK SUSPEND SETFCAP group +% LocalWords: socket domain locking mlock mlockall shmctl mmap OWNER LEASE +% LocalWords: lease immutable append only mknod BIND SERVICE BROADCAST RAW +% LocalWords: broadcast multicast PACKET CHROOT chroot NICE PACCT RAWIO TTY +% LocalWords: accounting ioperm iopl RESOURCE CONFIG hangup vhangup SYSLOG +% LocalWords: WAKE ALARM CLOCK BOOTTIME REALTIME sticky NOATIME fcntl swap +% LocalWords: multicasting dell'IPC SysV trusted IOPRIO CLASS IDLE lookup +% LocalWords: scheduling dcookie NEWNS unshare nice NUMA ioctl journaling +% LocalWords: ext capget header hdrp datap const ESRCH SOURCE undef version +% LocalWords: libcap lcap obj to text dup clear DIFFERS get ncap caps ssize +% LocalWords: argument length all setpcap from string name proc cat capgetp +% LocalWords: capsetp getcap read sigreturn sysctl protected hardlinks tmp +% LocalWords: dell' symlink symlinks pathname TOCTTOU of