Custom selinux policies
Karl Vogel
%%mtime(%a, %d %b %Y %T)

= Introduction =

I've written custom SELinux policies for several services.  They may not
be perfect, but it's way better than turning SELinux off.

Remember: every time someone disables SELinux,
//a little kitten doesn't get his forever home.//

= Example: ntpd =

Message about NTP in syslog:

```
May 23 01:06:51 setroubleshoot: SELinux is preventing /usr/sbin/ntpd
    from add_name access on the directory /etc/ntp/daemon/.
    For complete SELinux messages, run
    sealert -l 05294586-9567-4b5f-9f44-2a4df3566be1
```

You have to run sealert as root.  The raw audit messages are most
useful for creating a policy:

```
root# sealert -l 05294586-9567-4b5f-9f44-2a4df3566be1
SELinux is preventing /usr/sbin/ntpd from add_name access on the
directory /etc/ntp/daemon/.

[...]

You can generate a local policy module to allow this access.
Allow this access for now by executing:

    # grep ntpd /var/log/audit/audit.log | audit2allow -M mypol
    # semodule -i mypol.pp

[...]

Raw Audit Messages

type=AVC msg=audit(1527116806.223:345227): avc: denied { add_name }
    for pid=3040 comm="ntpd" name="drift.TEMP"
    scontext=system_u:system_r:ntpd_t:s0
    tcontext=unconfined_u:object_r:etc_t:s0 tclass=dir permissive=0

type=SYSCALL msg=audit(1527116806.223:345227): arch=x86_64
    syscall=open success=no exit=EACCES a0=560bc64d6cc0 a1=241 a2=1b6
    a3=0 items=2 ppid=1 pid=3040 auid=4294967295 uid=38 gid=38 euid=38
    suid=38 fsuid=38 egid=38 sgid=38 fsgid=38 tty=(none)
    ses=4294967295 comm=ntpd exe=/usr/sbin/ntpd
    subj=system_u:system_r:ntpd_t:s0 key=(null)

type=CWD msg=audit(1527116806.223:345227): cwd=/

type=PATH msg=audit(1527116806.223:345227): item=0
    name=/etc/ntp/daemon/ inode=1835637 dev=fb:00 mode=040700 ouid=38
    ogid=0 rdev=00:00 obj=unconfined_u:object_r:etc_t:s0
    nametype=PARENT

type=PATH msg=audit(1527116806.223:345227): item=1
    name=/etc/ntp/daemon/drift.TEMP nametype=CREATE
```


== Check the audit log ==

Look for NTPD errors:

```
root# grep ntpd /var/log/audit/audit.log | grep -v 'success=yes'
...
type=AVC msg=audit(1527116806.223:345227): avc: denied { add_name }
    for pid=3040 comm="ntpd" name="drift.TEMP"
    scontext=system_u:system_r:ntpd_t:s0
    tcontext=unconfined_u:object_r:etc_t:s0 tclass=dir permissive=0
type=SYSCALL msg=audit(1527116806.223:345227): arch=c000003e syscall=2
    success=no exit=-13 a0=560bc64d6cc0 a1=241 a2=1b6 a3=0 items=2
    ppid=1 pid=3040 auid=4294967295 uid=38 gid=38 euid=38 suid=38
    fsuid=38 egid=38 sgid=38 fsgid=38 tty=(none) ses=4294967295
    comm="ntpd" exe="/usr/sbin/ntpd" subj=system_u:system_r:ntpd_t:s0
    key=(null)
```

== Create the new policy ==

```
root# grep ntpd /var/log/audit/audit.log | grep -v 'success=yes' |
    audit2allow -M ntpd-drift

root# cat ntpd-drift.te
module ntpd-drift 1.0;

require {
        type ntpd_t;
        type etc_t;
        class dir add_name;
}

#============= ntpd_t ==============
allow ntpd_t etc_t:dir add_name;
```

= Example: iptables =

I'm getting entries like this in /var/log/messages:

```
Jun 24 18:53:56 setroubleshoot: SELinux is preventing
    /sbin/iptables-multi-1.4.7 from read access on the file /var/run/.
    For complete SELinux messages,
    run sealert -l 00f172d0-034b-4d13-8de2-f9698708ac23
```

== Check the audit log ==

```
me% sealert -l 00f172d0-034b-4d13-8de2-f9698708ac23
SELinux is preventing /sbin/iptables-multi-1.4.7 from read access on the
file /var/run/.

[...]

Raw Audit Messages

type=AVC msg=audit(1561416826.295:988687): avc: denied { read } for
    pid=13068 comm="iptables" name="xtables" dev="dm-0" ino=3145868
    scontext=unconfined_u:system_r:iptables_t:s0
    tcontext=unconfined_u:object_r:var_run_t:s0 tclass=file
    permissive=0

type=SYSCALL msg=audit(1561416826.295:988687): arch=x86_64
    syscall=open success=no exit=EACCES a0=40bf6c a1=40 a2=180
    a3=7ffef6ce7ef0 items=2 ppid=13049 pid=13068 auid=500 uid=0 gid=0
    euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=1
    comm=iptables exe=/sbin/iptables-multi-1.4.7
    subj=unconfined_u:system_r:iptables_t:s0 key=access

type=CWD msg=audit(1561416826.295:988687): cwd=/

type=PATH msg=audit(1561416826.295:988687): item=0 name=/var/run/
    inode=3146969 dev=f9:00 mode=040755 ouid=0 ogid=0 rdev=00:00
    obj=system_u:object_r:var_run_t:s0 nametype=PARENT

type=PATH msg=audit(1561416826.295:988687): item=1
    name=/var/run/xtables inode=3145868 dev=f9:00 mode=0100600 ouid=0
    ogid=0 rdev=00:00 obj=unconfined_u:object_r:var_run_t:s0
    nametype=NORMAL
```

