Altro materiale sulle capabilities.
authorSimone Piccardi <piccardi@gnulinux.it>
Sat, 19 Nov 2005 23:16:06 +0000 (23:16 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Sat, 19 Nov 2005 23:16:06 +0000 (23:16 +0000)
prochand.tex
sources/Makefile

index bd0cd21c848b4256530a6a3febca997e74b1d899..56c7f4ff1620ca2ee9740a8a42305580355d837b 100644 (file)
@@ -1867,7 +1867,6 @@ scrivere codice portabile.
 \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
@@ -2074,14 +2073,14 @@ vengono mantenuti in forma di tre diverse maschere binarie,\footnote{il kernel
   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} (definito come intero a 32 bit), il che comporta un
-  massimo di 32 \textit{capabilities} distinte.} in cui ciascun bit
-corrisponde ad una capacità diversa; se ne è riportato l'elenco,\footnote{si
-  tenga presente che l'elenco delle \textit{capabilities} presentato questa
-  tabella, ripreso dalla relativa pagina di manuale (accessibile con
-  \texttt{man capabilities}), è quello aggiornato al kernel 2.6.6.} con una
-breve descrizione, ed il nome delle costanti che identificano i singoli bit,
-in tab.~\ref{tab:proc_capabilities}.
+  \texttt{kernel\_cap\_t}; questo è attualmente definito come intero a 32 bit,
+  il che comporta un massimo di 32 \textit{capabilities} distinte.} in cui
+ciascun bit corrisponde ad una capacità diversa; se ne è riportato
+l'elenco,\footnote{si tenga presente che l'elenco delle \textit{capabilities}
+  presentato questa tabella, ripreso dalla relativa pagina di manuale
+  (accessibile con \texttt{man capabilities}), è quello aggiornato al kernel
+  2.6.6.} con una breve descrizione, ed il nome delle costanti che
+identificano i singoli bit, in tab.~\ref{tab:proc_capabilities}.
 
 L'utilizzo di tre distinti insiemi serve a fornire una interfaccia flessibile
 per l'uso delle \textit{capabilities}, con scopi analoghi a quelli per cui
@@ -2098,9 +2097,10 @@ sez.~\ref{sec:proc_setuid}; il loro significato 
   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{ereditate}'', cioè quelle che vengono trasmesse ad un nuovo
+  ``\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
@@ -2119,14 +2119,16 @@ capacit
 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 può al più rimuovere uno dei bit
-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 viene messo in esecuzione (con \func{exec}) un processo eredita (nel
-senso che assume negli insiemi \textit{effective} e \textit{permitted}) le
-\textit{capabilities} mantenute nell'insieme \textit{inherited}, a meno che
+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
@@ -2136,9 +2138,11 @@ capacit
 \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} Linux usa due funzioni,
-\funcd{capget} e \funcd{capset}, che permettono rispettivamente di leggerne ed
-impostarne i valori, i cui rispettivi prototipi sono:
+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}
 
@@ -2161,39 +2165,243 @@ impostarne i valori, i cui rispettivi prototipi sono:
       \textit{capability} di un altro processo senza avare
       \const{CAP\_SETPCAP}. 
   \end{errlist}
-  ed inoltre \errval{EFAULT} ed \errval{EINVAL}}
-\end{functions}
+  ed inoltre \errval{EFAULT} ed \errval{EINVAL}.
+}
 
-Queste due funzioni costituiscono una interfaccia di basso livello, ed usano
-due strutture specifiche di Linux, la cui definizione è riportata in
-fig.~\ref{fig:cap_kernel_struct}. Queste ultime, come le due funzioni
-precedenti, 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, 
+\end{functions}
 
