Product SiteDocumentation Site

14.5. Introducció a SELinux

14.5.1. Principis

SELinux («Security Enhanced Linux» o “Linux amb seguretat millorada”) és un sistema de control d'accés obligatori («Mandatory Access Control») fonamentat en la interfície LSM de Linux («Linux Security Modules» o “mòduls de seguretat de Linux”). A la pràctica, el nucli consulta a SELinux abans que cada crida de sistema per saber si el procés està autoritzat a fer l'operació donada.
SELinux utilitza un conjunt de regles, conegudes col·lectivament com a política, per autoritzar o prohibir les operacions. Aquestes normes són difícils de crear. Afortunadament, es proporcionen dues polítiques estàndard («targeted», o “dirigides”, i «strict», o “estrictes”) per evitar la major part de la feina de configuració.
Amb SELinux, la gestió dels drets és completament diferent dels sistemes Unix tradicionals. Els drets d'un procés depenen del seu context de seguretat. El context es defineix per la identitat de l'usuari que inicia el procés, el rol i el domini que l'usuari té en aquell moment. Els drets realment depenen del domini, però les transicions entre dominis estan controlades pels rols. Finalment, les possibles transicions entre rols depenen de la identitat.
Contextos de seguretat i usuaris d'Unix

Figura 14.1. Contextos de seguretat i usuaris d'Unix

A la pràctica, durant l'inici de sessió, l'usuari té assignat per defecte un context de seguretat (depenent dels rols que es puguin adoptar). Això defineix el domini actual, i per tant el domini que portaran tots els nous processos fills. Si es vol canviar el rol actual i el seu domini associat, cal executar newrole -r rol_r -t domini_t (normalment només hi ha un sol domini permès per a un rol donat, així doncs el paràmetre -t sovint es pot obviar). Aquesta ordre autentica l'usuari demanant la contrasenya. Aquesta característica impedeix que els programes canviïn automàticament els rols. Aquests canvis només poden ocórrer si estan explícitament permesos en la política de SELinux.
Òbviament els drets no s'apliquen a tots els objectes (fitxers, directoris, sòcols, dispositius, etc.). Poden variar d'objecte a objecte. Per aconseguir-ho, cada objecte està associat a un tipus (això es coneix com a etiquetatge). Els drets dels dominis s'expressen així amb conjunts d'operacions (des)autoritzades en aquests tipus (i, indirectament, en tots els objectes que estan etiquetats amb el tipus donat).
Per defecte, un programa hereta el domini de l'usuari que l'inicia, però les polítiques estàndard de SELinux esperen que molts programes importants s'executin en dominis dedicats. Per aconseguir-ho, aquests executables estan etiquetats amb un tipus dedicat (per exemple ssh està etiquetat amb ssh_exec_t, i quan el programa inicia, es canvia automàticament al domini ssh_t). Aquest mecanisme automàtic de transició de domini permet concedir només els drets requerits per cada programa. És un principi fonamental de SELinux.
Transicions automàtiques entre dominis

Figura 14.2. Transicions automàtiques entre dominis

14.5.2. Configuració de SELinux

El suport de SELinux està integrat en els nuclis estàndard proporcionats per Debian. Les eines bàsiques d'Unix admeten SELinux sense cap modificació. Per tant, és relativament fàcil habilitar SELinux.
The apt install selinux-basics selinux-policy-defaulti auditd command will automatically install the packages required to configure an SELinux system.
El paquet selinux-policy-default conté un conjunt de regles estàndard. Per defecte, aquesta política només limita l'accés a uns pocs serveis àmpliament exposats. Les sessions d'usuari no estan restringides i per tant és improbable que SELinux bloquegi operacions d'usuari legítimes. Tanmateix, això millora la seguretat dels serveis del sistema que funcionen a la màquina. Per configurar una política equivalent a les antigues regles "estrictes", només heu de desactivar el mòdul unconfined (la gestió de mòduls és detallarà més endavant en aquesta secció).
Una vegada que s'hagi instal·lat la política, s'haurien d'etiquetar tots els arxius disponibles (que significa assignar-los un tipus). Aquesta operació s'ha d'iniciar manualment amb fixfiles relabel.
El sistema SELinux ja està llest. Per activar-lo, s'ha d'afegir el paràmetre selinux=1 security=selinux al nucli de Linux. El paràmetre audit=1 permet el registre de SELinux que registra totes les operacions denegades. Finalment, el paràmetre enforcing=1 comporta l'aplicació de les regles: sense ell SELinux funciona en el seu mode per defecte «permissive» on les accions denegades estan registrades però tot i així executades. Per tant, s'hauria de modificar el fitxer de configuració del gestor d'arrencada GRUB per afegir els paràmetres desitjats. Una manera fàcil de fer-ho és modificar la variable GRUB_CMDLINE_LINUX a /etc/default/grub i executar update-grub. SELinux estarà actiu després d'un reinici.
Val la pena assenyalar que l'script selinux-activate automatitza aquestes operacions i obliga a etiquetar en la següent arrencada (fet que evita nous fitxers no etiquetats creats mentre SELinux encara no estava actiu i mentre l'etiquetatge estava en curs).

