Certmonger allows for the configuration of a post-save command to be run after it has obtained new certificates. This can be used to copy the key & certificates out of wherever certmonger is allowed to put them, and save them elsewhere with a particular owner/group, combine the certificate & chain into a single file as required by some software, etc.
The problem comes with SELinux which prevents my post-save scripts from being able to do all of that. I thought the solution was to give the scripts the context of certmonger_unconfined_exec_t, which would cause a transition to the certmonger_unconfined_t domain which is as its name suggests unconfined; but I can't get this to work.
I'm trying to use runcon to simulate certmonger executing a fake script:
# cat /tmp/fakescript #!/bin/bash set -eu id -Z
# /tmp/fakescript unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
# ls -Z /tmp/fakescript unconfined_u:object_r:certmonger_unconfined_exec_t:s0 /tmp/fakescript
# runcon system_u:system_r:certmonger_t:s0 /tmp/fakescript runcon: ‘/tmp/fakescript’: Permission denied
Here is the avc denial:
---- type=PROCTITLE msg=audit(27/04/21 16:16:47.156:153492) : proctitle=runcon system_u:system_r:certmonger_t:s0 /tmp/fakescript type=SYSCALL msg=audit(27/04/21 16:16:47.156:153492) : arch=x86_64 syscall=execve success=no exit=EACCES(Permission denied) a0=0x7ffd8aa768ab a1=0x7ffd8aa75888 a2=0x7ffd8aa75898 a3=0x0 items=0 ppid=177795 pid=177796 auid=sam.admin uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=pts5 ses=103 comm=runcon exe=/usr/bin/runcon subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=(null) type=AVC msg=audit(27/04/21 16:16:47.156:153492) : avc: denied { entrypoint } for pid=177796 comm=runcon path=/tmp/fakescript dev="dm-0" ino=33563064 scontext=system_u:system_r:certmonger_t:s0 tcontext=unconfined_u:object_r:certmonger_unconfined_exec_t:s0 tclass=file permissive=0
Even though:
# sepolicy transition -s certmonger_t -t certmonger_unconfined_t certmonger_t @ certmonger_unconfined_exec_t --> certmonger_unconfined_t
Diving in a little deeper, I can see that certmonger can execute the file:
# sesearch -s certmonger_t -t certmonger_unconfined_exec_t -c file -p execute -A allow certmonger_t certmonger_unconfined_exec_t:file { execute execute_no_trans getattr ioctl map open read };
... and that the file type is an entrypoint for the certmonger_unconfined_t domain:
# sesearch -s certmonger_unconfined_t -t certmonger_unconfined_exec_t -c file -p entrypoint -A allow certmonger_unconfined_t certmonger_unconfined_exec_t:file { entrypoint execute getattr ioctl lock map open read };
... and that transition is permitted from certmonger_t:
# sesearch -s certmonger_t -t certmonger_unconfined_t -c process -p transition -A allow certmonger_t certmonger_unconfined_t:process transition;
Which leaves me scratching my head, unsure why it doesn't work in practice...
On Tue, Apr 27, 2021 at 6:46 PM Sam Morris sam@robots.org.uk wrote:
Certmonger allows for the configuration of a post-save command to be run after it has obtained new certificates. This can be used to copy the key & certificates out of wherever certmonger is allowed to put them, and save them elsewhere with a particular owner/group, combine the certificate & chain into a single file as required by some software, etc.
The problem comes with SELinux which prevents my post-save scripts from being able to do all of that. I thought the solution was to give the scripts the context of certmonger_unconfined_exec_t, which would cause a transition to the certmonger_unconfined_t domain which is as its name suggests unconfined; but I can't get this to work.
I'm trying to use runcon to simulate certmonger executing a fake script:
# cat /tmp/fakescript #!/bin/bash set -eu id -Z
# /tmp/fakescript unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
# ls -Z /tmp/fakescript unconfined_u:object_r:certmonger_unconfined_exec_t:s0 /tmp/fakescript
# runcon system_u:system_r:certmonger_t:s0 /tmp/fakescript runcon: ‘/tmp/fakescript’: Permission denied
Here is the avc denial:
type=PROCTITLE msg=audit(27/04/21 16:16:47.156:153492) : proctitle=runcon system_u:system_r:certmonger_t:s0 /tmp/fakescript type=SYSCALL msg=audit(27/04/21 16:16:47.156:153492) : arch=x86_64 syscall=execve success=no exit=EACCES(Permission denied) a0=0x7ffd8aa768ab a1=0x7ffd8aa75888 a2=0x7ffd8aa75898 a3=0x0 items=0 ppid=177795 pid=177796 auid=sam.admin uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=pts5 ses=103 comm=runcon exe=/usr/bin/runcon subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=(null) type=AVC msg=audit(27/04/21 16:16:47.156:153492) : avc: denied { entrypoint } for pid=177796 comm=runcon path=/tmp/fakescript dev="dm-0" ino=33563064 scontext=system_u:system_r:certmonger_t:s0 tcontext=unconfined_u:object_r:certmonger_unconfined_exec_t:s0 tclass=file permissive=0
Even though:
# sepolicy transition -s certmonger_t -t certmonger_unconfined_t certmonger_t @ certmonger_unconfined_exec_t --> certmonger_unconfined_t
Diving in a little deeper, I can see that certmonger can execute the file:
# sesearch -s certmonger_t -t certmonger_unconfined_exec_t -c file -p execute -A allow certmonger_t certmonger_unconfined_exec_t:file { execute execute_no_trans getattr ioctl map open read };
... and that the file type is an entrypoint for the certmonger_unconfined_t domain:
# sesearch -s certmonger_unconfined_t -t certmonger_unconfined_exec_t -c file -p entrypoint -A allow certmonger_unconfined_t certmonger_unconfined_exec_t:file { entrypoint execute getattr ioctl lock map open read };
... and that transition is permitted from certmonger_t:
# sesearch -s certmonger_t -t certmonger_unconfined_t -c process -p transition -A allow certmonger_t certmonger_unconfined_t:process transition;
Which leaves me scratching my head, unsure why it doesn't work in practice...
Hi,
runcon is a useful tool, but its usage is a bit tricky: it can be used to run a process in a different context, but only if policy allows it. Namely, it uses setexeccon(3) to set the new process context and on the very next execvp(2) the context is checked and the change evaluated.
You are right with your commands how to check the 3 important parts to allow a transition. However, in your first command, you see the shell is running in unconfined_t. Is there a transition allowed to certmonger_t?
# sesearch -T -s unconfined_t -c process |grep certmonger_t <>
No. You would actually need a 3-link chain (certmonger_initrc_exec_t, certmonger_exec_t, certmonger_unconfined_exec_t), so it'd be worth writing a custom policy if you need to have it working from console. I still don't quite understand what is to be done there though. For instance, which process executes the post-save commands? Are there any audit records when it fails? Are there additional error messages in journal?
-- Sam Morris https://robots.org.uk/ PGP: rsa4096/CAAA AA1A CA69 A83A 892B 1855 D20B 4202 5CDA 27B9 _______________________________________________ selinux mailing list -- selinux@lists.fedoraproject.org To unsubscribe send an email to selinux-leave@lists.fedoraproject.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/selinux@lists.fedoraproject.or... Do not reply to spam on the list, report it: https://pagure.io/fedora-infrastructure
On Tue, 2021-04-27 at 21:11 +0200, Zdenek Pytela wrote:
runcon is a useful tool, but its usage is a bit tricky: it can be used to run a process in a different context, but only if policy allows it. Namely, it uses setexeccon(3) to set the new process context and on the very next execvp(2) the context is checked and the change evaluated.
You are right with your commands how to check the 3 important parts to allow a transition. However, in your first command, you see the shell is running in unconfined_t. Is there a transition allowed to certmonger_t?
# sesearch -T -s unconfined_t -c process |grep certmonger_t <>
No. You would actually need a 3-link chain (certmonger_initrc_exec_t, certmonger_exec_t, certmonger_unconfined_exec_t), so it'd be worth writing a custom policy if you need to have it working from console.
Ah, so I needed to look at the SYSCALL event, which has subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023, in order to realise that I wasn't really launching the script from the domain that I thought I was...
Thanks for explaining that.
I still don't quite understand what is to be done there though. For instance, which process executes the post-save commands? Are there any audit records when it fails? Are there additional error messages in journal?
In the particular case I was debugging, it looks like certmonger renewed the certificate a long time ago an this useful information has been rotated away.
So, rather than repeatedly renewing the certificate until I got the script working, I wanted to use runcon to simulate certmonger running my script so that I could find out if it was SELinux that prevented the script from working.
Now I understand that the problem was really my assumption that I understood how to use runcon to diagnose this sort of problem. :)
I've now gone back to certmonger and created a tracking request using the SelfSign CA, which I can renew as many times as I want while debugging the script. I've used that to prove that certmonger_unconfined_exec_t does work as expected, and that the problem was therefore with my post-save script and nothing to do with SELinux policy.
Since the existence and usage of certmonger_unconfined_t is a bit under-documented IMO, here's how I proved to myself that this domain can be used to allow certmonger to launch post-save command scripts that are able to do things that certmonger itself is not:
This script tries to create a file in /etc, which SELinux policy will prevent:
$ cat /tmp/fakescript.unconfined #!/bin/sh set -eu -o pipefail id > /etc/fakercert-id -Z
Here's how to use the SelfSign CA to creat a certificate and then invoke the script:
# selfsign-getcert request -w -v -I fakecert -f /etc/pki/tls/certs/fakescript.crt -k /etc/pki/tls/private/fakescript.key -C /tmp/fakescript.unconfined New signing request "fakecert" added. State NEWLY_ADDED_READING_CERT, stuck: no. State GENERATING_CSR, stuck: no. State POST_SAVED_CERT, stuck: no. State MONITORING, stuck: no.
That causes this avc denial; as expected, certmonger_t is not allowed to modify etc_t:
type=AVC msg=audit(28/04/21 11:10:01.147:164884) : avc: denied { create } for pid=187115 comm=fakescript.unconfined name=fakercert-id scontext=system_u:system_r:certmonger_t:s0 tcontext=system_u:object_r:etc_t:s0 tclass=file permissive=0
After using chcon to change the type of the script to certmonger_unconfined_exec_t:
$ ls -Z /tmp/fakescript.unconfined unconfined_u:object_r:certmonger_unconfined_exec_t:s0 /tmp/fakescript.unconfined
... I can tell certmonger to renew the certificate. In doing so it will launch the script--now with the right type to trigger transition to certmonger_unconfined_t:
# getcert resubmit -i fakecert -w -v Resubmitting "fakecert" to "SelfSign". State GENERATING_CSR, stuck: no. State NOTIFYING_ISSUED_SAVED, stuck: no. State MONITORING, stuck: no.
There's now no avc denial, hurrah! And here's the created file:
# cat /etc/fakercert-id context=system_u:system_r:certmonger_unconfined_t:s0
I hope someone else finds that helpful some day!
-- Sam Morris https://robots.org.uk/ PGP: rsa4096/CAAA AA1A CA69 A83A 892B 1855 D20B 4202 5CDA 27B9
Hi,
If I understand correctly, your problem is gone now. If you need some additional help, feel free to reply back.
I spotted one more thing:
On Wed, Apr 28, 2021 at 2:25 PM Sam Morris sam@robots.org.uk wrote:
On Tue, 2021-04-27 at 21:11 +0200, Zdenek Pytela wrote:
runcon is a useful tool, but its usage is a bit tricky: it can be used to run a process in a different context, but only if policy allows it. Namely, it uses setexeccon(3) to set the new process context and on the very next execvp(2) the context is checked and the change evaluated.
You are right with your commands how to check the 3 important parts to allow a transition. However, in your first command, you see the shell is running in unconfined_t. Is there a transition allowed to certmonger_t?
# sesearch -T -s unconfined_t -c process |grep certmonger_t <>
No. You would actually need a 3-link chain (certmonger_initrc_exec_t, certmonger_exec_t, certmonger_unconfined_exec_t), so it'd be worth writing a custom policy if you need to have it working from console.
Ah, so I needed to look at the SYSCALL event, which has subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023, in order to realise that I wasn't really launching the script from the domain that I thought I was...
Thanks for explaining that.
I still don't quite understand what is to be done there though. For instance, which process executes the post-save commands? Are there any audit records when it fails? Are there additional error messages in journal?
In the particular case I was debugging, it looks like certmonger renewed the certificate a long time ago an this useful information has been rotated away.
So, rather than repeatedly renewing the certificate until I got the script working, I wanted to use runcon to simulate certmonger running my script so that I could find out if it was SELinux that prevented the script from working.
Now I understand that the problem was really my assumption that I understood how to use runcon to diagnose this sort of problem. :)
I've now gone back to certmonger and created a tracking request using the SelfSign CA, which I can renew as many times as I want while debugging the script. I've used that to prove that certmonger_unconfined_exec_t does work as expected, and that the problem was therefore with my post-save script and nothing to do with SELinux policy.
Since the existence and usage of certmonger_unconfined_t is a bit under-documented IMO, here's how I proved to myself that this domain can be used to allow certmonger to launch post-save command scripts that are able to do things that certmonger itself is not:
This script tries to create a file in /etc, which SELinux policy will prevent:
$ cat /tmp/fakescript.unconfined #!/bin/sh set -eu -o pipefail id > /etc/fakercert-id -Z
Here's how to use the SelfSign CA to creat a certificate and then invoke the script:
# selfsign-getcert request -w -v -I fakecert -f
/etc/pki/tls/certs/fakescript.crt -k /etc/pki/tls/private/fakescript.key -C /tmp/fakescript.unconfined New signing request "fakecert" added. State NEWLY_ADDED_READING_CERT, stuck: no. State GENERATING_CSR, stuck: no. State POST_SAVED_CERT, stuck: no. State MONITORING, stuck: no.
That causes this avc denial; as expected, certmonger_t is not allowed to modify etc_t:
type=AVC msg=audit(28/04/21 11:10:01.147:164884) : avc: denied {
create } for pid=187115 comm=fakescript.unconfined name=fakercert-id scontext=system_u:system_r:certmonger_t:s0 tcontext=system_u:object_r:etc_t:s0 tclass=file permissive=0
The target context is etc_t, but the only file/dir in the path with this type should be /etc. It is a good idea to relabel some parts of the filesystem before in-deep troubleshooting:
# /sbin/restorecon -Rv /etc
or setup the machine to relabel all filesystems on the next reboot:
# fixfiles onboot and reboot the system.
After using chcon to change the type of the script to certmonger_unconfined_exec_t:
$ ls -Z /tmp/fakescript.unconfined unconfined_u:object_r:certmonger_unconfined_exec_t:s0
/tmp/fakescript.unconfined
... I can tell certmonger to renew the certificate. In doing so it will launch the script--now with the right type to trigger transition to certmonger_unconfined_t:
# getcert resubmit -i fakecert -w -v Resubmitting "fakecert" to "SelfSign". State GENERATING_CSR, stuck: no. State NOTIFYING_ISSUED_SAVED, stuck: no. State MONITORING, stuck: no.
There's now no avc denial, hurrah! And here's the created file:
# cat /etc/fakercert-id context=system_u:system_r:certmonger_unconfined_t:s0
I hope someone else finds that helpful some day!
-- Sam Morris https://robots.org.uk/ PGP: rsa4096/CAAA AA1A CA69 A83A 892B 1855 D20B 4202 5CDA 27B9
On Wed, Apr 28, 2021 at 02:43:29PM +0200, Zdenek Pytela wrote:
If I understand correctly, your problem is gone now. If you need some additional help, feel free to reply back.
I'm digging this thread up because I'm experimenting a bit more with SELinux, this time with confined users, and I came back to the thread while trying to figure some things out...
Originally I was trying to use runcon to reproduce the environment (in terms of process context) that cermonger's post-save scripts run in. It turned out that this wasn't going to work, as Zdenek explained:
On Tue, 2021-04-27 at 21:11 +0200, Zdenek Pytela wrote:
runcon is a useful tool, but its usage is a bit tricky: it can be used to run a process in a different context, but only if policy allows it. Namely, it uses setexeccon(3) to set the new process context and on the very next execvp(2) the context is checked and the change evaluated.
You are right with your commands how to check the 3 important parts to allow a transition. However, in your first command, you see the shell is running in unconfined_t. Is there a transition allowed to certmonger_t?
# sesearch -T -s unconfined_t -c process |grep certmonger_t <>
No. You would actually need a 3-link chain (certmonger_initrc_exec_t, certmonger_exec_t, certmonger_unconfined_exec_t), so it'd be worth writing a custom policy if you need to have it working from console.
For context, I'm experimenting with using the targeted policy's confined users. My user is mapped to staff_u and as such, can SSH in to a machine, but can't use the su command to become root. If I want to do system administrator stuff, I have two options:
1. Run 'newrole -r sysadm_r' and then use 'su' to switch user
2. Use 'sudo -r sysadm_r' which transitions and switches user in a single command; sudo can be configured to perform this transition by default by adding ROLE=sysadm_r to the sudoers entry
So where does that leave the runcon command? What is it typically used for?
I ask because a simple "runcon -r sysadm_r -t sysadm_t id" invocation fails with "runcon: 'id': Permission denied", and the following AVC denial:
avc: denied { transition } for pid=159994 comm="runcon" path="/usr/bin/id" dev="dm-0" ino=4064619 scontext=staff_u:staff_r:staff_t:s0 tcontext=staff_u:sysadm_r:sysadm_t:s0 tclass=process permissive=0
I guess newrole/sudo do additional stuff that's needed in order to transition into the target role.
If runcon doesn't do this extra stuff then what's the proper purpose of the command and how do people use it?
Thanks,
selinux@lists.fedoraproject.org