X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=filedir.tex;h=eca8d1d3be2bbdadad35813fb41b710432826314;hp=b15c5f098b3216c6b5539cb3aea5447d3b19a12f;hb=b2f11dd799533d64d84745204477831f9c1966ae;hpb=cea0c7d2a609e9de68fef7bb114e2d4c0a95f70e diff --git a/filedir.tex b/filedir.tex index b15c5f0..eca8d1d 100644 --- a/filedir.tex +++ b/filedir.tex @@ -2730,6 +2730,737 @@ scopi di sicurezza, che sono state introdotte nelle versioni pi Linux. +\subsection{La gestione delle \textit{capabilities}} +\label{sec:proc_capabilities} + +\itindbeg{capabilities} + +Come accennato in sez.~\ref{sec:proc_access_id} l'architettura classica della +gestione dei privilegi in un sistema unix-like ha il sostanziale problema di +fornire all'amministratore dei poteri troppo ampi, questo comporta che anche +quando si siano predisposte delle misure di protezione per in essere in grado +di difendersi dagli effetti di una eventuale compromissione del +sistema,\footnote{come montare un filesystem in sola lettura per impedirne + modifiche, o marcare un file come immutabile.} una volta che questa sia +stata effettuata e si siano ottenuti i privilegi di amministratore, queste +potranno essere comunque rimosse.\footnote{nei casi elencati nella precedente + nota si potrà sempre rimontare il sistema in lettura-scrittura, o togliere + la marcatura di immutabilità.} + +Il problema consiste nel fatto che nell'architettura tradizionale di un +sistema unix-like i controlli di accesso sono basati su un solo livello di +separazione: per i processi normali essi sono posti in atto, mentre per i +processi con i privilegi di amministratore essi non vengono neppure eseguiti; +per questo motivo non era previsto alcun modo per evitare che un processo con +diritti di amministratore non potesse eseguire certe operazioni, o per cedere +definitivamente alcuni privilegi da un certo momento in poi. + +Per ovviare a tutto ciò, a partire dai kernel della serie 2.2, è stato +introdotto un meccanismo, detto \textit{capabilities}, che consentisse di +suddividere i vari privilegi tradizionalmente associati all'amministratore in +un insieme di \textsl{capacità} distinte. L'idea era che queste capacità +potessero essere abilitate e disabilitate in maniera indipendente per ciascun +processo con privilegi di amministratore, permettendo così una granularità +molto più fine nella distribuzione degli stessi che evitasse la originaria +situazione di \textsl{tutto o nulla}. + +Il meccanismo completo delle \textit{capabilities}\footnote{l'implementazione + di Linux si rifà ad una bozza per quello che dovrebbe divenire lo standard + POSIX.1e, che prevede questa funzionalità.} prevederebbe anche la +possibilità di associare le stesse \textit{capabilities} anche ai singoli file +eseguibili,\footnote{una descrizione sommaria di questa funzionalità è + riportata nella pagina di manuale che descrive l'implementazione delle + \textit{capabilities} con Linux (accessibile con \texttt{man capabilities}), + ma non essendo implementata non ne tratteremo qui.} in modo da poter +stabilire quali capacità possono essere utilizzate quando viene messo in +esecuzione uno specifico programma; attualmente però questa funzionalità non è +implementata.\footnote{per attualmente si intende fino al kernel 2.6.23; + benché l'infrastruttura per crearla sia presente (vedi anche + sez.~\ref{sec:file_xattr}) finora non è disponibile nessuna realizzazione + delle specifiche POSIX.1e, esistono però dei patch di sicurezza del kernel, + come LIDS (vedi \href{http://www.lids.org}{\textsf{http://www.lids.org/})} + che realizzano qualcosa di simile.} + +% TODO verificare per process capability bounding set, vedi: +% http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=3b7391de67da515c91f48aa371de77cb6cc5c07e + +% TODO capire cosa cambia con i patch del 2.6.26, vedi +% http://lwn.net/Articles/280279/ + +\begin{table}[!h!btp] + \centering + \footnotesize + \begin{tabular}{|l|p{12cm}|} + \hline + \textbf{Capacità}&\textbf{Descrizione}\\ + \hline + \hline +% +% POSIX-draft defined capabilities. +% + \const{CAP\_CHOWN} & La capacità di cambiare proprietario e gruppo + proprietario di un file (vedi + sez.~\ref{sec:file_ownership_management}).\\ + \const{CAP\_DAC\_OVERRIDE}& La capacità di evitare il controllo dei + permessi di lettura, scrittura ed esecuzione dei + file, (vedi sez.~\ref{sec:file_access_control}) + caratteristici del modello classico del + controllo di accesso chiamato + \itindex{Discrectionary~Access~Control~(DAC)} + \textit{Discrectionary Access Control} (da cui + il nome DAC).\\ + \const{CAP\_DAC\_READ\_SEARCH}& La capacità di evitare il controllo dei + permessi di lettura, scrittura ed esecuzione per + le directory (vedi + sez.~\ref{sec:file_access_control}).\\ + \const{CAP\_FOWNER} & La capacità di evitare il controllo che + l'user-ID effettivo del processo (o meglio il + \textit{filesystem user-ID}, vedi + sez.~\ref{sec:proc_setuid}) coincida con + quello del proprietario di un file per tutte + le operazioni privilegiate non coperte dalle + precedenti \const{CAP\_DAC\_OVERRIDE} e + \const{CAP\_DAC\_READ\_SEARCH}. Queste + comprendono i cambiamenti dei permessi e dei + tempi del file (vedi + sez.~\ref{sec:file_perm_management} e + sez.~\ref{sec:file_file_times}), le impostazioni + degli attributi estesi (con il comando + \cmd{chattr}) e delle ACL, poter ignorare lo + \itindex{sticky~bit} \textit{sticky bit} nella + cancellazione dei file (vedi + sez.~\ref{sec:file_special_perm}), la possibilità + di impostare il flag di \const{O\_NOATIME} con + \func{open} e \func{fcntl} (vedi + sez.~\ref{sec:file_open} e + sez.~\ref{sec:file_fcntl}).\\ + \const{CAP\_FSETID} & La capacità di evitare la cancellazione + automatica dei bit \itindex{suid~bit} \acr{suid} + e \itindex{sgid~bit} \acr{sgid} quando un file + per i quali sono impostati viene modificato da + un processo senza questa capacità e la capacità + di impostare il bit \acr{sgid} su un file anche + quando questo è relativo ad un gruppo cui non si + appartiene (vedi + sez.~\ref{sec:file_perm_management}).\\ + \const{CAP\_KILL} & La capacità di mandare segnali a qualunque + processo (vedi sez.~\ref{sec:sig_kill_raise}).\\ + \const{CAP\_SETGID} & La capacità di manipolare i group ID dei + processi, sia il principale che i supplementari, + (vedi sez.~\ref{sec:proc_setgroups} che quelli + trasmessi tramite i socket \textit{unix domain} + (vedi sez.~\ref{sec:unix_socket}).\\ + \const{CAP\_SETUID} & La capacità di manipolare gli user ID del + processo (con \func{setuid}, \func{setreuid}, + \func{setresuid}, \func{setfsuid}) e di + trasmettere un valore arbitrario + dell'\textsl{uid} nel passaggio delle + credenziali coi socket \textit{unix domain} (vedi + sez.~\ref{sec:unix_socket}).\\ +% +% Linux specific capabilities +% +\hline + \const{CAP\_SETPCAP} & La capacità di impostare o rimuovere una capacità + (limitatamente a quelle che il processo + chiamante ha nel suo insieme di capacità + permesse) da qualunque processo.\\ +% TODO cambiata nel 2.4.24 rc1 ? + \const{CAP\_LINUX\_IMMUTABLE}& La capacità di impostare gli attributi + \textit{immutable} e \itindex{append~mode} + \textit{append only} per i file su un + filesystem che supporta questi + attributi estesi.\\ + \const{CAP\_NET\_BIND\_SERVICE}& La capacità di porre in ascolto server + su porte riservate (vedi + sez.~\ref{sec:TCP_func_bind}).\\ + \const{CAP\_NET\_BROADCAST}& La capacità di consentire l'uso di socket in + \itindex{broadcast} \textit{broadcast} e + \itindex{multicast} \textit{multicast}.\\ + \const{CAP\_NET\_ADMIN} & La capacità di eseguire alcune operazioni + privilegiate sulla rete (impostare le opzioni + privilegiate dei socket, abilitare il + \itindex{multicast} \textit{multicasting}, + impostare interfacce di rete e + tabella di instradamento).\\ + \const{CAP\_NET\_RAW} & La capacità di usare socket \texttt{RAW} e + \texttt{PACKET} (quelli che permettono di creare + pacchetti nei protocolli di basso livello).\\ + \const{CAP\_IPC\_LOCK} & La capacità di effettuare il \textit{memory + locking} \itindex{memory~locking} con le + funzioni \func{mlock}, \func{mlockall}, + \func{shmctl}, \func{mmap} (vedi + sez.~\ref{sec:proc_mem_lock} e + sez.~\ref{sec:file_memory_map}). \\ + \const{CAP\_IPC\_OWNER} & La capacità di evitare il controllo dei permessi + per le operazioni sugli oggetti di + intercomunicazione fra processi (vedi + sez.~\ref{sec:ipc_sysv}).\\ + \const{CAP\_SYS\_MODULE}& La capacità di caricare e rimuovere moduli del + kernel. \\ + \const{CAP\_SYS\_RAWIO} & La capacità di eseguire operazioni sulle porte + di I/O con \func{ioperm} e \func{iopl} (vedi + sez.~\ref{sec:file_io_port}).\\ + \const{CAP\_SYS\_CHROOT}& La capacità di eseguire la funzione + \func{chroot} (vedi + sez.~\ref{sec:file_chroot}).\\ + \const{CAP\_SYS\_PTRACE}& Consente di tracciare qualunque processo con + \func{ptrace} (vedi + sez.~\ref{sec:xxx_ptrace}).\\ + \const{CAP\_SYS\_PACCT} & La capacità di usare le funzioni di + \textit{accounting} dei processi (vedi + sez.~\ref{sec:sys_bsd_accounting}).\\ + \const{CAP\_SYS\_ADMIN} & La capacità di eseguire una serie di compiti + amministrativi (come impostare le quote, + attivare e disattivare la swap, montare, + rimontare e smontare filesystem, ecc.). \\ + \const{CAP\_SYS\_BOOT} & La capacità di fare eseguire un riavvio del + sistema.\\ +% TODO trattare reboot e kexec + \const{CAP\_SYS\_NICE} & La capacità di modificare le priorità dei + processi (vedi sez.~\ref{sec:proc_priority}). \\ + \const{CAP\_SYS\_RESOURCE}& La capacità di superare le limitazioni sulle + risorse, aumentare le quote disco, usare lo + spazio disco riservato all'amministratore.\\ + \const{CAP\_SYS\_TIME} & La capacità di modificare il tempo di sistema + (vedi sez.~\ref{sec:sys_time}).\\ + \const{CAP\_SYS\_TTY\_CONFIG}& La capacità di simulare un \textit{hangup} + della console, con la funzione + \func{vhangup}.\\ + \const{CAP\_MKNOD} & La capacità di creare file di dispositivo con la + funzione \func{mknod} (vedi + sez.~\ref{sec:file_mknod}).\footnotemark\\ + \const{CAP\_LEASE} & La capacità di creare dei \textit{file lease} + \index{file!lease} su di un file (vedi + sez.~\ref{sec:file_asyncronous_lease}) + indipendentemente dalla proprietà dello + stesso.\footnotemark\\ + \const{CAP\_SETFCAP} & La capacità di impostare le + \textit{capabilities} di un file (non + supportata).\\ + \const{CAP\_AUDIT\_WRITE}&consente la scrittura di dati nel giornale di + auditing del kernel.\\ + \const{CAP\_AUDIT\_CONTROL}& consente di abilitare e disabilitare il + controllo dell'auditing.\footnotemark\\ +% TODO verificare questa roba dell'auditing + \hline + \end{tabular} + \caption{Le costanti che identificano le \textit{capabilities} presenti nel + kernel.} +\label{tab:proc_capabilities} +\end{table} + +\footnotetext[21]{questa capacità è presente soltanto a partire dai kernel + della serie 2.4.x.} + +\footnotetext[22]{questa capacità è presente soltanto a partire dai kernel della + serie 2.4.x.} + +\footnotetext{queste ultime due capacità sono presenti soltanto a partire dai + kernel della serie 2.6.11.} + +Per gestire questo nuovo meccanismo ciascun processo porta con sé tre distinti +insiemi di \textit{capabilities}, che vengono denominati rispettivamente +\textit{effective}, \textit{permitted} ed \textit{inherited}. Questi insiemi +vengono mantenuti in forma di tre diverse maschere binarie,\footnote{il kernel + li mantiene, come i vari identificatori di sez.~\ref{sec:proc_setuid}, + all'interno della \struct{task\_struct} di ciascun processo (vedi + fig.~\ref{fig:proc_task_struct}), nei tre campi \texttt{cap\_effective}, + \texttt{cap\_inheritable}, \texttt{cap\_permitted} del tipo + \texttt{kernel\_cap\_t}; questo è attualmente definito come intero a 32 bit, + il che comporta un massimo di 32 \textit{capabilities} distinte.} in cui +ciascun bit corrisponde ad una capacità diversa; se ne è riportato +l'elenco,\footnote{si tenga presente che l'elenco delle \textit{capabilities} + presentato questa tabella, ripreso dalla relativa pagina di manuale + (accessibile con \texttt{man capabilities}) e dalle definizioni in + \texttt{sys/capabilities.h}, è quello aggiornato al kernel 2.6.6.} con una +breve descrizione, ed il nome delle costanti che identificano i singoli bit, +in tab.~\ref{tab:proc_capabilities}; la tabella è divisa in due parti, la +prima riporta le \textit{capabilities} previste nella bozza dello standard +POSIX1.e, la seconda quelle specifiche di Linux. + +L'utilizzo di tre distinti insiemi serve a fornire una interfaccia flessibile +per l'uso delle \textit{capabilities}, con scopi analoghi a quelli per cui +sono mantenuti i diversi insiemi di identificatori di +sez.~\ref{sec:proc_setuid}; il loro significato è il seguente: +\begin{basedescript}{\desclabelwidth{2.0cm}\desclabelstyle{\nextlinelabel}} +\item[\textit{effective}] l'insieme delle \textit{capabilities} + ``\textsl{effettive}'', cioè di quelle che vengono effettivamente usate dal + kernel quando deve eseguire il controllo di accesso per le varie operazioni + compiute dal processo. +\item[\textit{permitted}] l'insieme delle \textit{capabilities} + ``\textsl{permesse}'', cioè l'insieme di quelle capacità che un processo + \textsl{può} impostare come \textsl{effettive}. Se un processo cancella una + capacità da questo insieme non potrà più riassumerla (almeno che non esegua + un programma che è \acr{suid} di root). +\item[\textit{inherited}] l'insieme delle \textit{capabilities} + ``\textsl{ereditabili}'', cioè quelle che vengono trasmesse ad un nuovo + programma eseguito attraverso una chiamata ad \func{exec} (con l'eccezione + del caso che questo sia \acr{suid} di root). +\label{sec:capabilities_set} +\end{basedescript} + +Oltre a questi tre insiemi, che sono relativi al singolo processo, il kernel +mantiene un insieme generale valido per tutto il sistema, chiamato +\itindex{capabilities~bounding~set} \textit{capabilities bounding set}. Ogni +volta che un programma viene posto in esecuzione con \func{exec} il contenuto +degli insiemi \textit{effective} e \textit{permitted} vengono mascherati con +un \textsl{AND} binario del contenuto corrente del \textit{capabilities + bounding set}, così che il nuovo processo potrà disporre soltanto delle +capacità in esso elencate. + +Il \textit{capabilities bounding set} è un parametro di sistema, accessibile +attraverso il contenuto del file \procfile{/proc/sys/kernel/cap-bound}, che per +questa sua caratteristica consente di impostare un limite generale alle +capacità che possono essere accordate ai vari processi. Questo valore può +essere impostato ad un valore arbitrario esclusivamente dal primo processo +eseguito nel sistema (di norma cioè da \texttt{/sbin/init}), ogni processo +eseguito successivamente (cioè con \textsl{pid} diverso da 1) anche se +eseguito con privilegi di amministratore potrà soltanto rimuovere uno dei bit +già presenti dell'insieme: questo significa che una volta rimossa una +\textit{capability} dal \textit{capabilities bounding set} essa non sarà più +disponibile, neanche per l'amministratore, a meno di un riavvio. + +Quando un programma viene messo in esecuzione\footnote{cioè quando viene + eseguita la \func{execve} con cui lo si lancia; in corrispondenza di una + \func{fork} le \textit{capabilities} non vengono modificate.} esso eredita +(nel senso che assume negli insiemi \textit{effective} e \textit{permitted}) +le \textit{capabilities} mantenute nell'insieme \textit{inherited}, a meno che +non sia eseguito un programma \acr{suid} di root o la \func{exec} sia stata +eseguita da un programma con \textsl{uid} reale zero; in tal caso il programma +ottiene tutte le \textit{capabilities} presenti nel \textit{capabilities + bounding set}. In questo modo si può far si che ad un processo eseguito in +un secondo tempo possano essere trasmesse solo un insieme limitato di +capacità, impedendogli di recuperare quelle assenti nell'insieme +\textit{inherited}. Si tenga presente invece che attraverso una \func{fork} +vengono mantenute le stesse capacità del processo padre. + +Per la gestione delle \textit{capabilities} il kernel mette a disposizione due +funzioni che permettono rispettivamente di leggere ed impostare i valori dei +tre insiemi illustrati in precedenza. Queste due funzioni sono \funcd{capget} +e \funcd{capset} e costituiscono l'interfaccia di gestione basso livello; i +loro rispettivi prototipi sono: +\begin{functions} + \headdecl{sys/capability.h} + + \funcdecl{int capget(cap\_user\_header\_t hdrp, cap\_user\_data\_t datap)} + Legge le \textit{capabilities}. + + \funcdecl{int capset(cap\_user\_header\_t hdrp, const cap\_user\_data\_t + datap)} + Imposta le \textit{capabilities}. + + + \bodydesc{Entrambe le funzioni ritornano 0 in caso di successo e -1 in caso + di errore, nel qual caso \var{errno} può assumere i valori: + \begin{errlist} + \item[\errcode{ESRCH}] si è fatto riferimento ad un processo inesistente. + \item[\errcode{EPERM}] si è tentato di aggiungere una capacità + nell'insieme delle \textit{capabilities} permesse, o di impostare una + capacità non presente nell'insieme di quelle permesse negli insieme + delle effettive o ereditate, o si è cercato di impostare una + \textit{capability} di un altro processo senza avare + \const{CAP\_SETPCAP}. + \end{errlist} + ed inoltre \errval{EFAULT} ed \errval{EINVAL}. +} + +\end{functions} + +Queste due funzioni prendono come argomenti due tipi di dati dedicati, +definiti come puntatori a due strutture specifiche di Linux, illustrate in +fig.~\ref{fig:cap_kernel_struct}. Per poterle utilizzare occorre anche +cancellare la macro \macro{\_POSIX\_SOURCE}.\footnote{per farlo occorre + utilizzare la direttiva di preprocessore \direct{undef}; si dovrà cioè + inserire una istruzione \texttt{\#undef \_POSIX\_SOURCE} prima di includere + \texttt{sys/capability.h}.} Si tenga presente che le strutture di +fig.~\ref{fig:cap_kernel_struct}, come i prototipi delle due funzioni +\func{capget} e \func{capset}, sono soggette ad essere modificate con il +cambiamento del kernel (in particolare i tipi di dati delle strutture) ed +anche se finora l'interfaccia è risultata stabile, non c'è nessuna +assicurazione che questa venga mantenuta.\footnote{anzi, visto lo scarso + utilizzo di questa funzionalità ci sono state varie discussioni fra gli + sviluppatori del kernel relative all'eliminarla o al modificarla + radicalmente.} Pertanto se si vogliono scrivere programmi portabili che +possano essere eseguiti su qualunque versione del kernel è opportuno +utilizzare le interfacce di alto livello. + +\begin{figure}[!htb] + \footnotesize + \centering + \begin{minipage}[c]{15cm} + \includestruct{listati/cap_user_header_t.h} + \end{minipage} + \normalsize + \caption{Definizione delle strutture a cui fanno riferimento i puntatori + \structd{cap\_user\_header\_t} e \structd{cap\_user\_data\_t} usati per + l'interfaccia di gestione di basso livello delle \textit{capabilities}.} + \label{fig:cap_kernel_struct} +\end{figure} + +La struttura a cui deve puntare l'argomento \param{hdrp} serve ad indicare, +tramite il campo \var{pid}, il processo del quale si vogliono leggere o +modificare le \textit{capabilities}. Il campo \var{version} deve essere +impostato al valore della versione delle usata dal kernel (quello indicato +dalla costante \const{\_LINUX\_CAPABILITY\_VERSION} di +fig.~\ref{fig:cap_kernel_struct}) altrimenti le funzioni ritorneranno con un +errore di \errcode{EINVAL}, restituendo nel campo stesso il valore corretto +della versione in uso. La struttura a cui deve puntare l'argomento +\param{datap} invece conterrà i valori letti o da impostare per i tre insiemi +delle capacità del processo. + +Dato che le precedenti funzioni, oltre ad essere specifiche di Linux, non +garantiscono la stabilità nell'interfaccia, è sempre opportuno effettuare la +gestione delle \textit{capabilities} utilizzando le funzioni di libreria a +questo dedicate. Queste funzioni, che seguono quanto previsto nelle bozze +dello standard POSIX.1e, non fanno parte delle \acr{glibc} e sono fornite in +una libreria a parte,\footnote{la libreria è \texttt{libcap2}, nel caso di + Debian può essere installata con il pacchetto omonimo.} pertanto se un +programma le utilizza si dovrà indicare esplicitamente l'uso della suddetta +libreria attraverso l'opzione \texttt{-lcap} del compilatore. + +Le funzioni dell'interfaccia delle bozze di POSIX.1e prevedono l'uso di uno +tipo di dato opaco, \type{cap\_t}, come puntatore ai dati mantenuti nel +cosiddetto \textit{capability state},\footnote{si tratta in sostanza di un + puntatore ad una struttura interna utilizzata dalle librerie, i cui campi + non devono mai essere acceduti direttamente.} in sono memorizzati tutti i +dati delle \textit{capabilities}. In questo modo è possibile mascherare i +dettagli della gestione di basso livello, che potranno essere modificati senza +dover cambiare le funzioni dell'interfaccia, che faranno riferimento soltanto +ad oggetti di questo tipo. L'interfaccia pertanto non soltanto fornisce le +funzioni per modificare e leggere le \textit{capabilities}, ma anche quelle +per gestire i dati attraverso \type{cap\_t}. + +La prima funzione dell'interfaccia è quella che permette di inizializzare un +\textit{capability state}, allocando al contempo la memoria necessaria per i +relativi dati. La funzione è \funcd{cap\_init} ed il suo prototipo è: +\begin{functions} + \headdecl{sys/capability.h} + + \funcdecl{cap\_t cap\_init(void)} + Crea ed inizializza un \textit{capability state}. + + \bodydesc{La funzione ritorna un valore non nullo in caso di successo e + \macro{NULL} in caso di errore, nel qual caso \var{errno} assumerà il + valore \errval{ENOMEM}. + } +\end{functions} + +La funzione restituisce il puntatore \type{cap\_t} ad uno stato inizializzato +con tutte le \textit{capabilities} azzerate. In caso di errore (cioè quando +non c'è memoria sufficiente ad allocare i dati) viene restituito \macro{NULL} +ed \var{errno} viene impostata a \errval{ENOMEM}. La memoria necessaria a +mantenere i dati viene automaticamente allocata da \func{cap\_init}, ma dovrà +essere disallocata esplicitamente quando non è più necessaria utilizzando, per +questo l'interfaccia fornisce una apposita funzione, \funcd{cap\_free}, il cui +prototipo è: +\begin{functions} + \headdecl{sys/capability.h} + + \funcdecl{int cap\_free(void *obj\_d)} + Disalloca la memoria allocata per i dati delle \textit{capabilities}. + + \bodydesc{La funzione ritorna 0 in caso di successo e $-1$ in caso di + errore, nel qual caso \var{errno} assumerà il valore \errval{EINVAL}. + } +\end{functions} + +La funzione permette di liberare la memoria allocata dalle altre funzioni +della libreria sia per un \textit{capability state}, nel qual caso l'argomento +dovrà essere un dato di tipo \type{cap\_t}, che per una descrizione testuale +dello stesso,\footnote{cioè quanto ottenuto tramite la funzione + \func{cap\_to\_text}.} nel qual caso l'argomento dovrà essere un dato di +tipo \texttt{char *}. Per questo l'argomento \param{obj\_d} è dichiarato come +\texttt{void *} e deve sempre 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{functions} + \headdecl{sys/capability.h} + + \funcdecl{cap\_t cap\_dup(cap\_t cap\_p)} + Duplica un \textit{capability state} restituendone una copia. + + \bodydesc{La funzione ritorna un valore non nullo in caso di successo e + \macro{NULL} in caso di errore, nel qual caso \var{errno} potrà assumere i + valori \errval{ENOMEM} o \errval{EINVAL}. + } +\end{functions} + +La funzione crea una copia del \textit{capability state} 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.\footnote{alla fine delle operazioni si ricordi però di + 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{functions} + \headdecl{sys/capability.h} + + \funcdecl{int cap\_clear(cap\_t cap\_p)} + Inizializza un \textit{capability state} cancellando tutte le + \textit{capabilities}. + + \bodydesc{La funzione ritorna 0 in caso di successo e $-1$ in caso di + errore, nel qual caso \var{errno} assumerà il valore \errval{EINVAL}. + } +\end{functions} + +La funzione si limita ad azzerare tutte le \textit{capabilities} presenti nel +\textit{capability state} 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}. + +Per la gestione dei valori delle \textit{capabilities} presenti in un +\textit{capability state} l'interfaccia prevede due funzioni, +\funcd{cap\_get\_flag} e \funcd{cap\_set\_flag}, che permettono +rispettivamente di leggere o impostare il valore di un flag delle +\textit{capabilities}; i rispettivi prototipi sono: +\begin{functions} + \headdecl{sys/capability.h} + + \funcdecl{int cap\_get\_flag(cap\_t cap\_p, cap\_value\_t cap, cap\_flag\_t + flag, cap\_flag\_value\_t *value\_p)} + Legge il valore di una \textit{capability}. + + \funcdecl{int cap\_set\_flag(cap\_t cap\_p, cap\_flag\_t flag, int ncap, + cap\_value\_t *caps, cap\_flag\_value\_t value)} + Imposta il valore di una \textit{capability}. + + \bodydesc{Le funzioni ritornano 0 in caso di successo e $-1$ in caso di + errore, nel qual caso \var{errno} assumerà il valore \errval{EINVAL}. +} +\end{functions} + +In entrambe le funzioni l'argomento \param{cap\_p} indica il puntatore al +\textit{capability state} su cui operare, mentre l'argomento \param{flag} +indica su quale dei tre insiemi illustrati a +pag.~\pageref{sec:capabilities_set} si intende operare. Questi devono essere +specificati 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 + \texttt{/usr/include/sys/capability.h}.} uno dei valori illustrati in +tab.~\ref{tab:cap_set_identifier}. + +\begin{table}[htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|l|} + \hline + \textbf{Valore} & \textbf{Significato} \\ + \hline + \hline + \const{CAP\_EFFECTIVE} & Capacità dell'insieme \textsl{effettivo}.\\ + \const{CAP\_PERMITTED} & Capacità dell'insieme \textsl{permesso}.\\ + \const{CAP\_INHERITABLE}& Capacità dell'insieme \textsl{ereditabile}.\\ + \hline + \end{tabular} + \caption{Valori possibili per il tipo di dato \type{cap\_flag\_t} che + identifica gli insiemi delle \textit{capabilities}.} + \label{tab:cap_set_identifier} +\end{table} + +La capacità che si intende controllare o impostare invece deve essere +specificata attraverso una variabile di tipo \type{cap\_value\_t}, che può +prendere come valore uno qualunque di quelli riportati in +tab.~\ref{tab:proc_capabilities}, in questo caso però non è possibile +combinare diversi valori in una maschera binaria, una variabile di tipo +\type{cap\_value\_t} deve indicare una sola capacità.\footnote{nel file di + header citato nella nota precedente il tipo \type{cap\_value\_t} è definito + come \ctyp{int}, ma i valori validi sono soltanto quelli di + tab.~\ref{tab:proc_capabilities}.} + +Infine lo stato di una 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 + \const{CAP\_CLEAR}& La capacità non è impostata.\\ + \const{CAP\_SET} & La capacità è impostata.\\ + \hline + \end{tabular} + \caption{Valori possibili per il tipo di dato \type{cap\_flag\_value\_t} che + indica lo stato di una capacità.} + \label{tab:cap_value_type} +\end{table} + +La funzione \func{cap\_get\_flag} legge lo stato della capacità indicata +dall'argomento \param{cap} all'interno dell'insieme indicato dall'argomento +\param{flag} e ne restituisce il valore nella variabile posta all'indirizzo +puntato dall'argomento \param{value\_p}; è possibile cioè leggere soltanto uno +stato di una 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. 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 +impostazione) viene indicato dall'argomento \param{value}. + +Per la visualizzazione dello stato delle \textit{capabilities} l'interfaccia +prevede una funzione apposita, \funcd{cap\_to\_text}, il cui prototipo è: +\begin{functions} + \headdecl{sys/capability.h} + + \funcdecl{char * cap\_to\_text(cap\_t caps, ssize\_t * length\_p)} + + Genera una visualizzazione testuale delle \textit{capabilities}. + + \bodydesc{La funzione ritorna un puntatore alla stringa con la descrizione + delle \textit{capabilities} in caso di successo e \val{NULL} in caso di + errore, nel qual caso \var{errno} può assumere i valori \errval{EINVAL} o + \errval{ENOMEM}. + } +\end{functions} + +La funzione ritorna l'indirizzo di una stringa contente la descrizione +testuale del contenuto del \textit{capabilities state} \param{caps} passato +come argomento, e, qualora l'argomento \param{length\_p} sia diverso da +\val{NULL}, restituisce 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}. + +Fin quei abbiamo trattato solo le funzioni di servizio relative alla +manipolazione dei \textit{capabilities state}; l'interfaccia di gestione +prevede però anche le funzioni per la gestione delle \textit{capabilities} +stesse. La prima di queste è \funcd{cap\_get\_proc} che consente la lettura +delle \textit{capabilities} del processo corrente, il suo prototipo è: +\begin{functions} + \headdecl{sys/capability.h} + + \funcdecl{cap\_t cap\_get\_proc(void)} + Legge le \textit{capabilities} del processo corrente. + + \bodydesc{La funzione ritorna un valore diverso da \val{NULL} in caso di + successo e \val{NULL} in caso di errore, nel qual caso \var{errno} può + assumere i valori \errval{EINVAL}, \errval{EPERM} o \errval{ENOMEM}. } +\end{functions} + +La funzione legge il valore delle \textit{capabilities} associate al processo +da cui viene invocata, restituendo il risultato tramite il puntatore ad un +\textit{capabilities 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{capgetp}, 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 \texttt{sys/capability.h}.} è: +\begin{functions} + \headdecl{sys/capability.h} + + \funcdecl{int capgetp(pid\_t pid, cap\_t cap\_d)} + Legge le \textit{capabilities} del processo indicato da \param{pid}. + + \bodydesc{La funzione ritorna 0 in caso di successo e $-1$ in caso di + errore, nel qual caso \var{errno} può assumere i valori \errval{EINVAL}, + \errval{EPERM} o \errval{ENOMEM}. + } +\end{functions} +%TODO controllare e correggere i codici di errore!!! + +La funzione legge il valore delle \textit{capabilities} del processo indicato +con l'argomento \param{pid}, e restituisce il risultato nel +\textit{capabilities state} posto all'indirizzo indicato con l'argomento +\param{cap\_d}; a differenza della precedente in questo caso il +\textit{capability state} deve essere stato creato in precedenza. 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{Verbatim} +... +CapInh: 0000000000000000 +CapPrm: 00000000fffffeff +CapEff: 00000000fffffeff +... +\end{Verbatim} + +Infine per impostare le \textit{capabilities} del processo corrente (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{functions} + \headdecl{sys/capability.h} + + \funcdecl{int cap\_set\_proc(cap\_t cap\_p)} + Imposta le \textit{capabilities} del processo corrente. + + \bodydesc{La funzione ritorna 0 in caso di successo e $-1$ in caso di + errore, nel qual caso \var{errno} può assumere i valori \errval{EINVAL}, + \errval{EPERM} o \errval{ENOMEM}. + } +\end{functions} + +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). + +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 pid viene passato come parametro dell'opzione. + +\begin{figure}[htb] + \footnotesize \centering + \begin{minipage}[c]{15cm} + \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 \textsl{pid} del processo di cui si vuole +leggere le \textit{capabilities} e nulla altrimenti. Nel primo caso +(\texttt{\small 1--6}) si utilizza direttamente (\texttt{\small 2}) +\func{cap\_get\_proc} per ottenere lo stato delle capacità del processo, nel +secondo (\texttt{\small 7--14}) prima si inizializza (\texttt{\small 8}) uno +stato vuoto e poi (\texttt{\small 9}) si legge il valore delle capacità del +processo indicato. + +Il passo successivo è utilizzare (\texttt{\small 16}) \func{cap\_to\_text} per +tradurre in una stringa lo stato, e poi (\texttt{\small 17}) stamparlo; infine +(\texttt{\small 19--20}) 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/ +% TODO documentare prctl ... + \subsection{Gli attributi estesi} \label{sec:file_xattr} @@ -4025,9 +4756,9 @@ programmi e librerie) di cui il server potrebbe avere bisogno. % LocalWords: removexattr lremovexattr fremovexattr attributename lacl acl % LocalWords: OBJ setfacl len any prefix separator options NUMERIC IDS SMART % LocalWords: INDENT major number IDE Documentation makedev fopendir proc copy +% LocalWords: euidaccess eaccess delete def tag qualifier permset %%% Local Variables: %%% mode: latex %%% TeX-master: "gapil" %%% End: -% LocalWords: euidaccess eaccess delete def tag qualifier permset