14.5.3. Gestió d'un sistema SELinux

La política de SELinux és un conjunt modular de regles, i la seva instal·lació detecta i habilita automàticament tots els mòduls pertinents basats en els serveis ja instal·lats. Així doncs, el sistema està operatiu immediatament. No obstant això, quan s'instal·la un servei després de la política de SELinux, cal que sigui capaç d'habilitar manualment el mòdul corresponent. Aquest és el propòsit de l'ordre semodule. A més, heu de poder definir els rols que cada usuari pot adoptar, i això es pot fer amb l'ordre semanage.
Aquestes dues ordres es poden utilitzar per modificar la configuració actual de SELinux, que s'emmagatzema a /etc/selinux/default/. A diferència d'altres fitxers de configuració que es poden trobar a /etc/, tots aquests fitxers no s'han de canviar manualment. S'haurien d'utilitzar els programes dissenyats per a aquest propòsit.

14.5.3.1. Gestió dels mòduls de SELinux

Els mòduls de SELinux disponibles s'emmagatzemen al directori /usr/share/selinux/default/. Per habilitar un d'aquests mòduls en la configuració actual, s'hauria d'utilitzar semodule -i mòdul.pp.bz2. L'extensió pp.bz2 significa «policy package» o “paquet de polítiques” (comprimit amb bzip2).
L'eliminació d'un mòdul de la configuració actual es fa amb semodule -r mòdul. Finalment, l'ordre semodule -l llista els mòduls que estan instal·lats actualment. També en mostra els números de versió. Els mòduls es poden activar de manera selectiva amb semodule -e i desactivar amb semodule -d.
# semodule -i /usr/share/selinux/default/abrt.pp.bz2
libsemanage.semanage_direct_install_info: abrt module will be disabled after install as there is a disabled instance of this module present in the system.
# semodule -l
accountsd
acct
[...]
# semodule -e abrt
# semodule -d accountsd
# semodule -l
abrt
acct
[...]
# semodule -r abrt
libsemanage.semanage_direct_remove_key: abrt module at priority 100 is now active.
semodule carrega immediatament la nova configuració llevat que afegiu l'opció -n. Val la pena assenyalar que el programa actua per defecte amb la configuració actual (indicada per la variable SELINUXTYPE a /etc/selinux/config), però que se'n pot modificar una altra especificant-la amb l'opció -s.

14.5.3.2. Gestió d'identitats

Cada vegada que un usuari inicia sessió, se li assigna una identitat de SELinux. Aquesta identitat defineix els rols que podrà adoptar. Aquestes dues assignacions (de l'usuari a la identitat i d'aquesta identitat als rols) són configurables amb l'ordre semanage.
You should definitely read the semanage(8) manual page. All the managed concepts have their own manual page; for instance, semanage-login(8). Even if the command's syntax tends to be similar for all the concepts which are managed, it is recommended to read its manual page. You will find common options to most subcommands: -a to add, -d to delete, -m to modify, -l to list, and -t to indicate a type (or domain).
semanage login -l llista la relació actual entre els identificadors d'usuari i les identitats de SELinux. Els usuaris que no tenen una entrada explícita obtenen la identitat indicada a l'entrada __default__. L'ordre semanage login -a -s user_u usuari associarà la identitat user_u a l'usuari indicat. Finalment, semanage login -d usuari elimina l'entrada de relació assignada a aquest usuari.
# semanage login -a -s user_u rhertzog
# semanage login -l

Login Name           SELinux User         MLS/MCS Range        Service

