SELinux - personalizzare una policy - Centos 5 - RHEL - Freshclam - caso concreto
SELinux è sempre stato la mia croce / delizia.
SELinux è un argomento complesso, ma in poche parole è un sistema che permette in ambienti Linux un maggior controllo su quello che un programma / utente può o non può fare aumentando sensibilmente il livello di sicurezza raggiungibile su un server.
Tra le idee di base vi è quella del contesto, ovvero è permessa o non permessa una operazione in base alla situazione in cui questa viene eseguita. Esempio è perfettamente lecito girare in costume da bagno nel contesto "spiaggia", mentre non lo è mentre si gira nel contesto"tribunale" :D.
SELinux è un argomento complesso, ma in poche parole è un sistema che permette in ambienti Linux un maggior controllo su quello che un programma / utente può o non può fare aumentando sensibilmente il livello di sicurezza raggiungibile su un server.
Tra le idee di base vi è quella del contesto, ovvero è permessa o non permessa una operazione in base alla situazione in cui questa viene eseguita. Esempio è perfettamente lecito girare in costume da bagno nel contesto "spiaggia", mentre non lo è mentre si gira nel contesto"tribunale" :D.
Per ulteriori approfondimenti in appendice diversi riferimenti a SELinux
Problema:
Nell'articolo "CentOS5 + QmailToaster Mailserver Setup - simple howto", se non si disabilitasse SELinux, l'installazione di QmailToaster non andrebbe a buon fine perchè durante l'installazione del pacchetto clamav-toaster-0.xx.x viene avviato il servizio freshclam che permette l'aggiornamento dell'antivirus stesso. Il servizio all'avvio semplicemente si blocca senza generare nessun errore. Il demone stesso clamd ha problemi nella lettura del db virus.
Soluzione 1:
Disabilitare SELinux - Questa è l'idea proposta da chiunque, forum, how-to. Qui per esempio l'how-to ufficiale per l'installazione di QmailToaster su CentoOS 4.3 :
Firewall Configuration:
Select "No firewall"
Select "Disabled" mode for SELinux
Per me questa è una NON-soluzione.
Perchè è come lasciare la macchina chiusa a chiave ma con i finestrini appena socchiusi. Abbiamo lasciato la macchina aperta alla mercè dei ladri? Sicuramente no, però abbiamo lasciato loro una via d'entrata in più.
Per esperienza personale SELinux mi ha, per usare un termine tecnico, parato il XXXX più di una volta. Specialmente in presenza degli immancabili bachi di cui i software, per definizione, sono portatori.
Soluzione 2:
Per fortuna (e perseveranza) mia seguo SELinux dalla sua introduzione in Fedora Core 3 e posso dire che da allora la tecnologia è migliorata e di molto fornendo via via strumenti più potenti.
Uno di questi è un log che pochi conoscono audit.log. Il suo contenuto è finito dentro a /var/log/messages in Fedora Core 5, ma in CentOS 5 lo troviamo nel percorso originario /var/log/audit/audit.log.
Un esempio del contenuto di questo log è:
Si possono notare delle linee con la dicitura "denied" -negato- ovvero una operazione non permessa dalle attuali policy di sicurezza. Bene noi partendo da queste indicazioni andremmo a costruire la nostra politica personalizzata.
type=AVC msg=audit(1190013769.595:958064): avc: denied { write } for pid=11794 comm="clamd" name="clamav" dev=dm-0 ino=4030584 scontext=system_u:system_r:clamd_t:s0 tcontext=system_u:object_r:usr_t:s0 tclass=dir
type=SYSCALL msg=audit(1190013769.595:958064): arch=40000003 syscall=5 success=no exit=-13 a0=96a369c a1=242 a2=1fc a3=96a3698 items=0 ppid=2187 pid=11794 auid=4294967295 uid=46 gid=46 euid=46 suid=46 fsuid=46 egid=46 sgid=46 fsgid=46 tty=(none) comm="clamd" exe="/usr/sbin/clamd" subj=system_u:system_r:clamd_t:s0 key=(null)
type=AVC msg=audit(1190013769.596:958065): avc: denied { read } for pid=11794 comm="clamd" name="main.cvd" dev=dm-0 ino=4030636 scontext=system_u:system_r:clamd_t:s0 tcontext=system_u:object_r:usr_t:s0 tclass=file
type=SYSCALL msg=audit(1190013769.596:958065): arch=40000003 syscall=5 success=no exit=-13 a0=96a37a8 a1=0 a2=1b6 a3=969efc0 items=0 ppid=2187 pid=11794 auid=4294967295 uid=46 gid=46 euid=46 suid=46 fsuid=46 egid=46 sgid=46 fsgid=46 tty=(none) comm="clamd" exe="/usr/sbin/clamd" subj=system_u:system_r:clamd_t:s0 key=(null)
type=AVC msg=audit(1190013770.175:958066): avc: denied { read write } for pid=11808 comm="freshclam" name="0" dev=devpts ino=2 scontext=root:system_r:freshclam_t:s0 tcontext=root:object_r:devpts_t:s0 tclass=chr_file
type=AVC msg=audit(1190013770.175:958066): avc: denied { read write } for pid=11808 comm="freshclam" name="0" dev=devpts ino=2 scontext=root:system_r:freshclam_t:s0 tcontext=root:object_r:devpts_t:s0 tclass=chr_file
type=AVC msg=audit(1190013770.175:958066): avc: denied { read write } for pid=11808 comm="freshclam" name="0" dev=devpts ino=2 scontext=root:system_r:freshclam_t:s0 tcontext=root:object_r:devpts_t:s0 tclass=chr_file
type=AVC msg=audit(1190013770.175:958066): avc: denied { read write } for pid=11808 comm="freshclam" name="0" dev=devpts ino=2 scontext=root:system_r:freshclam_t:s0 tcontext=root:object_r:devpts_t:s0 tclass=chr_file
type=SYSCALL msg=audit(1190013770.175:958066): arch=40000003 syscall=11 success=yes exit=0 a0=832aa88 a1=832acc0 a2=832abb8 a3=832a6d8 items=0 ppid=11807 pid=11808 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) comm="freshclam" exe="/usr/bin/freshclam" subj=root:system_r:freshclam_t:s0 key=(null)
type=AVC_PATH msg=audit(1190013770.175:958066): path="/dev/pts/0"
type=AVC_PATH msg=audit(1190013770.175:958066): path="/dev/pts/0"
type=AVC_PATH msg=audit(1190013770.175:958066): path="/dev/pts/0"
type=AVC msg=audit(1190013770.280:958067): avc: denied { append } for pid=11808 comm="freshclam" name="freshclam.log" dev=dm-0 ino=10158808 scontext=root:system_r:freshclam_t:s0 tcontext=root:object_r:clamd_var_log_t:s0 tclass=file
type=SYSCALL msg=audit(1190013770.280:958067): arch=40000003 syscall=5 success=no exit=-13 a0=9af6448 a1=441 a2=1b6 a3=9af70b8 items=0 ppid=11807 pid=11808 auid=0 uid=46 gid=46 euid=46 suid=46 fsuid=46 egid=46 sgid=46 fsgid=46 tty=(none) comm="freshclam" exe="/usr/bin/freshclam" subj=root:system_r:freshclam_t:s0 key=(null)
type=AVC msg=audit(1190013770.626:958068): avc: denied { write } for pid=11810 comm="clamd" name="clamav" dev=dm-0 ino=4030584 scontext=system_u:system_r:clamd_t:s0 tcontext=system_u:object_r:usr_t:s0 tclass=dir
type=SYSCALL msg=audit(1190013770.626:958068): arch=40000003 syscall=5 success=no exit=-13 a0=8d6169c a1=242 a2=1fc a3=8d61698 items=0 ppid=2187 pid=11810 auid=4294967295 uid=46 gid=46 euid=46 suid=46 fsuid=46 egid=46 sgid=46 fsgid=46 tty=(none) comm="clamd" exe="/usr/sbin/clamd" subj=system_u:system_r:clamd_t:s0 key=(null)
type=AVC msg=audit(1190013770.627:958069): avc: denied { read } for pid=11810 comm="clamd" name="main.cvd" dev=dm-0 ino=4030636 scontext=system_u:system_r:clamd_t:s0 tcontext=system_u:object_r:usr_t:s0 tclass=file
Versione Veloce:
- Ci spostiamo dentro la cartella $home con il comando
>cdcreiamo una cartella my_policies con il comando
>mkdir my_policiese ci spostiamo dentro con
>cd my_policiesadesso lanciamo il comando
1> audit2allow -i /var/log/audit/audit.log -M myClamdPolicies
Generazione file tipo enforcement: myClamdPolicies.te
Compilazione policy
checkmodule -M -m -o myClamdPolicies.mod myClamdPolicies.te
semodule_package -o myClamdPolicies.pp -m myClamdPolicies.mod
******************** IMPORTANTE **********************
Per poter caricare questo pacchetto di policy appena creato nel kernel,
vi è richiesto di eseguire
semodule -i myClamdPolicies.pp
Ora, come consigliato dal programma lanciamo:
2>semodule -i myClamdPolicies.pp
Controlliamo se siamo ancora con SELinux abilitato con:
>sestatus
SELinux status: enabled
SELinuxfs mount: /selinux
Current mode: enforcing
Mode from config file: enforcing
Policy version: 21
Policy from config file: targeted
dove vediamo che è abilitato e attivo.
Bene se ora proviamo a lanciare
service freshclam startci darà OK, altrimenti ripetere i passaggi 1 e 2 finchè non lo farà !
Versione Meditata:
Nella soluzione veloce non abbiamo ben capito cosa è successo, ma ogni buon sistemista vuol capire come funziona, per avere pieno controllo su quello che sta facendo e non lasciare (involontariamente) la porta aperta a intrusioni.
Con il comando precedente se osserviamo dentro alla cartella che abbiamo creato, troviamo 3 file:
>ll
totale 24
-rw-r--r-- 1 root root 2137 17 set 10:03 myClamdPolicies.mod
-rw-r--r-- 1 root root 2153 17 set 10:03 myClamdPolicies.pp
-rw-r--r-- 1 root root 598 17 set 10:03 myClamdPolicies.te
adesso vedremo come creare e manipolare con cognizione di causa questi tre file.
In particolare vedremo come (rif. audit2allow):
- Generare il file di policies .te;
- Compilare il binario .mod;
- Pacchettizzare il policy package .pp;
- Per creare il file di policies .te il modo migliore è sempre quello di usare il comando audit2allow:
>audit2allow -i /var/log/audit/audit.log -m myClamdPolicies2 > myClamdPolicies2.te
Questa volta possiamo guardare dentro il file myClamdPolicies2.te con il comando> vi myClamdPolicies2.te
Ci troveremo davanti un contenuto del genere:
Qualora trovassimo qualche riga con programmi che non hanno a che fare con il problema che stiamo cercando di risolvere, possiamo rimuoverle. Se una volta installato il modulo, volessimo vedere le modifiche dall'ultimo caricamento delle policies possiamo usare lo switch -l di audit2allow:
module myClamdPolicies2 1.0;
require {
class chr_file { read write };
class dir { add_name setattr write };
class file { append create getattr lock read write };
class sock_file create;
type clamd_t;
type clamd_var_log_t;
type devpts_t;
type freshclam_t;
type proc_t;
type tmp_t;
type usr_t;
role system_r;
};
allow clamd_t proc_t:file { getattr read };
allow clamd_t tmp_t:sock_file create;
allow clamd_t usr_t:dir { add_name write };
allow clamd_t usr_t:file { create getattr read write };
allow freshclam_t clamd_var_log_t:file { append getattr lock };
allow freshclam_t devpts_t:chr_file { read write };
allow freshclam_t usr_t:dir { setattr write };
allow freshclam_t usr_t:file read;> audit2allow -h
audit2allow [-adhilrv] [-t file ] [ -f fcfile ] [-i
] [[-m|-M] ] [-o ]
-a, --all read input from audit and message log, conflicts with -i
-d, --dmesg read input from output of /bin/dmesg
-h, --help display this message
-i, --input read input fromconflicts with -a
-l, --lastreload read input only after last "load_policy"
-m, --module generate module/require output
-M generate loadable module package, conflicts with -o
-o, --output append output to, conflicts with -M
-r, --requires generate require output
-t, --tefile Add input from Existing Type Enforcement file
-f, --fcfile Existing Type Enforcement file, requires -M
-v, --verbose verbose output
-A, --analyze Analyze output - Ora possiamo compilarlo in binario con il comando
>checkmodule -M -m -o myClamdPolicies2.mod myClamdPolicies2.te
- Infine possiamo pacchettizzarlo
>semodule_package -o myClamdPolicies2.pp -m myClamdPolicies2.mod
- Lo carichiamo con (come abbiamo fatto prima)
>semodule -i myClamdPolicies2
- Se è andato tutto per il meglio adesso possiamo controllare se il nostro pacchetto è tra quelli caricati con
>semodule -l
amavis 1.1.0
ccs 1.0.0
clamav 1.1.0
dcc 1.1.0
evolution 1.1.0
iscsid 1.0.0
mozilla 1.1.0
mplayer 1.1.0
myClamdPolicies 1.0
myClamdPolicies2 1.0
nagios 1.1.0
oddjob 1.0.1
pcscd 1.0.0
pyzor 1.1.0
razor 1.1.0
ricci 1.0.0
smartmon 1.1.0
Semplice no? :D
Conclusioni:
Quando su una distro abilitata con SELinux c'è qualcosa che non funziona e controllando nei log tradizionali non vi è nessuna informazione utile, conviene sempre controllare il file /var/log/audit/audit.log . Un'altra prova da fare è la seguente e cioè controllare con sestatus se SELinux è abilitato e in che modo:
>sestatus
SELinux status: enabled
SELinuxfs mount: /selinux
Current mode: enforcing
Mode from config file: enforcing
Policy version: 21
Policy from config file: targeted
Provare a disabilitare temporaneamente SELinux con il comando
>setenforce 0Verificando stavolta con
>sestatus
SELinux status: enabled
SELinuxfs mount: /selinux
Current mode: permissive <- Disabilitate, ma il log continua Mode from config file: enforcing Policy version: 21 Policy from config file: targeted
Vediamo che SELinux è disabilitato. Bene, se adesso, il programma o la funzionalità che stavamo cercando di far funzionare ora gira, vuol dire che il problema era relativo a SELinux e può essere risolto con i metodi prima descritti.
Byez
Riferimenti:
-
http://www.nsa.gov/selinux/ Homepage del team di sviluppo NSA SELinux.
http://selinux.sourceforge.net Homepage della comunity di SELinux.
http://www.linuxtopia.org/online_books/centos5/centos5_administration_guide/index.html - Libro piuttosto esaustivo su CentOS e RHEL. I capitoli relativi a SELinux sono dal 43 al 46.
- http://fedoraproject.org/wiki/SELinux/ - Documentazione di riferimento per gli ambienti fedora
"L'ignoranza è l'origine di tutti i mali."
(Socrate)
Tag: SELINUX, tuning, CentOS, RHEL, audit2allow




