Mailing List Archive

run_init + pipes
I have been struggling to get my hardened systems managed by Ansible for
quite some time now. I have almost everything working well now, except
service control. It seems like the run_init stuff in OpenRC behaves
strangely when /sbin/rc-service is called via exec(),
stdin/stdout/stderr are connected to pipes, and the whole thing is run
through sudo. I suspect it has something to do with the way run_init
tries to prompt for credentials (even though I have that "disabled").

Here's what I've got set up:

-----------------

test-bd06fe ~ # grep -Ev '^#|^$' /etc/selinux/config
SELINUX=permissive
SELINUXTYPE=strict

test-bd06fe ~ # getenforce
Permissive

test-bd06fe ~ # cat /etc/pam.d/run_init
#%PAM-1.0
# Uncomment the next line if you do not want to enter your passwd everytime
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

test-bd06fe ~ # cat /etc/sudoers.d/root
root ALL = (ALL) ROLE=sysadm_r TYPE=sysadm_t ALL

test-bd06fe ~ # cat test2.py
import subprocess

p = subprocess.Popen(['/sbin/rc-service', 'nfsmount', 'restart'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
o, e = p.communicate()
print('exitcode: {}'.format(p.returncode))
print('stdout: {}'.format(o))
print('stderr: {}'.format(e))

test-bd06fe ~ # python2.7 test2.py
exitcode: 0
stdout: * Starting NFS sm-notify ... [ ok ]
* Mounting NFS filesystems ... [ ok ]

stderr:

test-bd06fe ~ # rc-service nfsmount status
* status: started

test-bd06fe ~ # rc-service nfsmount stop
* Unmounting NFS filesystems ...
[ ok ]

test-bd06fe ~ # sudo python2.7 test2.py
exitcode: 0
stdout:
stderr:

test-bd06fe ~ # rc-service nfsmount status
* status: stopped

-----------------

As you can see, this happens even when SELinux is not enforcing, so I
don't think it is policy related. I wonder if there is some way to stop
run_init from trying to prompt for authentication altogether, especially
when stdin/stdout/stderr is not a tty.

Any thoughts or pointers would be appreciated.

Thanks,

--
♫Dustin
http://dustin.hatch.name/
Re: run_init + pipes [ In reply to ]
On Thu, Apr 24, 2014 at 07:13:45PM -0500, Dustin C. Hatch wrote:
> I have been struggling to get my hardened systems managed by Ansible for
> quite some time now. I have almost everything working well now, except
> service control. It seems like the run_init stuff in OpenRC behaves
> strangely when /sbin/rc-service is called via exec(),
> stdin/stdout/stderr are connected to pipes, and the whole thing is run
> through sudo. I suspect it has something to do with the way run_init
> tries to prompt for credentials (even though I have that "disabled").
[...]
> p = subprocess.Popen(['/sbin/rc-service', 'nfsmount', 'restart'],
> stdin=subprocess.PIPE,
> stdout=subprocess.PIPE,
> stderr=subprocess.PIPE)
> o, e = p.communicate()
> print('exitcode: {}'.format(p.returncode))
> print('stdout: {}'.format(o))
> print('stderr: {}'.format(e))

Try calling rc-service through run_init, so something like

#v+
p = subprocess.Popen(['/sbin/run_init', '/sbin/rc-service', 'nfsmount',
'restart']...)
#v-

[...]
> As you can see, this happens even when SELinux is not enforcing, so I
> don't think it is policy related. I wonder if there is some way to stop
> run_init from trying to prompt for authentication altogether, especially
> when stdin/stdout/stderr is not a tty.
>
> Any thoughts or pointers would be appreciated.

There's some magic involved, see my small write-up at
http://blog.siphos.be/2013/04/not-needing-run_init-for-password-less-service-management/

Wkr,
Sven Vermeulen
Re: run_init + pipes [ In reply to ]
On 04/27/2014 09:01 AM, Sven Vermeulen wrote:
> On Thu, Apr 24, 2014 at 07:13:45PM -0500, Dustin C. Hatch wrote:
>> I have been struggling to get my hardened systems managed by Ansible for
>> quite some time now. I have almost everything working well now, except
>> service control. It seems like the run_init stuff in OpenRC behaves
>> strangely when /sbin/rc-service is called via exec(),
>> stdin/stdout/stderr are connected to pipes, and the whole thing is run
>> through sudo. I suspect it has something to do with the way run_init
>> tries to prompt for credentials (even though I have that "disabled").
> [...]
>> p = subprocess.Popen(['/sbin/rc-service', 'nfsmount', 'restart'],
>> stdin=subprocess.PIPE,
>> stdout=subprocess.PIPE,
>> stderr=subprocess.PIPE)
>> o, e = p.communicate()
>> print('exitcode: {}'.format(p.returncode))
>> print('stdout: {}'.format(o))
>> print('stderr: {}'.format(e))
>
> Try calling rc-service through run_init, so something like
>
> #v+
> p = subprocess.Popen(['/sbin/run_init', '/sbin/rc-service', 'nfsmount',
> 'restart']...)
> #v-
>

I really have no control over how rc-service gets called, since it is
handled by Ansible. I did try using run_init in my example code, but
that caused it to fail 100% of the time, not just when run by sudo. This
leads me to believe that the problem is in run_init itself.

Further testing finally revealed an error when I connected stdout and
stderr to pipes, but left stdin connected to the console:

tcgetattr:: Inappropriate ioctl for device

It would seem run_init is unconditionally trying to manipulate stdout as
if it were a TTY, which may be the problem.

> [...]
>> As you can see, this happens even when SELinux is not enforcing, so I
>> don't think it is policy related. I wonder if there is some way to stop
>> run_init from trying to prompt for authentication altogether, especially
>> when stdin/stdout/stderr is not a tty.
>>
>> Any thoughts or pointers would be appreciated.
>
> There's some magic involved, see my small write-up at
> http://blog.siphos.be/2013/04/not-needing-run_init-for-password-less-service-management/
>

Thanks, I've read that post a few times, and it does help me understand
how the transition takes place. I don't think this problem is directly
SELinux related anymore though, but rather a bug in run_init. I'll try
to track it down.


--
♫Dustin
http://dustin.hatch.name/