selinux and logrotate

Ted Rule ejtr at layer3.co.uk
Mon Jul 4 18:35:17 UTC 2005


I found a similar set of problems with FC3/FC4 strict policy arising
from my local decision to make /tmp a noexec partition. It led me to
find various nasty interactions between cups, logrotate, and
glibc-secure-mode when running with and without SELinux in enforcing
mode.


My current solution goes as follows:

a)	Modify /etc/cron.daily/logrotate to explicitly set TMPDIR
to a new logrotate specific location

$ cat /etc/cron.daily/logrotate
#!/bin/sh

# Use EXEC capable temp area for logrotate to run scripts within.
if [ -d  /var/spool/logrotate/tmp ]; then
        if [ -w  /var/spool/logrotate/tmp ]; then
                # SELinux  currently forbids chmod on the tmp dir itself
                #chmod 700 /var/spool/logrotate/tmp
                export TMPDIR=/var/spool/logrotate/tmp
        else
                exit 1
        fi
else
        exit 1
fi

/usr/sbin/logrotate -v /etc/logrotate.conf

$


b)	Label the Cron Daily script as logrotate_exec_t and the new tmp area
as tmp_t. Without this, the script suffers a secure mode transition as
it executes /usr/sbin/logrotate, and the TMPDIR env variable setting is
lost. The temporary script is already dynamically created as
logrotate_tmp_t by the policy, and the policy already has
"can_exec(logrotate_t, logrotate_tmp_t)" to allow logrotate to exec its
own creations.

$ cat /etc/selinux/strict/src/policy/file_contexts/program/logrotate.fc
# logrotate
/usr/sbin/logrotate     --      system_u:object_r:logrotate_exec_t
/usr/sbin/logcheck      --      system_u:object_r:logrotate_exec_t
ifdef(`distro_debian', `
/usr/bin/savelog        --      system_u:object_r:logrotate_exec_t
/var/lib/logrotate(/.*)?        system_u:object_r:logrotate_var_lib_t
', `
/var/lib/logrotate\.status --   system_u:object_r:logrotate_var_lib_t
')
# For TMPDIR workround
ifdef(`distro_redhat', `
/etc/cron.daily/logrotate --    system_u:object_r:logrotate_exec_t
')
/etc/cron\.(daily|weekly)/sysklogd -- system_u:object_r:logrotate_exec_t
/var/lib/logcheck(/.*)?         system_u:object_r:logrotate_var_lib_t
# using a hard-coded name under /var/tmp is a bug - new version fixes it
/var/tmp/logcheck       -d      system_u:object_r:logrotate_tmp_t
# For TMPDIR workround
/var/spool/logrotate/tmp -d     system_u:object_r:tmp_t
$


c)	Add policy to SELinux to allow logrotate_exec_t to exec itself under
Fedora/Redhat so as to allow the cron.daily script to
exec /usr/sbin/logrotate

$ sudo diff -u logrotate.te.strict.fc4.orig
logrotate.te.strict.fc4.patched
--- logrotate.te.strict.fc4.orig        2005-05-20 19:53:12.000000000
+0100
+++ logrotate.te.strict.fc4.patched     2005-06-23 13:38:38.000000000
+0100
@@ -33,6 +33,11 @@
 can_exec(logrotate_t, logrotate_exec_t)
 ')

+ifdef(`distro_redhat', `
+# for /etc/cron.daily/logrotate TMPDIR workround
+can_exec(logrotate_t, logrotate_exec_t)
+')
+
 # for perl
 allow logrotate_t usr_t:file { getattr read ioctl };
 allow logrotate_t usr_t:lnk_file read;
$


d)	Make sure cups logrotate uses service.

FC4 default /etc/logrotate.d/cups has


/var/log/cups/*_log {
    missingok
    notifempty
    sharedscripts
    postrotate
        /etc/init.d/cups condrestart >/dev/null 2>&1 || true
    endscript
}


my one has:


$ cat /etc/logrotate.d/cups
/var/log/cups/*_log {
    missingok
    notifempty
    sharedscripts
    postrotate
        /sbin/service cups condrestart >/dev/null 2>&1 || true
    endscript
}
$

The problem here is that cups ALSO interprets TMPDIR.
If restarted with /sbin/service, the environment is cleansed
by /sbin/service itself before launching cups irrespective of
SELinux mode, so that the overnight restart has the same
environment as the boot sequence.

If restarted with /etc/init.d/cups, cups inherits TMPDIR 
rom /etc/cron.daily/logrotate if SELinux is not enforcing,
and all sorts of nonsense arises.

Another safety measure here is to explicitly set the tmp
directory in cupsd.conf so that it doesn't even try to use TMPDIR.


A longer term thought is that logrotate should allow the setting of the
tmp directory directly in logrotate.conf and should ignore TMPDIR,
Likewise cups should ignore TMPDIR and cupsd.conf should have
an explicit tmp dir setting uncommented as distributed in the rpm.

Similary, persons should avoid using calls to /etc/init.d/xxxx in logrotate scripts and 
always use /sbin/service so that the environment is clean even when SELinux is not enforcing.

A wider feeling I got from investigating this on my machine is
that the SELinux FAQ should contain some more explicit information
on what is and isn't saved across a secure-mode transition.
As far as I could tell, SELinux doesn't perform a secure-mode transition when
running in permissive mode; the consequence is that when a program
passes environment variables to a child process, the child will see a different
environment depending on whether running permissive or enforcing - this
had me very confused until I realised what was going on.
Perhaps there could be a global setting (boolean?) to force permissive mode
to perform secure-mode transitions so that programs always see the same 
environment?



-- 
Ted Rule

Director, Layer3 Systems Ltd

W: http://www.layer3.co.uk/




More information about the fedora-selinux-list mailing list