Bug 2093355

Summary: AVCs when trying to execute a command through qemu-ga ("guest-exec" command)
Product: Red Hat Enterprise Linux 8 Reporter: Renaud Métrich <rmetrich>
Component: selinux-policyAssignee: Zdenek Pytela <zpytela>
Status: CLOSED ERRATA QA Contact: Milos Malik <mmalik>
Severity: medium Docs Contact: Jan Fiala <jafiala>
Priority: medium    
Version: 8.6CC: amepatil, apeetham, coli, demeng, gfialova, jinzhao, juzhang, lvrabec, marcandre.lureau, mmalik, phou, qizhu, virt-maint, zpytela
Target Milestone: rcKeywords: Triaged
Target Release: 8.9Flags: jafiala: needinfo+
jafiala: needinfo+
pm-rhel: mirror+
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: selinux-policy-3.14.3-118.el8 Doc Type: Enhancement
Doc Text:
.New SELinux boolean to allow QEMU Guest Agent executing confined commands Previously, commands that were supposed to execute in a confined context through the QEMU Guest Agent daemon program, such as `mount`, failed with an Access Vector Cache (AVC) denial. To be able to execute these commands, the `guest-agent` must run in the `virt_qemu_ga_unconfined_t` domain. Therefore, this update adds the SELinux policy boolean `virt_qemu_ga_run_unconfined` that allows `guest-agent` to make the transition to `virt_qemu_ga_unconfined_t` for executables located in any of the following directories: * `/etc/qemu-ga/fsfreeze-hook.d/` * `/usr/libexec/qemu-ga/fsfreeze-hook.d/` * `/var/run/qemu-ga/fsfreeze-hook.d/` In addition, the necessary rules for transitions for the `qemu-ga` daemon have been added to the SELinux policy boolean. As a result, you can now execute confined commands through the QEMU Guest Agent without AVC denials by enabling the `virt_qemu_ga_run_unconfined` boolean.
Story Points: ---
Clone Of: Environment:
Last Closed: 2023-11-14 15:47:42 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Renaud Métrich 2022-06-03 14:09:25 UTC
Description of problem:

We have a customer trying to execute commands through qemu-agent, similarly to what VMWare provides with "vmrun":
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
$ virsh qemu-agent-command domain '{"execute":"guest-exec", ...
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

Commands that are supposed to execute in a confined context (e.g. "mount") fail due to an AVC popping up:
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
type=PROCTITLE msg=audit(06/03/2022 15:39:26.449:72) : proctitle=/usr/bin/qemu-ga --method=virtio-serial --path=/dev/virtio-ports/org.qemu.guest_agent.0 --blacklist= -F/etc/qemu-ga/fsfreeze-hoo 
type=SYSCALL msg=audit(06/03/2022 15:39:26.449:72) : arch=x86_64 syscall=execve success=no exit=EACCES(Permission denied) a0=0x55bff8ef9df9 a1=0x55bff8ed6780 a2=0x7ffeb34343a8 a3=0x8 items=0 ppid=1603 pid=1605 auid=unset uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=(none) ses=unset comm=qemu-ga exe=/usr/bin/qemu-ga subj=system_u:system_r:virt_qemu_ga_t:s0 key=(null) 
type=AVC msg=audit(06/03/2022 15:39:26.449:72) : avc:  denied  { execute } for  pid=1605 comm=qemu-ga name=mount dev="dm-0" ino=33712610 scontext=system_u:system_r:virt_qemu_ga_t:s0 tcontext=system_u:object_r:mount_exec_t:s0 tclass=file permissive=0 
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

This happens because the service, executing as "virt_qemu_ga_t", cannot execute commands because of missing rules in the policy (here above for "mount_exec_t").

