Mailing List Archive

Running rc-service without run_init
I'm fairly new to SELinux, and I am trying to get a server set up with
SELinux running. I use Ansible for configuration management, and I am
having some trouble getting it working with SELinux in Enforcing mode.
Most stuff is working fine, with the major exception of controlling
OpenRC services.

Ansible connects to the server as an unprivileged user (typically the
user running it) over SSH and then executes all change commands via
sudo. This works for most things, like copying files, etc., but if it
has to restart a service after making a configuration change, it fails.
I am not sure how to configure SELinux policy and/or sudo to get the
user into the correct context to be able to restart arbitrary services.
I cannot use run_init because Ansible does not know how to do so.

Here's what I've tried so far:

Create local user 'dustin':
useradd -m dustin

Authorize 'dustin' to run commands with sudo:
test-3238ec ~ # cat /etc/sudoers.d/dustin
dustin ALL = (ALL) ALL

Test dustin's sudo access:
dustin@test-3238ec ~ $ sudo id
Password:
uid=0(root) gid=0(root)
groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),26(tape),27(video)
context=user_u:user_r:user_t

Map dustin to staff_u SELinux User:
semanage login -a -s staff_u dustin
chcon -R -u staff_u -r object_r /home/dustin

Test dustin's sudo access again:
dustin@test-3238ec ~ $ sudo id
Password:
uid=0(root) gid=0(root)
groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),26(tape),27(video)
context=staff_u:staff_r:staff_t
dustin@test-3238ec ~ $ sudo -r sysadm_r -t sysadm_t id
uid=0(root) gid=0(root)
groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),26(tape),27(video)
context=staff_u:sysadm_r:sysadm_t

Okay, dustin can now run system commands:
dustin@test-3238ec ~ $ sudo -r sysadm_r -t sysadm_t mv /etc/fstab{,.bak}
dustin@test-3238ec ~ $ ls /etc/fstab*
/etc/fstab.bak

dustin is not able to control services without run_init and the root
password:
dustin@test-3238ec ~ $ sudo -r sysadm_r -t sysadm_t rc-service nfsmount
restart
Authenticating root.
Cannot find your entry in the shadow passwd file.
dustin@test-3238ec ~ $ sudo -r sysadm_r -t sysadm_t run_init rc-service
nfsmount restart
Authenticating root.
Password:
* Unmounting NFS filesystems ... [ ok ]
* Starting NFS sm-notify ... [ ok ]
* Mounting NFS filesystems ... [ ok ]

Add pam_rootok to pam.d/run_init:
test-3238ec ~ # cat /etc/pam.d/run_init
#%PAM-1.0
auth sufficient pam_rootok.so
auth include system-auth
account include system-auth
password include system-auth
session include system-auth
session optional pam_xauth.so

This allows dustin to control services using run_init without knowing
the root password:
dustin@test-3238ec ~ $ sudo -r sysadm_r -t sysadm_t run_init rc-service
nfsmount restart
Authenticating root.
* Unmounting NFS filesystems ... [ ok ]
* Starting NFS sm-notify ... [ ok ]
* Mounting NFS filesystems ... [ ok ]

My understanding is that in order to be able to control services, one
needs to have the system_r role[1]. I don't know how to get there, though:
dustin@test-3238ec ~ $ sudo -r system_r rc-service nfsmount restart
Password:
sudo: unable to get default type for role system_r
sudo: unable to execute /sbin/rc-service: Invalid argument
dustin@test-3238ec ~ $ sudo -r system_r -t sysadm_t rc-service nfsmount
restart
sudo: staff_u:system_r:sysadm_t is not a valid context
sudo: unable to execute /sbin/rc-service: Invalid argument
dustin@test-3238ec ~ $ sudo -r system_r -t run_init_t rc-service
nfsmount restart
sudo: staff_u:system_r:run_init_t is not a valid context
sudo: unable to execute /sbin/rc-service: Invalid argument

I tried a policy change that should allow OpenRC to make the transition
for me[2] but it did not work:
test-3238ec ~ # make -f /usr/share/selinux/strict/include/Makefile
localruninit.pp
Compiling strict localruninit module
/usr/bin/checkmodule: loading policy configuration from
tmp/localruninit.tmp
/usr/bin/checkmodule: policy configuration loaded
/usr/bin/checkmodule: writing binary representation (version 16) to
tmp/localruninit.mod
Creating strict localruninit.pp policy package
rm tmp/localruninit.mod tmp/localruninit.mod.fc
test-3238ec ~ # semodule -i localruninit.pp
dustin@test-3238ec ~ $ sudo -r sysadm_r -t sysadm_t rc-service nfsmount
restart
Password:
Authenticating root.
Cannot find your entry in the shadow passwd file.

I'm not sure where to go from here. Any help would be appreciated.