Digg/dgrossato
Flickr/dgrossato
Linkedin/dgrossato
YouTube/dgrossato
Del.icio.us/dgrossato
Technorati/dgrossato
MyBlogLog/dgrossato
8 commenti:
bello e completo, complimenti
Grazie, spero possa essere utile a qualcuno.
Hai mai provato SELinux?
Byez
Grazie, incomincero' ad implementarlo sui miei server..
a me non è chiara una cosa: come fa audit2allow che deve abilitare solo clamd?
@Mlk: Beh spero di averti dato qualche idea positiva. :D Se hai problemi particolari mi trovi qui :D
@Anonimo: audit2allow a partire dal file di log di SElinux vede quali operazioni sono state negate e da quelle ti crea il modulo. Lui ovviamente ci mette dentro tutto, quindi come riportato per semplicità in questo articolo, se c'è solo clamd che non funziona ti genera i permessi solo per clamd, altrimenti ti mescola un po' tutto. E' per questo che ho presentato anche la modalità un po' più meditata, ovvero da quello che ti genera audit2allow, tu puoi rimuovere tutto quello che non ti serve o eventualmente correggere qualche modalità di accesso.
Byez
grazie per aver chiarito :D
Grazie a te per aver chiesto e avermi dato la possibilità di chiarire! :D
Ciao e grazie per la spiegazione ... avrei un problema ho eseguito alla lettere la tua spiegazione ma quando provo a caricare la policy ... il sistema genera questo mess:
libsemanage.semanage_get_lock: Could not get direct transaction lock at /etc/selinux/targeted/modules/semanage.trans.LOCK. Resource temporarily unavailable.
semodule: Failed on myPostfixPolicies.pp!
Mi puoi dare qualche aiuto ?
ciao e grazie
Posta un commento