== Create the new policy ==

It's easier and more accurate to use the raw audit messages above
to create the rule:

```
root# cat raw
type=AVC msg=audit(1561416826.295:988687): avc:  denied  { read } for...
type=SYSCALL msg=audit(1561416826.295:988687): arch=x86_64 syscall=open...
type=CWD msg=audit(1561416826.295:988687): cwd=/
type=PATH msg=audit(1561416826.295:988687): item=0 name=/var/run/ inode=...
type=PATH msg=audit(1561416826.295:988687): item=1 name=/var/run/xtables...

root# audit2allow -M iptables < raw
******************** IMPORTANT ***********************
To make this policy package active, execute:
semodule -i iptables.pp

root# cat iptables.te
module iptables 1.0;

require {
        type var_run_t;
        type iptables_t;
        class file read;
}

#============= iptables_t ==============
allow iptables_t var_run_t:file read;
```

= Example: /var/crash access =

I might like to see coredumps.  Messages in syslog:

```
Jan 8 08:21:42 setroubleshoot: SELinux is preventing
    /usr/libexec/abrt-hook-ccpp from create access on the file
    /var/crash/. For complete SELinux messages: run
    sealert -l 4a3a6822-f26d-4c77-a9cd-51ac2f974739
```

== Check the audit log ==

sealert report:

```
me% sealert -l 4a3a6822-f26d-4c77-a9cd-51ac2f974739

SELinux is preventing /usr/libexec/abrt-hook-ccpp from create access
on the file /var/crash/.

[...]

Raw Audit Messages
type=AVC msg=audit(1578489692.653:745403): avc: denied { create } for
    pid=20789 comm="abrt-hook-ccpp"
    name="core-Chrome_~dThread-11-500-226-22484-1578489692"
    scontext=system_u:system_r:kernel_t:s0
    tcontext=unconfined_u:object_r:unconfined_t:s0 tclass=file
    permissive=0

type=SYSCALL msg=audit(1578489692.653:745403): arch=x86_64
    syscall=openat success=no exit=EACCES a0=3 a1=b15ea0 a2=20041
    a3=180 items=2 ppid=11321 pid=20789 auid=4294967295 uid=0 gid=0
    euid=500 suid=0 fsuid=500 egid=226 sgid=0 fsgid=226 tty=(none)
    ses=4294967295 comm=abrt-hook-ccpp exe=/usr/libexec/abrt-hook-ccpp
    subj=system_u:system_r:kernel_t:s0 key=(null)

type=CWD msg=audit(1578489692.653:745403): cwd=/

type=PATH msg=audit(1578489692.653:745403): item=0 name=/var/crash/
    inode=3147444 dev=f9:00 mode=041777 ouid=0 ogid=0 rdev=00:00
    obj=system_u:object_r:var_t:s0 nametype=PARENT

type=PATH msg=audit(1578489692.653:745403): item=1
    name=/var/crash/core-Chrome_~dThread-11-500-226-22484-1578489692
    nametype=CREATE
```

== Create the new policy ==

New varcrash policy:

```
root# grep abrt-hook-ccpp /var/log/audit/audit.log |
        audit2allow -M varcrash
******************** IMPORTANT ***********************
To make this policy package active, execute:

semodule -i varcrash.pp

root# file varcrash*
varcrash.pp: SE Linux modular policy version 1, 1 sections, mod version
    10, MLS, module name varcrash\003
varcrash.te: ASCII text

root# rm varcrash.pp

root# cat varcrash.te
module varcrash 1.0;

require {
        type unconfined_t;
        type kernel_t;
        class file create;
}

#============= kernel_t ==============
allow kernel_t unconfined_t:file create;
```

= Sample files =

The [examples examples] directory has some local policies I've created,
plus a Makefile that will compile your .te files into binary form and
install them so they can be run at boot time.

Here's a tarball if you want to download [the whole damn thing policies.tar].

= What SELinux policies do I have? =

It's handy to keep a list of policies for your system, in case you install a
new box and want to make sure it's current.

```
root# semodule -l > POLICIES

root# cat POLICIES
abrt         1.2.0
ada          1.4.0
...
ipsec        1.10.2
iptables     1.1
...
mykexec      1.7
mypasswd     1.3
ntpd-drift   1.5
varcrash     1.2
```

= Running your policies at boot =

Here's part of my /etc/rc.d/rc.local file.  All local policies are compiled
into binary form and copied to /usr/local/etc/selinux:

```
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init.

tag='rc.local'
/usr/bin/logger -t $tag start
echo -n 'rc.local: '

/bin/touch /var/lock/subsys/local

# -----------------------------------------------------------------
# LOCAL ADDITIONS
#
# SElinux.
if test -d /usr/local/etc/selinux ; then
    echo -n ' selinux'
    ( cd /usr/local/etc/selinux && /usr/sbin/semodule -i *.pp &&
        /usr/bin/logger -t $tag 'selinux local policies' )
fi  

# Track reboots.
x=$(uname -rs | tr 'A-Z ' 'a-z-')
/bin/date "+$x %Y-%m-%d %H:%M:%S %z" >> /var/log/reboot

echo '.'
/usr/bin/logger -t $tag finish
```

= Feedback =

Feel free to send [comments mailto:vogelke@pobox.com].

-----------------------
//Generated from [%%infile %%infile] by//
//[txt2tags http://txt2tags.sourceforge.net]//{br}
//$Revision: 1.2 $// {br}
//$UUID: 32ca047f-99b5-3a0d-a034-51110136f8a1 $//