[1]
http://selinux-mac.blogspot.com/2009/06/selinux-lockdown-part-seven-su-newrole.html
[2]
http://blog.siphos.be/2013/04/not-needing-run_init-for-password-less-service-management/

--
♫Dustin
http://dustin.hatch.name/
Re: Running rc-service without run_init [ In reply to ]
On Sat, Jan 11, 2014 at 11:34:43PM -0600, Dustin C. Hatch wrote:
> Ansible connects to the server as an unprivileged user (typically the
> user running it) over SSH and then executes all change commands via
> sudo. This works for most things, like copying files, etc., but if it
> has to restart a service after making a configuration change, it fails.
> I am not sure how to configure SELinux policy and/or sudo to get the
> user into the correct context to be able to restart arbitrary services.
> I cannot use run_init because Ansible does not know how to do so.
>
> Here's what I've tried so far:
[.... user mapped to staff_u so it is granted staff_r/sysadm_r roles ...]
[.... pam_rootok.so used in run_init to remove root password requirement ...]
> My understanding is that in order to be able to control services, one
> needs to have the system_r role[1]. I don't know how to get there, though:
> dustin@test-3238ec ~ $ sudo -r system_r rc-service nfsmount restart
> Password:
> sudo: unable to get default type for role system_r
> sudo: unable to execute /sbin/rc-service: Invalid argument
> dustin@test-3238ec ~ $ sudo -r system_r -t sysadm_t rc-service nfsmount
> restart
> sudo: staff_u:system_r:sysadm_t is not a valid context
> sudo: unable to execute /sbin/rc-service: Invalid argument
> dustin@test-3238ec ~ $ sudo -r system_r -t run_init_t rc-service
> nfsmount restart
> sudo: staff_u:system_r:run_init_t is not a valid context
> sudo: unable to execute /sbin/rc-service: Invalid argument

You shouldn't directly mention system_r (as role) in sudo at any point as
far as I know. Either a role is granted the right to start services directly
(which is used for the services that use what I call "named init scripts")
or the role is allowed the run_init_t domain and calls it through
run_init.

In Gentoo, OpenRC calls run_init internally so you don't need to pass it on
directly when invoked through a shell. But it does require the policy change
as you mentioned (but you don't need to add it yourself, it should already
be in the Gentoo policy).

> I tried a policy change that should allow OpenRC to make the transition
> for me[2] but it did not work:
[...]
> dustin@test-3238ec ~ $ sudo -r sysadm_r -t sysadm_t rc-service nfsmount
> restart
> Password:
> Authenticating root.
> Cannot find your entry in the shadow passwd file.
>
> I'm not sure where to go from here. Any help would be appreciated.

I'll look into it (it's reproduceable).

Seems that the trick from the blog post doesn't work for sudo. As far as I
can see, the transition to the sysadm_r role and sysadm_t domain work
nicely, and rc-service is a regular bin_t (so it's not about mismatching
transitions).

In the mean time you can use "sudo run_init rc-service nfsmount" and grant
the user the rights for it in the sudoers file. You can also directly enter
the ROLE= and TYPE= parameters in the sudoers file so that you don't need to
pass it on directly.

Wkr,
Sven Vermeulen
Re: Running rc-service without run_init [ In reply to ]
On Sun, Jan 12, 2014 at 12:30:57PM +0100, Sven Vermeulen wrote:
> > dustin@test-3238ec ~ $ sudo -r sysadm_r -t sysadm_t rc-service nfsmount
> > restart
> > Password:
> > Authenticating root.
> > Cannot find your entry in the shadow passwd file.
> >
> > I'm not sure where to go from here. Any help would be appreciated.
>
> I'll look into it (it's reproduceable).
>
> Seems that the trick from the blog post doesn't work for sudo. As far as I
> can see, the transition to the sysadm_r role and sysadm_t domain work
> nicely, and rc-service is a regular bin_t (so it's not about mismatching
> transitions).

I think I found it. It seemed that the integrated run_init support, provided
through the runscript_selinux.so library that we provide (for OpenRC) didn't
use PAM authentication, even when policycoreutils was built with USE="pam".

This is because the ebuild didn't use the python-r1.eclass BUILD_DIR
location (where the files were compiled earlier in the phase) but the
"normal" ${S} location (which contains the sources). As a result, the "make
install" phase started building the code, without taking the various USE
flags into account, and then installing those files.

I've pushed out policycoreutils-2.2.5-r2 which should fix this, and the
following sudoers like allowed me to check the status of the SSH service
without root password request, and without the error on shadow entries:

oper ALL=(root) ROLE=sysadm_r TYPE=sysadm_t NOPASSWD: /sbin/rc-service

~$ sudo rc-service sshd status
Authenticating root.
* status: started