+Queste due funzioni prendono come argomenti due tipi di dati dedicati,
+definiti come puntatori a due strutture specifiche di Linux, illustrate in
+fig.~\ref{fig:cap_kernel_struct}. Per poterle utilizzare occorre anche
+cancellare la macro \macro{\_POSIX\_SOURCE}.\footnote{per farlo occorre
+  utilizzare la direttiva di preprocessore \direct{undef}; si dovrà cioè
+  inserire una istruzione \texttt{\#undef \_POSIX\_SOURCE} prima di includere
+  \texttt{sys/capability.h}.} Si tenga presente che le strutture di
+fig.~\ref{fig:cap_kernel_struct}, come i prototipi delle due funzioni
+\func{capget} e \func{capset}, sono soggette ad essere modificate con il
+cambiamento del kernel (in particolare i tipi di dati delle strutture) ed
+anche se finora l'interfaccia è risultata stabile, non c'è nessuna
+assicurazione che questa venga mantenuta. Pertando se si vogliono scrivere
+programmi portabili che possano essere eseguiti su qualunque versione del
+kernel è opportuno utilizzare le interfacce di alto livello.
 
 \begin{figure}[!htb]
   \footnotesize
   \centering
   \begin{minipage}[c]{15cm}
-    \includestruct{listati/tms.h}
+    \includestruct{listati/cap_user_header_t.h}
   \end{minipage} 
   \normalsize 
-  \caption{Le strutture specifiche di Linux per l'interfaccia di gestione di
-    basso livello delle \textit{capabilities}.}
+  \caption{Definizione delle strutture a cui fanno riferimento i puntatori
+    \structd{cap\_user\_header\_t} e \structd{cap\_user\_data\_t} usati per
+    l'interfaccia di gestione di basso livello delle \textit{capabilities}.}
   \label{fig:cap_kernel_struct}
 \end{figure}
 
+La struttura a cui deve puntare l'argomento \param{hdrp} serve ad indicare,
+tramite il campo \var{pid}, il processo del quale si vogliono leggere o
+modificare le \textit{capabilities}. Il campo \var{version} deve essere
+impostato al valore della versione delle usata dal kernel (quello indicato
+dalla costante \const{\_LINUX\_CAPABILITY\_VERSION} di
+fig.~\ref{fig:cap_kernel_struct}) altrimenti le funzioni ritorneranno con un
+errore di \errcode{EINVAL}, restituendo nel campo stesso il valore corretto
+della versione in uso.  La struttura a cui deve puntare l'argomento
+\param{datap} invece conterrà i valori letti o da impostare per i tre insiemi
+delle capacità del processo.
+
+Dato che le precedenti funzioni, oltre ad essere specifiche di Linux, non
+garantiscono la stabilità nell'interfaccia, è sempre opportuno effettuare la
+gestione delle \textit{capabilities} utilizzando le funzioni di libreria a
+questo dedicate. Queste funzioni, che seguono quanto previsto nelle bozze
+dello standard POSIX.1e, non fanno parte delle \acr{glibc} e sono fornite in
+una libreria a parte,\footnote{la libreria è \texttt{libcap2}, nel caso di
+  Debian può essere installata con il pacchetto omonimo.} pertanto se un
+programma le utilizza si dovrà indicare esplicitamente l'uso della suddetta
+libreria attraverso l'opzione \texttt{-lcap} del compilatore.
+
+Le funzioni dell'interfaccia POSIX.1e prevedono l'uso di uno tipo di dato
+opaco, \type{cap\_t}, come puntatore ai dati mantenuti nel cosiddetto
+\textit{capability state},\footnote{si tratta in sostanza di un puntatore ad
+  una struttura interna utilizzata dalle librerie, i cui campi non devono mai
+  essere acceduti direttamente.} in sono memorizzati tutti i dati delle
+\textit{capabilities}. In questo modo è possibile mascherare i dettagli della
+gestione di basso livello, che potranno essere modificati senza dover cambiare
+le funzioni dell'interfaccia, che faranno riferimento soltanto ad oggetti di
+questo tipo.  L'interfaccia pertanto non soltanto fornirà le funzioni per
+modificare e leggere le \textit{capabilities}, ma anche quelle per gestire i
+dati attraverso \type{cap\_t}.
+
+La prima funzione dell'interfaccia è allora quella che permette di
+inizializzare un \textit{capability state}, allocando al contempo la memoria
+necessaria per i relativi dati. La funzione è \funcd{cap\_init} ed il suo
+prototipo è:
+\begin{functions}
+  \headdecl{sys/capability.h}
 
-sono definite in una apposita struttura del kernel, 
+  \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}
 
-Per la gestione delle \textit{capabilities} lo standard POSIX.1e prevede l'uso
-di uno specifico tipo di dato \type{cap\_t}, che 
+La funzione restituisce il puntatore \type{cap\_t} ad uno stato inizializzato
+con tutte le \textit{capabilities} azzerate. In caso di errore (cioè quando
+non c'è memoria suffuciente ad allocare i dati) viene restituito \macro{NULL}
+ed \var{errno} viene impostata a \errval{ENOMEM}.  La memoria necessaria a
+mantenere i dati viene automaticamente allocata da \func{cap\_init}, ma dovrà
+essere disallocata esplicitamente quando non più necessaria utilizzando la
+funzione \funcd{cap\_free}, il cui prototipo è:
+\begin{functions}
+  \headdecl{sys/capability.h}
 
+  \funcdecl{int cap\_free(void *obj\_d)} 
+  Disalloca la memoria allocata per i dati delle \textit{capabilities}.
+  
+  \bodydesc{La funzione ritorna 0 in caso di successo e $-1$ in caso di
+    errore, nel qual caso \var{errno} assumerà il valore \errval{EINVAL}.
+}
+\end{functions}
 
+La funzione permette di liberare la memoria allocata dalle altre funzioni
+della libreria sia per un \textit{capability state}, nel qual caso l'argomento
+dovrà essere un dato di tipo \type{cap\_t}, che per una descrizione testuale
+dello stesso,\footnote{cioè quanto ottenuto tramite la funzione
+  \func{cap\_to\_text}.} nel qual caso l'argomento dovrà essere di tipo
+\texttt{char *}. L'argomento \param{obj\_d} deve corrispondere ad un oggetto
+ottenuto tramite altre funzioni della libreria, altrimenti la funzione fallirà
+con un errore di \errval{EINVAL}.
+
+Infine si può creare una copia di un \textit{capability state} ottenuto in
+precedenza tramite la funzione \funcd{cap\_dup}, il cui prototipo è:
+\begin{functions}
+  \headdecl{sys/capability.h}
 
+  \funcdecl{cap\_t cap\_dup(cap\_t cap\_p)} 
+  Duplica un \textit{capability state} restituendone una copia.
+  
+  \bodydesc{La funzione ritorna un valore non nullo in caso di successo e
+    \macro{NULL} in caso di errore, nel qual caso \var{errno} potrà assumere i
+    valori \errval{ENOMEM} o \errval{EINVAL}.  
+}
+\end{functions}
+
+La funzione crea una copia del \textit{capability state} \param{cap\_p}
+passato come argomento, restituendo il puntatore alla copia che conterrà gli
+stessi valori delle \textit{capabilities} presenti nell'originale. La memoria
+necessaria viene allocata automaticamente dalla funzione. Una volta effettuata
+la copia i due \textit{capability state} potranno essere modificati in maniera
+completamente indipendente.
+
+Una seconda classe di funzioni di servizio sono quelle per la gestione dei
+dati contenuti all'interno di un \textit{capability state}; la prima di esse è
+\funcd{cap\_clear}, il cui prototipo è:
+\begin{functions}
+  \headdecl{sys/capability.h}
+
+  \funcdecl{int cap\_clear(cap\_t cap\_p)} 
+  Inizializza un \textit{capability state} cancellando tutte le
+  \textit{capabilities}.
+  
+  \bodydesc{La funzione ritorna 0 in caso di successo e $-1$ in caso di
+    errore, nel qual caso \var{errno} assumerà il valore \errval{EINVAL}.
+}
+\end{functions}
 
+La funzione si limita ad azzerare tutte le \textit{capabilities} presenti nel
+\textit{capability state} \param{cap\_p} passato come argomento restituendo
+uno stato \textsl{vuoto}, analogo a quello che si ottiene nella creazione con 
+\func{cap\_init}.
 
+Per la gestione dei valori delle \textit{capabilities} presenti in un
+\textit{capability state} l'interfaccia prevede due funzioni,
+\funcd{cap\_get\_flag} e \funcd{cap\_set\_flag}, che permettono
+rispettivamente di leggere o impostare il valore di un flag delle
+\textit{capabilities}; i rispettivi prototipi sono:
+\begin{functions}
+  \headdecl{sys/capability.h}
+
+  \funcdecl{int cap\_get\_flag(cap\_t cap\_p, cap\_value\_t cap, cap\_flag\_t
+    flag, cap\_flag\_value\_t *value\_p)}
+  Legge il valore di una \textit{capability}.
+
+  \funcdecl{int cap\_set\_flag(cap\_t cap\_p, cap\_flag\_t flag, int ncap,
+    cap\_value\_t *caps, cap\_flag\_value\_t value)} 
+  Imposta il valore di una \textit{capability}.
+  
+  \bodydesc{Le funzioni ritornano 0 in caso di successo e $-1$ in caso di
+    errore, nel qual caso \var{errno} assumerà il valore \errval{EINVAL}.
+}
+\end{functions}
+
+In entrambe le funzioni l'argomento \param{cap\_p} indica il
+\textit{capability state} su cui operare, mentre l'argomento \param{flag}
+indica su quale dei tre insiemi illustrati a
+pag.~\pageref{sec:capabilities_set} si intende operare. Questo deve essere
+specificato con una variabile di tipo \type{cap\_flag\_t} e può assumere
+esclusivamente\footnote{si tratta in effetti di un tipo enumerato, come si può
+  verificare dalla sua definizione che si trova in
+  \texttt{/usr/include/sys/capability.h}.} uno dei valori illustrati in
+tab.~\ref{tab:cap_set_identifier}.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|l|}
+    \hline
+    \textbf{Valore} & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{CAP\_EFFECTIVE}  & Capacità dell'insieme \textsl{effettivo}.\\
+    \const{CAP\_PERMITTED}  & Capacità dell'insieme \textsl{permesso}.\\ 
+    \const{CAP\_INHERITABLE}& Capacità dell'insieme \textsl{ereditabile}.\\
+    \hline
+  \end{tabular}
+  \caption{Valori possibili per il tipo di dato \type{cap\_flag\_t} che
+    identifica gli insiemi delle \textit{capabilities}.}
+  \label{tab:cap_set_identifier}
+\end{table}
+
+La capacità che si intende controllare o impostare deve essere specificata
+attraverso una variabile di tipo \type{cap\_value\_t}, che può prendere come
+valore uno qualunque di quelli riportati in tab.~\ref{tab:proc_capabilities},
+in questo caso però non è possibile combinare diversi valori in una maschera
+binaria, una variabile di tipo \type{cap\_value\_t} deve indicare una sola
+\textit{capabilities}.\footnote{nel file di header citato nella nota
+  precedente il tipo \type{cap\_value\_t} è definito come \ctyp{int}, ma i
+  valori validi sono soltanto quelli di tab.~\ref{tab:proc_capabilities}.}
+Infine lo stato di una \textit{capabilities} è descritto ad una variabile di
+tipo \type{cap\_flag\_value\_t}, che a sua volta può assumere soltanto
+uno\footnote{anche questo è un tipo enumerato.} dei valori di
+tab.~\ref{tab:cap_value_type}.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|l|}
+    \hline
+    \textbf{Valore} & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{CAP\_CLEAR}& La capacità non è impostata.\\ 
+    \const{CAP\_SET}  & La capacità è impostata.\\
+    \hline
+  \end{tabular}
+  \caption{Valori possibili per il tipo di dato \type{cap\_flag\_value\_t} che
+    indica lo stato di una capacità.}
+  \label{tab:cap_value_type}
+\end{table}
+
+La funzione \func{cap\_get\_flag} legge lo stato della capacità indicata
+dall'argomento \param{cap} all'interno dell'insieme indicato dall'argomento
+\param{flag} e ne restituisce il valore nella variabile posta all'indirizzo
+puntato dall'argomento \param{value\_p}; è possibile cioè leggere soltanto uno
+stato alla volta.
+
+La funzione \func{cap\_set\_flag} può invece impostare più capacità, anche se
+solo all'interno dello stesso insieme, in una sola chiamata.
 
 
 
@@ -2201,6 +2409,8 @@ di uno specifico tipo di dato \type{cap\_t}, che
 \itindend{capabilities}
 
 
+
+
 \section{La gestione della priorità di esecuzione}
 \label{sec:proc_priority}
 
index 7832b6d8f216df9e550201f38dd271f1fc8d64a3..3d20078e6f3495af0a291cdce2080358836eb663 100644 (file)
@@ -115,6 +115,9 @@ wwwd: wwwd.c
 acctctrl: AcctCtrl.c
        $(CC) $(CFLAGS) $^ -o $@
 
+printcap: 
+       $(CC) $(CFLAGS) $^ -o $@
+
 
 # Macro per la generazione della tarball dei sorgenti
 package: clean gapil_source.tgz