Details
-
Bug
-
Status: Accepted
-
Normal
-
Resolution: Unresolved
-
PUP 3.7.3
-
None
-
None
-
Any SELinux system
-
Night's Watch
Description
Puppet on SELinux enabled systems currently has an issue where the init provider does not start programs into their correct SELinux context.
While this problem was first discovered with Gentoo's openrc provider, this applies for sure to redhat and probably debian as well. Though I don't have a test case for debian at the moment.
The problem is setup like this.
When you start a service under selinux, the program inherits the contexts of the current SELinux user/role/context unless there's a transition to move it to a more appropriate domain.
Thre is a selinux userspace utility called run_init to "help" this along so that init scripts can be called via userspace into their proper context.
The problem illustrated:
This is how sshd likes to run on EL6:
# ps auxZ | grep /usr/sbin/sshd
system_u:system_r:sshd_t:s0-s0:c0.c1023 root 1932 0.0 0.0 66688 1252 ? Ss Dec14 0:00 /usr/sbin/sshd
Now restart the service and see what context it runs under. This, by the way, is how puppet will restart a service. Either with "service" or directly calling the init script - either way the result is the same.
# service sshd restart
Stopping sshd: [ OK ]
Starting sshd: [ OK ]# ps auxZ | grep /usr/sbin/sshd
unconfined_u:system_r:sshd_t:s0-s0:c0.c1023 root 3955 0.5 0.0 66688 1220 ? Ss 03:02 0:00 /usr/sbin/sshd
It should not be too surprising that the root user's selinux user is unconfined_u under EL6:
# id -Z
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
Now when sshd is restarted with run_init:
# run_init service sshd restart
Authenticating root.
Stopping sshd: [ OK ]
Starting sshd: [ OK ]# ps auxZ | grep /usr/sbin/sshd
system_u:system_r:sshd_t:s0-s0:c0.c1023 root 3981 0.0 0.0 66688 1228 ? Ss 03:03 0:00 /usr/sbin/sshd
Correct context!
I'm reasonably close to a solution, but it requires tweaking for non-selinux cases and has a few engineering "concerns".
In short:
1) Drop a run_init command into the provider:
has_command(:run_init, '/usr/sbin/run_init') do
is_optional
end
2) Modify the service calls accordingly.
Eg, statuscmd in the openrc.rb provider goes from this:
command(:rcservice), @resource[:name], :status
...to this:
command(:run_init), command(:rcservice), @resource[:name], :status
This works happily in the openrc example, though it does not work so well in the non-selinux case due to an additional space being prepended to the run_init command being nonexistent.
I'm not clear how to solve that, but that's a solid starting point into fixing this.
This does have an additional issue where any case where run_init is used, a modification to pam needs to be made so the automatic transition is possible. I'm not clear on the general resolution of that.