Previously, this also gave the mentioned "Cannot find your entry in the
shadow passwd file." error.

Wkr,
Sven Vermeulen
Re: Running rc-service without run_init [ In reply to ]
On 01/12/2014 05:30 AM, Sven Vermeulen wrote:
> On Sat, Jan 11, 2014 at 11:34:43PM -0600, Dustin C. Hatch wrote:
>> My understanding is that in order to be able to control services, one
>> needs to have the system_r role[1]. I don't know how to get there, though:
>
> You shouldn't directly mention system_r (as role) in sudo at any point as
> far as I know. Either a role is granted the right to start services directly
> (which is used for the services that use what I call "named init scripts")
> or the role is allowed the run_init_t domain and calls it through
> run_init.
>
That's what I thought; these were really just stabs in the dark.
> In Gentoo, OpenRC calls run_init internally so you don't need to pass it on
> directly when invoked through a shell. But it does require the policy change
> as you mentioned (but you don't need to add it yourself, it should already
> be in the Gentoo policy).
>
I should have mentioned that even as root, with or without pam_rootok, I
can't call rc-service without run_init first.
> ...
> Seems that the trick from the blog post doesn't work for sudo. As far as I
> can see, the transition to the sysadm_r role and sysadm_t domain work
> nicely, and rc-service is a regular bin_t (so it's not about mismatching
> transitions).
>
Again, forgot to mention that not only sudo suffers from this problem.
Even logged in as root (on the console or via SSH and then newrole), I
need run_init to control services.
> In the mean time you can use "sudo run_init rc-service nfsmount" and grant
> the user the rights for it in the sudoers file. You can also directly enter
> the ROLE= and TYPE= parameters in the sudoers file so that you don't need to
> pass it on directly.
>
In my original tests, I was using ROLE= and TYPE= in sudoers; I switched
to command line arguments in order to be explicit on this message.
> Wkr,
> Sven Vermeulen
>
Thanks for your help.

--
♫Dustin
http://dustin.hatch.name/
Re: Running rc-service without run_init [ In reply to ]
On 01/12/2014 07:54 AM, Sven Vermeulen wrote:
> On Sun, Jan 12, 2014 at 12:30:57PM +0100, Sven Vermeulen wrote:
>>> dustin@test-3238ec ~ $ sudo -r sysadm_r -t sysadm_t rc-service nfsmount
>>> restart
>>> Password:
>>> Authenticating root.
>>> Cannot find your entry in the shadow passwd file.
>>>
>>> I'm not sure where to go from here. Any help would be appreciated.
>>
>> I'll look into it (it's reproduceable).
>>
>> Seems that the trick from the blog post doesn't work for sudo. As far as I
>> can see, the transition to the sysadm_r role and sysadm_t domain work
>> nicely, and rc-service is a regular bin_t (so it's not about mismatching
>> transitions).
>
> I think I found it. It seemed that the integrated run_init support, provided
> through the runscript_selinux.so library that we provide (for OpenRC) didn't
> use PAM authentication, even when policycoreutils was built with USE="pam".
>
> This is because the ebuild didn't use the python-r1.eclass BUILD_DIR
> location (where the files were compiled earlier in the phase) but the
> "normal" ${S} location (which contains the sources). As a result, the "make
> install" phase started building the code, without taking the various USE
> flags into account, and then installing those files.
>
> I've pushed out policycoreutils-2.2.5-r2 which should fix this, and the
> following sudoers like allowed me to check the status of the SSH service
> without root password request, and without the error on shadow entries:
>
> oper ALL=(root) ROLE=sysadm_r TYPE=sysadm_t NOPASSWD: /sbin/rc-service
>
> ~$ sudo rc-service sshd status
> Authenticating root.
> * status: started
>
> Previously, this also gave the mentioned "Cannot find your entry in the
> shadow passwd file." error.
>
> Wkr,
> Sven Vermeulen
>
Cool, I've kicked off a catalyst rebuild of my SELinux stage[1234] and
will deploy a new test VM as soon as its done. I'll let you know how it
goes.

Thanks again for your help.

