Tmpfs with selinux

So having a rather tricky time trying to set the correct selinux context for a tmpfs mount.

Short version

I am using a tmpfs mount for n-central to log to, since it generates a lot of spam, and then use rsync to persist on shutdown and restore on startup.

fstab

tmpfs   /var/log/n-central tmpfs    defaults,noatime,mode=0755,size=10M,context=system_u:object_r:var_log_n_central_t  0 0

policy (te)

module nagent-log-rsync 1.0;

require {
    type rsync_t;
    type user_tmp_t;
    type logrotate_t;
    class dir setattr;
    class file { create getattr open read rename setattr unlink write };
}

# Define custom types for /var/log/n-central/ and /var/log/n-central-persist/
type var_log_n_central_t;
type var_log_n_central_persist_t;

#============= rsync_t ==============
allow rsync_t var_log_n_central_t:dir setattr;
allow rsync_t var_log_n_central_t:file { create getattr open read rename setattr unlink write };

allow rsync_t var_log_n_central_persist_t:dir setattr;
allow rsync_t var_log_n_central_persist_t:file { create getattr open read rename setattr unlink write };

allow rsync_t user_tmp_t:file open;
allow rsync_t user_tmp_t:file unlink;

#============= logrotate_t ==============
allow logrotate_t var_log_n_central_t:file { getattr open read write rename create unlink setattr };

contexts (fc)

/var/log/n-central(/.*)?   system_u:object_r:var_log_n_central_t:s0
/var/log/n-central-persist(/.*)?   system_u:object_r:var_log_n_central_persist_t:s0

How I compiled & actioned the policy

checkmodule -M -m -o nagent-log-rsync.mod nagent-log-rsync.te
semodule_package -o nagent-log-rsync.pp -m nagent-log-rsync.mod -f nagent-log-rsync.fc
sudo semodule -i nagent-log-rsync.pp

Problem

The moment I add ,context=system_u:object_r:var_log_n_central_t to the fstab I cant remount, boot will fail horribly too.

The policy is loaded.

> seinfo -t | grep var_log_n_central_t
   var_log_n_central_t
> sudo sesearch -A | grep n_central
allow logrotate_t var_log_n_central_t:file { create getattr open read rename setattr unlink write };
allow rsync_t var_log_n_central_persist_t:dir setattr;
allow rsync_t var_log_n_central_persist_t:file { create getattr open read rename setattr unlink write };
allow rsync_t var_log_n_central_t:dir setattr;
allow rsync_t var_log_n_central_t:file { create getattr open read rename setattr unlink write };

But remount just fails with no clear error

> sudo mount -o remount -v /var/log/n-central
mount: /var/log/n-central: mount point not mounted or bad option.
       dmesg(1) may have more information after failed mount system call.

# dmesg
[ 1180.152547] SELinux: security_context_str_to_sid (system_u:object_r:var_log_n_central_t) failed with errno=-22

Just not really sure what to do from here or what I missed?

Try this way:

context=system_u:object_r:var_log_n_central_t:s0

Check the output:

sudo semanage fcontext -l | grep -e /var/log/n-central

well

The error in dmesg now is

SELinux: unable to change security options during remount (dev tmpfs, type=tmpfs)

I would try a reboot, but after the last round, that wasn’t fun to fix without a Live USB

Also Logs:

sudo semanage fcontext -l | grep -e /var/log/n-central
/var/log/n-central(/.*)?                           all files          system_u:object_r:var_log_n_central_t:s0 
/var/log/n-central-persist(/.*)?                   all files          system_u:object_r:var_log_n_central_persist_t:s0 

Yeah boot still fails.
And I’m not finding anything meaningful in the logs…

Check in permissive SELinux mode, otherwise it seems to generate AVC denials.

Wow what a Journey, I’m starting to understand the hate for SELinux, this is a pretty simple use case by my books, and it was a serious mission.

Tips for anyone going down this rabbit hole in the future.

  1. add nofail to the mount, that way you don’t break boot and can test while in the os.
  2. try with restorecon first, and get that passing.
  3. restart the mount in systemd to get the last fails firing
  4. sudo ausearch -m avc --start recent | audit2allow is your friend to help formate what should go in your policy