The solution is similar to what was implemented for VMTools (BZ #1667016):
we need to have a transition happening in qemu-ga when executing a command to something like "virt_qemu_ga_unconfined_t".

This of course requires changes in the SELinux policy. Please sync with them.

Version-Release number of selected component (if applicable):

qemu-guest-agent-6.2.0-11.module+el8.6.0+14707+5aa4b42d.x86_64

How reproducible:

Always

Steps to Reproduce:
1. Disable blacklisting in /etc/sysconfig/qemu-ga

    #BLACKLIST_RPC=...

2. Restart the service

3. Execute a command from the host

Actual results:

AVC

Expected results:

No AVC

Additional infos:

A workaround (but it's not a viable solution in the long term) is to execute the service as an unconfined domain, e.g. "unconfined_service_t", which can be achieved using a shell script wrapper.

Comment 1 dehanmeng 2022-06-09 00:51:35 UTC
Try to reproduce it on qemu side but didn't reproduce this issue. will try to run it on libvirt side. And actually, if /etc/sysconfig/qemu-ga file changed, qga.service should've been restarted, btw. maybe you did that but didn't write it down there, if the whole operations are correct and configurations are well.

Comment 2 Renaud Métrich 2022-06-09 05:32:09 UTC
Yes sorry I restarts the service after changing /etc/sysconfig/qemu-ga.

Comment 3 dehanmeng 2022-06-14 06:47:37 UTC
(In reply to Renaud Métrich from comment #2)
> Yes sorry I restarts the service after changing /etc/sysconfig/qemu-ga.

okay, I got it. Could you please provide the XML file you used to boot up VM? it would be better for us to reproduce the same issue.

Comment 21 Marc-Andre Lureau 2022-06-21 08:10:47 UTC
See discussion "qemu-ga guest-exec & SELinux" from selinux-fedora List:
https://lists.fedoraproject.org/archives/list/selinux@lists.fedoraproject.org/thread/LWL4WVO42KVFGZZDXATPBUDTPU36S5BK/

Daniel Berrange said:
"IMHO execution of external commands should only be allowed after toggling
a SELinux boolean tunable."

It looks like we should find a selinux solution. In Fedora first, before it can be backported. I am moving the bug back to selinux.

Thanks

Comment 22 Renaud Métrich 2022-06-21 08:37:26 UTC
I think there is no need for any additional SELinux boolean as long as the child of the service in charge of executing the command runs in the "unconfined domain".

Comment 23 Zdenek Pytela 2023-02-08 16:42:33 UTC
Merged in rawhide, we will consider it to backport to rhel 8.8 or 8.9.

Comment 33 dehanmeng 2023-08-28 08:58:28 UTC
the new pck should not be ready yet right?  I was testing 'selinux-policy-38.1.23-1.el9' but there is no active booleans at all.

Comment 35 Milos Malik 2023-08-28 09:05:15 UTC
This BZ is filed against RHEL-8.

@demeng , please use the latest selinux-policy build for RHEL-8: selinux-policy-3.14.3-128.el8

Comment 42 dehanmeng 2023-08-29 02:20:04 UTC
Hi all, 
After executing the above steps as comment 16&37&39, I paste some output and results here, but the final result is that I couldn't execute qga command 'guest-exec' successfully.

output:
[root@vm-73-228 ~]# semanage fcontext -l | grep virt_qemu_ga_unco
/etc/qemu-ga/fsfreeze-hook.d(/.*)?                 all files          system_u:object_r:virt_qemu_ga_unconfined_exec_t:s0 
/usr/libexec/qemu-ga/fsfreeze-hook.d(/.*)?         all files          system_u:object_r:virt_qemu_ga_unconfined_exec_t:s0 
/usr/local/bin/qemu-quest-agent-wrapper            all files          system_u:object_r:virt_qemu_ga_unconfined_exec_t:s0 
/var/run/qemu-ga/fsfreeze-hook.d(/.*)?             all files          system_u:object_r:virt_qemu_ga_unconfined_exec_t:s0 


results:

{"execute":"guest-exec","arguments":{"path":"qemu-quest-agent-wrapper","arg":["mount","-l"],"input-data":"","capture-output":true}}
{"error": {"class": "CommandNotFound", "desc": "Command guest-exec has been disabled"}}
{"execute":"guest-exec-status","arguments":{"pid":948}}
{"error": {"class": "CommandNotFound", "desc": "Command guest-exec-status has been disabled"}}

anything is not correct? or does it require libvirt only?

Comment 43 Milos Malik 2023-08-29 13:17:53 UTC
I believe that the mount command is usually present on RHEL machines. Which means that the CommandNotFound error belongs to the qemu-quest-agent-wrapper command.

Did you create the qemu-quest-agent-wrapper file?

Comment 45 Zdenek Pytela 2023-08-30 07:49:32 UTC
(In reply to dehanmeng from comment #44)
> (In reply to Milos Malik from comment #43)
> > I believe that the mount command is usually present on RHEL machines. Which
> > means that the CommandNotFound error belongs to the qemu-quest-agent-wrapper
> > command.
> > 
> > Did you create the qemu-quest-agent-wrapper file?
> 
> [root@vm-73-228 selinux-policy]# cat /usr/local/bin/qemu-quest-agent-wrapper 
> #!/bin/sh
> 
> echo "$(basename $0) executing as $(id -Z)"
> exec "${@:-}"
> 
> anything I need to change?

I believe no need for a change, but check permissions+context of the wrapper and look for AVC denials if there are any:

ls -lZ /usr/local/bin/qemu-quest-agent-wrapper
ausearch -i -m avc,user_avc,selinux_err,user_selinux_err -ts today

Is the searched path configured comewhere? Isn't it necessary to include full path instead of just the wrapper name?
execute":"guest-exec","arguments":{"path":"qemu-quest-agent-wrapper","arg":["mount","-l"],"input-data":"","capture-output":true}}

Comment 46 dehanmeng 2023-08-30 07:57:54 UTC
(In reply to Zdenek Pytela from comment #45)
> (In reply to dehanmeng from comment #44)
> > (In reply to Milos Malik from comment #43)
> > > I believe that the mount command is usually present on RHEL machines. Which
> > > means that the CommandNotFound error belongs to the qemu-quest-agent-wrapper
> > > command.
> > > 
> > > Did you create the qemu-quest-agent-wrapper file?
> > 
> > [root@vm-73-228 selinux-policy]# cat /usr/local/bin/qemu-quest-agent-wrapper 
> > #!/bin/sh
> > 
> > echo "$(basename $0) executing as $(id -Z)"
> > exec "${@:-}"
> > 
> > anything I need to change?
> 
> I believe no need for a change, but check permissions+context of the wrapper
> and look for AVC denials if there are any:
> 
> ls -lZ /usr/local/bin/qemu-quest-agent-wrapper

[root@vm-73-228 ~]# ls -lZ /usr/local/bin/qemu-quest-agent-wrapper
-rwxr-xr-x. 1 root root unconfined_u:object_r:virt_qemu_ga_unconfined_exec_t:s0 69 Aug 28 17:59 /usr/local/bin/qemu-quest-agent-wrapper

> ausearch -i -m avc,user_avc,selinux_err,user_selinux_err -ts today

[root@vm-73-228 ~]# ausearch -i -m avc,user_avc,selinux_err,user_selinux_err -ts today
<no matches>

> 
> Is the searched path configured comewhere? Isn't it necessary to include
> full path instead of just the wrapper name?
> execute":"guest-exec","arguments":{"path":"qemu-quest-agent-wrapper","arg":
> ["mount","-l"],"input-data":"","capture-output":true}}

I actually tested it with both absolute/relative path, and always get that error.

Comment 51 Nikola Knazekova 2023-09-26 12:52:30 UTC
LGTM

Comment 54 errata-xmlrpc 2023-11-14 15:47:42 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory (selinux-policy bug fix and enhancement update), and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2023:7091

Comment 59 Red Hat Bugzilla 2024-08-28 04:25:03 UTC
The needinfo request[s] on this closed bug have been removed as they have been unresolved for 120 days