# Custom selinux policies

## Karl Vogel

### Fri, 17 Jul 2026 03:27:57

# 1. 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.

# 2. 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

## 2.1. 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)

## 2.2. 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;

# 3. 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

## 3.1. 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

## 3.2. 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;

# 4. 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

## 4.1. 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

## 4.2. 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;

# 5. Sample files

The 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.

# 6. 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

# 7. 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

# 8. Feedback

Feel free to send comments.

Generated from policies.t2t by txt2tags
$Revision: 1.2 $
$UUID: 32ca047f-99b5-3a0d-a034-51110136f8a1 $