__default__          unconfined_u         s0-s0:c0.c1023       *
rhertzog             user_u               s0                   *
root                 unconfined_u         s0-s0:c0.c1023       *
# semanage login -d rhertzog
semanage user -l llista les relacions entre les identitats d'usuari de SELinux i els rols permesos. Afegir una nova identitat requereix definir els rols corresponents i un prefix d'etiquetatge que s'utilitza per assignar un tipus a fitxers personals (/home/usuari/*). El prefix ha de ser triat entre user, staff, i sysadm. El prefix «staff» dona com a resultat fitxers de tipus «staff_home_dir_t». La creació d'una nova identitat d'usuari de SELinux es fa amb semanage user -a -R rols -P prefixe identitat. Finalment, es pot eliminar una identitat d'usuari de SELinux amb semanage user -d identitat.
# semanage user -a -R 'staff_r user_r' -P staff test_u
# semanage user -l

                Labeling   MLS/       MLS/                          
SELinux User    Prefix     MCS Level  MCS Range                      SELinux Roles

root            sysadm     s0         s0-s0:c0.c1023                 staff_r sysadm_r system_r
staff_u         staff      s0         s0-s0:c0.c1023                 staff_r sysadm_r
sysadm_u        sysadm     s0         s0-s0:c0.c1023                 sysadm_r
system_u        user       s0         s0-s0:c0.c1023                 system_r
test_u          staff      s0         s0                             staff_r user_r
unconfined_u    unconfined s0         s0-s0:c0.c1023                 system_r unconfined_r
user_u          user       s0         s0                             user_r
# semanage user -d test_u

14.5.3.3. Gestió de contextos de fitxers, ports i booleans

Cada mòdul SELinux proporciona un conjunt de regles d'etiquetatge de fitxers, però també és possible afegir regles d'etiquetatge personalitzades per atendre algun cas específic. Per exemple, si es vol que el servidor web pugui llegir fitxers dins de la jerarquia de fitxers /srv/www/, es pot executar semanage fcontext -a -t httpd_sys_content_t "/srv/www(/.*)?" seguit de restorecon -R /srv/www/. La primera ordre registra les noves regles d'etiquetatge i l'última reinicia els tipus de fitxers d'acord amb les regles d'etiquetatge actuals.
De la mateixa manera, els ports TCP/UDP estan etiquetats de manera que només els dimonis corresponents poden escoltar-hi. Per exemple, si es vol que el servidor web pugui escoltar pel port 8080, caldrà d'executar semanage port -m -t http_port_t -p tcp 8080.
Some SELinux modules export Boolean options that you can tweak to alter the behavior of the default rules. The getsebool utility can be used to inspect those options (getsebool boolean displays one option, and getsebool -a them all). The setsebool boolean value command changes the current value of a Boolean option. The -P option makes the change permanent, it means that the new value becomes the default and will be kept across reboots. The example below grants web servers an access to home directories (this is useful when users have personal websites in ~/public_html/).
# getsebool httpd_enable_homedirs
httpd_enable_homedirs --> off
# setsebool -P httpd_enable_homedirs on
# getsebool httpd_enable_homedirs
httpd_enable_homedirs --> on

14.5.4. Adaptació de les regles

Com que la política de SELinux és modular, podria ser interessant desenvolupar nous mòduls per a aplicacions (possiblement personalitzades) que no els tenen. Aquests nous mòduls completaran la política de referència.
Per crear nous mòduls, cal el paquet selinux-policy-dev, així com selinux-policy-doc. Aquest últim conté la documentació de les regles estàndard (/usr/share/doc/selinux-policy-doc/html/) i fitxers de mostra que es poden utilitzar com a patró per crear nous mòduls. Instal·leu aquests fitxers i estudieu-los més de prop:
$ cp /usr/share/doc/selinux-policy-doc/Makefile.example Makefile
$ cp /usr/share/doc/selinux-policy-doc/example.fc ./
$ cp /usr/share/doc/selinux-policy-doc/example.if ./
$ cp /usr/share/doc/selinux-policy-doc/example.te ./
El fitxer .te és el més important. Defineix les regles. El fitxer .fc defineix els "contextos de fitxers", és a dir, els tipus assignats als fitxers relacionats amb aquest mòdul. Les dades del fitxer .fc s'utilitzen durant el pas de l'etiquetatge de fitxers. Finalment, el fitxer .if defineix la interfície del mòdul: és un conjunt de "funcions públiques" que altres mòduls poden utilitzar per interaccionar correctament amb el mòdul que esteu creant.