Things I had to fix that I didn’t thought I would have to:

  1. systemd cronjob permissions
  2. systemd init permissions
  3. self association for the custom type

If there’s any pointers then I’d be happy to take that onboard.
Specifically I noticed that the nagent-log-restore service I have, that uses the find command required some more unconfined_service_t permissions, which didn’t seem right.

Anyway here is my final .te policy, the .fc stayed the same.

module nagent-log-rsync 1.0;

require {
    type rsync_t;
    type user_tmp_t;
    type logrotate_t;
    type mount_t;
    type unconfined_t;
    type unconfined_service_t;
    type fs_t;
    type init_t;
    type system_cronjob_t;
    class dir { getattr setattr relabelto relabelfrom read search open mounton write add_name remove_name };
    class file { create getattr open read rename setattr unlink write relabelto relabelfrom append ioctl };
    class filesystem { relabelto relabelfrom associate mount remount getattr };
}

# Define custom types for /var/log/n-central/ and /var/log/n-central-persist/
type var_log_n_central_t;
type var_log_n_central_persist_t;

#============= rsync_t ==============
allow rsync_t var_log_n_central_t:dir { getattr setattr search read open write add_name remove_name };
allow rsync_t var_log_n_central_t:file { create getattr open read rename setattr unlink write };

allow rsync_t var_log_n_central_persist_t:dir { getattr setattr search read open write add_name remove_name };
allow rsync_t var_log_n_central_persist_t:file { create getattr open read rename setattr unlink write };

#============= logrotate_t ==============
allow logrotate_t var_log_n_central_t:file { getattr open read write rename create unlink setattr };
allow logrotate_t var_log_n_central_t:dir { getattr search };

#============= system_cronjob_t ==============
allow system_cronjob_t var_log_n_central_t:dir { search write read add_name };
allow system_cronjob_t var_log_n_central_t:file { getattr create append open ioctl };

#============= mount_t ==============
allow mount_t var_log_n_central_t:filesystem { relabelto relabelfrom mount };
allow mount_t var_log_n_central_t:dir { getattr mounton };

#============= unconfined_t (fix restorecon) ==============
allow unconfined_t var_log_n_central_t:filesystem { relabelto relabelfrom associate };
allow unconfined_t var_log_n_central_t:file { relabelto relabelfrom getattr };
allow unconfined_t var_log_n_central_t:dir { relabelto relabelfrom read getattr setattr open search };
allow unconfined_service_t var_log_n_central_t:dir { search getattr open };
allow unconfined_service_t var_log_n_central_t:file { read append getattr };

allow unconfined_t var_log_n_central_persist_t:filesystem { relabelto relabelfrom associate };
allow unconfined_t var_log_n_central_persist_t:file { relabelto relabelfrom getattr };
allow unconfined_t var_log_n_central_persist_t:dir { relabelto relabelfrom read getattr setattr open search };
allow unconfined_service_t var_log_n_central_persist_t:dir { search getattr open };
allow unconfined_service_t var_log_n_central_persist_t:file { read append getattr open };

#============= unconfined_t (fix n-agent) ==============
allow unconfined_t var_log_n_central_t:filesystem { remount };
allow unconfined_service_t var_log_n_central_t:dir { read write add_name };
allow unconfined_service_t var_log_n_central_t:file { read create write };

#============= unconfined_t (fix find in systemd unit) ==============
allow unconfined_service_t var_log_n_central_t:file open;
allow unconfined_service_t var_log_n_central_t:filesystem getattr;

#============= fs_t (otherwise relabelling wont work) ==============
allow var_log_n_central_t self:filesystem { associate };
allow var_log_n_central_t fs_t:filesystem { associate };
allow var_log_n_central_persist_t fs_t:filesystem { associate };

#============= init_t (or systemd can't init the mount) ==============
allow init_t var_log_n_central_t:dir { getattr read open };
allow init_t var_log_n_central_t:file { getattr read open };