--
♫Dustin
http://dustin.hatch.name/
Re: Running rc-service without run_init [ In reply to ]
On 01/12/2014 08:44 AM, Dustin C. Hatch wrote:
> On 01/12/2014 07:54 AM, Sven Vermeulen wrote:
>> On Sun, Jan 12, 2014 at 12:30:57PM +0100, Sven Vermeulen wrote:
>>>> dustin@test-3238ec ~ $ sudo -r sysadm_r -t sysadm_t rc-service nfsmount
>>>> restart
>>>> Password:
>>>> Authenticating root.
>>>> Cannot find your entry in the shadow passwd file.
>>>>
>>>> I'm not sure where to go from here. Any help would be appreciated.
>>>
>>> I'll look into it (it's reproduceable).
>>>
>>> Seems that the trick from the blog post doesn't work for sudo. As far as I
>>> can see, the transition to the sysadm_r role and sysadm_t domain work
>>> nicely, and rc-service is a regular bin_t (so it's not about mismatching
>>> transitions).
>>
>> I think I found it. It seemed that the integrated run_init support, provided
>> through the runscript_selinux.so library that we provide (for OpenRC) didn't
>> use PAM authentication, even when policycoreutils was built with USE="pam".
>>
>> This is because the ebuild didn't use the python-r1.eclass BUILD_DIR
>> location (where the files were compiled earlier in the phase) but the
>> "normal" ${S} location (which contains the sources). As a result, the "make
>> install" phase started building the code, without taking the various USE
>> flags into account, and then installing those files.
>>
>> I've pushed out policycoreutils-2.2.5-r2 which should fix this, and the
>> following sudoers like allowed me to check the status of the SSH service
>> without root password request, and without the error on shadow entries:
>>
>> oper ALL=(root) ROLE=sysadm_r TYPE=sysadm_t NOPASSWD: /sbin/rc-service
>>
>> ~$ sudo rc-service sshd status
>> Authenticating root.
>> * status: started
>>
>> Previously, this also gave the mentioned "Cannot find your entry in the
>> shadow passwd file." error.
>>
>> Wkr,
>> Sven Vermeulen
>>
> Cool, I've kicked off a catalyst rebuild of my SELinux stage[1234] and
> will deploy a new test VM as soon as its done. I'll let you know how it
> goes.
>
> Thanks again for your help.
>
It is indeed working now, thank you. Is there any chance this can be
backported to 2.1?

--
♫Dustin
http://dustin.hatch.name/
Re: Running rc-service without run_init [ In reply to ]
On Sun, Jan 12, 2014 at 11:44:56AM -0600, Dustin C. Hatch wrote:
> >> I think I found it. It seemed that the integrated run_init support, provided
> >> through the runscript_selinux.so library that we provide (for OpenRC) didn't
> >> use PAM authentication, even when policycoreutils was built with USE="pam".
> >>
> >> This is because the ebuild didn't use the python-r1.eclass BUILD_DIR
> >> location (where the files were compiled earlier in the phase) but the
> >> "normal" ${S} location (which contains the sources). As a result, the "make
> >> install" phase started building the code, without taking the various USE
> >> flags into account, and then installing those files.
[...]
> > Cool, I've kicked off a catalyst rebuild of my SELinux stage[1234] and
> > will deploy a new test VM as soon as its done. I'll let you know how it
> > goes.
> >
> > Thanks again for your help.
> >
> It is indeed working now, thank you. Is there any chance this can be
> backported to 2.1?

Certainly; policycoreutils-2.1.14-r5 is now in tree with the same fix.

Wkr,
Sven Vermeulen
Re: Running rc-service without run_init [ In reply to ]
This patch makes run_init unneccessary for "normal" init scripts (those
labeled initrc_exec_t). However, it's still neccessary for scripts with
custom types, such as iptables.

Looking at the openrc code clearly shows that rc-service doesn't make
any attempt to transition to the correct domain (initrc_t) beforce
execv()'ing the script.

Are there any plans to change this?


Regards,
Luis


--
Luis Ressel <aranea@aixah.de>
GPG fpr: F08D 2AF6 655E 25DE 52BC E53D 08F5 7F90 3029 B5BD
Re: Running rc-service without run_init [ In reply to ]
On Sat, Jan 25, 2014 at 08:48:25PM +0100, Luis Ressel wrote:
> This patch makes run_init unneccessary for "normal" init scripts (those
> labeled initrc_exec_t). However, it's still neccessary for scripts with
> custom types, such as iptables.
>
> Looking at the openrc code clearly shows that rc-service doesn't make
> any attempt to transition to the correct domain (initrc_t) beforce
> execv()'ing the script.
>
> Are there any plans to change this?

OpenRC doesn't do much SELinux specific here, beyond calling the run_init
code. There are no plans (from me) currently to update the behavior to also
support the other, named init scripts as this should be handled by the
policy.

When a named script exists, there usually is an interface for that domain as
well that allows the given role/type to execute the script and have it
transition to the right domain and role.

For instance, for postgresql_initrc_exec_t, you have postgresql_admin(). If
you assign this to, say, sysadm_t/sysadm_r, then the regular system
administrator on the system can handle these services as well.
I have tried to implement a rule that grants an "operate all service
scripts" privilege to a domain, but that didn't work out fine (yet). That
being said, there is a build option (I think it is called direct_sysadm or
so) that should support this - but that breaks the integrated run_init
implementation iirc.

Wkr,
Sven Vermeulen