14.5.4.1. Creació d'un fitxer .fc

Llegir l'exemple següent hauria de ser suficient per entendre l'estructura d'aquesta mena de fitxer. Podeu utilitzar expressions regulars per assignar el mateix context de seguretat a diversos fitxers, o fins i tot a un arbre de directoris sencer.

Exemple 14.2. Fitxer example.fc

# myapp executable will have:
# label: system_u:object_r:myapp_exec_t
# MLS sensitivity: s0
# MCS categories: <none>

/usr/sbin/myapp         --      gen_context(system_u:object_r:myapp_exec_t,s0)

14.5.4.2. Creació d'un fitxer .if

A l'exemple següent, la primera interfície (“myapp_domtrans”) controla qui pot executar l'aplicació. El segon (“myapp_read_log”) concedeix drets de lectura als fitxers de registre de l'aplicació.
Cada interfície ha de generar un conjunt vàlid de regles que es poden inserir en un fitxer .te. Per tant, cal declarar tots els tipus que utilitzeu (amb la macro gen_require), i utilitzar directives estàndard per concedir drets. No obstant això, cal tenir en compte que es poden utilitzar interfícies proporcionades per altres mòduls. La següent secció donarà més explicacions sobre com expressar aquests drets.

Exemple 14.3. El fitxer example.if

## <summary>Myapp example policy</summary>
## <desc>
##      <p>
##              More descriptive text about myapp.  The desc
##              tag can also use p, ul, and ol
##              html tags for formatting.
##      </p>
##      <p>
##              This policy supports the following myapp features:
##              <ul>
##              <li>Feature A</li>
##              <li>Feature B</li>
##              <li>Feature C</li>
##              </ul>
##      </p>
## </desc>
#

########################################
## <summary>
##      Execute a domain transition to run myapp.
## </summary>
## <param name="domain">
##      <summary>
##      Domain allowed to transition.
##      </summary>
## </param>
#
interface(`myapp_domtrans',`
        gen_require(`
                type myapp_t, myapp_exec_t;
        ')

        domtrans_pattern($1,myapp_exec_t,myapp_t)
')

########################################
## <summary>
##      Read myapp log files.
## </summary>
## <param name="domain">
##      <summary>
##      Domain allowed to read the log files.
##      </summary>
## </param>
#
interface(`myapp_read_log',`
        gen_require(`
                type myapp_log_t;
        ')

        logging_search_logs($1)
        allow $1 myapp_log_t:file read_file_perms;
')

14.5.4.3. Creació d'un fitxer .te

Doneu un cop d'ull al fitxer example.te:
policy_module(example,1.0.0) 1 # a non-base module name must match the file name

########################################
#
# Declarations
#

type myapp_t; 2
type myapp_exec_t;
domain_type(myapp_t)
domain_entry_file(myapp_t, myapp_exec_t) 3

type myapp_log_t;
logging_log_file(myapp_log_t) 4

type myapp_tmp_t;
files_tmp_file(myapp_tmp_t)

########################################
#
# Myapp local policy
#

allow myapp_t myapp_log_t:file { read_file_perms append_file_perms }; 5

allow myapp_t myapp_tmp_t:file manage_file_perms;
files_tmp_filetrans(myapp_t,myapp_tmp_t,file)

1

El mòdul s'ha d'identificar pel seu nom i el número de versió. Aquesta directiva és necessària.

2

Si el mòdul introdueix nous tipus, ha de declarar-los amb directives com aquesta. No s'ha de dubtar per crear tants tipus com siguin necessaris en lloc de concedir massa drets inútils.

3

Aquestes interfícies defineixen el tipus myapp_t com un domini de procés que hauria d'utilitzar qualsevol executable etiquetat amb myapp_exec_t. Implícitament, això afegeix un atribut exec_type en aquests objectes, que al seu torn permet a altres mòduls concedir drets per executar aquests programes: per exemple, el mòdul userdomain permet processos amb dominis user_t, staff_t, i sysadm_t per executar-los. Els dominis d'altres aplicacions confinades no tindran els drets per executar-les, tret que les normes els concedeixin drets similars (aquest és el cas, per exemple, de dpkg amb el seu domini dpkg_t).

4

logging_log_file és una interfície proporcionada per la política de referència. Indica que els fitxers etiquetats amb el tipus donat són fitxers de registre que haurien de beneficiar-se de les regles associades (per exemple, concedint drets a logrotate perquè pugui manipular-los).

5

La directiva allow és la directiva base utilitzada per autoritzar una operació. El primer paràmetre és el domini de procés que està autoritzat per executar l'operació. El segon defineix l'objecte que un procés del domini anterior pot manipular. Aquest paràmetre és de la forma “tipus:classe” on tipus és el seu tipus SELinux i classe descriu la naturalesa de l'objecte (fitxer, directori, sòcol, «fifo», etc.). Finalment, l'últim paràmetre descriu els permisos (les operacions permeses).
Els permisos es defineixen com el conjunt d'operacions permeses i segueixen aquesta plantilla: { operació1 operació2 }. No obstant això, també es poden utilitzar macros que representin els permisos més útils. El fitxer /usr/share/selinux/devel/include/support/obj_perm_sets.spt els llista.
La pàgina web següent proporciona una llista relativament exhaustiva de classes d'objectes, i de permisos que es poden concedir.
Ara només cal trobar el conjunt mínim de normes necessàries per a garantir que l'aplicació o el servei desitjats funcionin correctament. Per a aconseguir-ho, s'hauria de tenir un bon coneixement de com funciona l'aplicació i de quin tipus de dades gestiona i/o genera.
No obstant això, és possible un enfocament empíric. Una vegada que els objectes rellevants estan etiquetats correctament, es pot utilitzar l'aplicació en mode permissiu: les operacions que serien prohibides són registrades però tot i així funcionaran. En analitzar els registres, ara ja es podran identificar les operacions a permetre. Heus aquí un exemple d'una entrada de registre d'aquest tipus:
avc:  denied  { read write } for  pid=1876 comm="syslogd" name="xconsole" dev=tmpfs ino=5510 scontext=system_u:system_r:syslogd_t:s0 tcontext=system_u:object_r:device_t:s0 tclass=fifo_file permissive=1
Per entendre millor aquest missatge, estudiem-lo per parts.

Taula 14.1. Anàlisi d'una traça de SELinux

MissatgeDescripció
avc: deniedS'ha denegat una operació.
{ read write }Aquesta operació requeria els permisos read i write.
pid=1876El procés amb el PID 1876 va executar l'operació (o ho va intentar).
comm="syslogd"El procés era una instància del programa syslogd.
name="xconsole"L'objecte de destinació s'anomenava xconsole. A vegades també es pot tenir una variable «path», amb el camí complet, en lloc seu.
dev=tmpfsEl dispositiu que alberga l'objecte de destinació és un tmpfs (un sistema de fitxers en memòria). Per a un disc real, es podria veure la partició que allotjava l'objecte (per exemple, «sda3»).
ino=5510L'objecte és identificat pel número d'«inode» 5510.
scontext=system_u:system_r:syslogd_t:s0Aquest és el context de seguretat del procés que va executar l'operació.
tcontext=system_u:object_r:device_t:s0Aquest és el context de seguretat de l'objecte destí.
tclass=fifo_fileL'objecte de destinació és un fitxer «FIFO».
Observant aquesta entrada de registre, és possible construir una regla que permeti aquesta operació. Per exemple, allow syslogd_t device_t:fifo_file { read write }. Aquest procés es pot automatitzar, i és exactament el que ofereix l'ordre audit2allow (al paquet policycoreutils). Aquest enfocament només és útil si els diversos objectes ja estan etiquetats correctament segons el que s'ha de confinar. En qualsevol cas, haureu de revisar detingudament les normes generades i validar-les segons el vostre coneixement de l'aplicació. De fet, aquest enfocament tendeix a concedir més drets dels que realment es necessiten. La solució adequada és sovint crear nous tipus i concedir drets només sobre aquests. També pot passar que una operació denegada no sigui fatal per a l'aplicació, en aquest cas podria ser millor afegir una regla de «dontaudit» per evitar l'entrada al registre malgrat la denegació efectiva.

14.5.4.4. Compilació dels fitxers

Una vegada que els 3 fitxers (exemple.if,exemple.fc, i exemple.te) coincideixen amb les vostres expectatives per a les noves regles, canvieu-los el nom a myapp.extensió i executeu make NAME=devel per generar un mòdul al fitxer myapp.pp (el podeu carregar immediatament amb semodule -i myapp.pp). Si es defineixen diversos mòduls, make crearà tots els fitxers corresponents .pp.