Note: This bug is displayed in read-only format because the product is no longer active in Red Hat Bugzilla.
RHEL Engineering is moving the tracking of its product development work on RHEL 6 through RHEL 9 to Red Hat Jira (issues.redhat.com). If you're a Red Hat customer, please continue to file support cases via the Red Hat customer portal. If you're not, please head to the "RHEL project" in Red Hat Jira and file new tickets here. Individual Bugzilla bugs in the statuses "NEW", "ASSIGNED", and "POST" are being migrated throughout September 2023. Bugs of Red Hat partners with an assigned Engineering Partner Manager (EPM) are migrated in late September as per pre-agreed dates. Bugs against components "kernel", "kernel-rt", and "kpatch" are only migrated if still in "NEW" or "ASSIGNED". If you cannot log in to RH Jira, please consult article #7032570. That failing, please send an e-mail to the RH Jira admins at rh-issues@redhat.com to troubleshoot your issue as a user management inquiry. The email creates a ServiceNow ticket with Red Hat. Individual Bugzilla bugs that are migrated will be moved to status "CLOSED", resolution "MIGRATED", and set with "MigratedToJIRA" in "Keywords". The link to the successor Jira issue will be found under "Links", have a little "two-footprint" icon next to it, and direct you to the "RHEL project" in Red Hat Jira (issue links are of type "https://issues.redhat.com/browse/RHEL-XXXX", where "X" is a digit). This same link will be available in a blue banner at the top of the page informing you that that bug has been migrated.

Bug 1871135

Summary: virtqemud forward net-xx command to virtnetworkd and execute it as root for unprivileged user with polkit enabled
Product: Red Hat Enterprise Linux 9 Reporter: yalzhang <yalzhang>
Component: DocumentationAssignee: Jiri Herrmann <jherrman>
Documentation sub component: default QA Contact: yalzhang <yalzhang>
Status: CLOSED CURRENTRELEASE Docs Contact:
Severity: medium    
Priority: medium CC: berrange, fjin, haoli, jherrman, jsuchane, kkiwi, lcheng, rhel-docs, virt-maint, xuzhang, yacao, yisun, ymankad
Version: 9.0Keywords: Reopened, Triaged
Target Milestone: betaFlags: pm-rhel: mirror+
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2023-01-02 15:53:05 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:
Bug Depends On:    
Bug Blocks: 1897025    

Description yalzhang@redhat.com 2020-08-21 12:03:37 UTC
Description of problem:
polkit setting can not work with split daemon

Version-Release number of selected component (if applicable):
# rpm -q libvirt polkit
libvirt-6.6.0-2.module+el8.3.0+7567+dc41c0a9.x86_64
polkit-0.115-11.el8.x86_64

How reproducible:
100%

Steps to Reproduce:
1. Enable split daemon:
# systemctl stop libvirtd.service# systemctl stop libvirtd{,-ro,-admin,-tcp,-tls}.socket
# for drv in qemu interface network nodedev nwfilter secret storage; do systemctl unmask virt${drv}d.service; systemctl unmask virt${drv}d{,-ro,-admin}.socket; systemctl enable virt${drv}d.service; systemctl enable virt${drv}d{,-ro,-admin}.socket; done
#  for drv in qemu network nodedev nwfilter secret storage; do systemctl start virt${drv}d{,-ro,-admin}.socket; done

2. Edit the /etc/libvirt/virtqemud.conf  to enable 'polkit' as the Access control driver:
# cat /etc/libvirt/virtqemud.conf
...
access_drivers = [ "polkit" ]
unix_sock_rw_perms = "0777"
auth_unix_rw = "none"

# systemctl restart virtqemud

3. add unprivileged user:
# useradd test1
# passwd test1
# su - test1

4. connected to qemu:///system as unprivileged user:
$ virsh -c qemu:///system
Welcome to virsh, the virtualization interactive terminal.

Type:  'help' for help with commands
       'quit' to quit

virsh # list --all
 Id   Name   State
-----------------------
 -    rel    shut off

virsh # start rel
error: Failed to start domain rel
error: access denied: 'QEMU' denied access   ----> this is expected as no polkit rules set

virsh # net-list --all
 Name      State    Autostart   Persistent
--------------------------------------------
 default   active   yes         yes
 net-1     active   no          yes

virsh # net-destroy net-1 Network net-1 destroyed   -------> should fail

Actual results:
In step 4, when we execute the net-destroy command, the virtqemud forward the command unchanged to virtnetworkd, but it seems virtnetworkd execute the command as root.

Expected results:
In step 4, the net-destroy command should fail as we connected as unprivileged user

Additional info:
Once we configure /etc/libvirt/virtnetworkd.conf to enable 'polkit' as the Access control driver just as the virtqemud.conf, the result is as expected:

$ virsh -c qemu:///system
Welcome to virsh, the virtualization interactive terminal.

Type:  'help' for help with commands
       'quit' to quit

virsh # net-list --all
 Name      State    Autostart   Persistent
--------------------------------------------
 default   active   yes         yes
 net-1     active   no          yes

virsh # net-destroy net-1
error: Failed to destroy network net-1
error: access denied: 'network' denied access

Comment 1 yalzhang@redhat.com 2020-08-27 04:25:38 UTC
same with nwfilter-define/ nwfilter-undefine

Comment 3 Daniel Berrangé 2020-12-03 16:47:52 UTC
(In reply to yalzhang from comment #0)
> Description of problem:
> polkit setting can not work with split daemon
> 
> Version-Release number of selected component (if applicable):
> # rpm -q libvirt polkit
> libvirt-6.6.0-2.module+el8.3.0+7567+dc41c0a9.x86_64
> polkit-0.115-11.el8.x86_64
> 
> How reproducible:
> 100%
> 
> Steps to Reproduce:
> 1. Enable split daemon:
> # systemctl stop libvirtd.service# systemctl stop
> libvirtd{,-ro,-admin,-tcp,-tls}.socket
> # for drv in qemu interface network nodedev nwfilter secret storage; do
> systemctl unmask virt${drv}d.service; systemctl unmask
> virt${drv}d{,-ro,-admin}.socket; systemctl enable virt${drv}d.service;
> systemctl enable virt${drv}d{,-ro,-admin}.socket; done
> #  for drv in qemu network nodedev nwfilter secret storage; do systemctl
> start virt${drv}d{,-ro,-admin}.socket; done
> 
> 2. Edit the /etc/libvirt/virtqemud.conf  to enable 'polkit' as the Access
> control driver:
> # cat /etc/libvirt/virtqemud.conf
> ...
> access_drivers = [ "polkit" ]
> unix_sock_rw_perms = "0777"
> auth_unix_rw = "none"
> 
> # systemctl restart virtqemud
> 
> 3. add unprivileged user:
> # useradd test1
> # passwd test1
> # su - test1
> 
> 4. connected to qemu:///system as unprivileged user:
> $ virsh -c qemu:///system
> Welcome to virsh, the virtualization interactive terminal.
> 
> Type:  'help' for help with commands
>        'quit' to quit
> 
> virsh # list --all
>  Id   Name   State
> -----------------------
>  -    rel    shut off
> 
> virsh # start rel
> error: Failed to start domain rel
> error: access denied: 'QEMU' denied access   ----> this is expected as no
> polkit rules set
> 
> virsh # net-list --all
>  Name      State    Autostart   Persistent
> --------------------------------------------
>  default   active   yes         yes
>  net-1     active   no          yes
> 
> virsh # net-destroy net-1 Network net-1 destroyed   -------> should fail
> 
> Actual results:
> In step 4, when we execute the net-destroy command, the virtqemud forward
> the command unchanged to virtnetworkd, but it seems virtnetworkd execute the
> command as root.
> 
> Expected results:
> In step 4, the net-destroy command should fail as we connected as
> unprivileged user

> 
> Additional info:
> Once we configure /etc/libvirt/virtnetworkd.conf to enable 'polkit' as the
> Access control driver just as the virtqemud.conf, the result is as expected:

Yes, this is the key.

I think that overall this bug report simply reflects a configuration mistake.

If you're going to enable polkit access control with the modular daemons it
needs to be enabled on all of them at once.

Admittedly this isn't exactly obvious at first glance, but with the way we
proxy API calls between daemons there's no real way around it.

Comment 4 yalzhang@redhat.com 2021-10-21 03:55:09 UTC
Test on latest rhel 9 libvirt-7.8.0-1.el9.x86_64, all the commands net-destroy/start net-define/undefine can not work as expected. I'm not sure if the configuration need to be updated, please help to have a look, Thank you!
 
1. Current rhel 9 enable modular daemons by default, configure the daemons by below script:
# cd /etc/libvirt
# cat edit_polkit.sh
#!/bin/bash
for drv in qemu interface network nodedev nwfilter secret storage proxy;
do
cp virt${drv}d.conf  virt${drv}d.conf_bak
cat>>virt${drv}d.conf<<EOF
access_drivers = [ "polkit" ] 
unix_sock_rw_perms = "0777"
auth_unix_rw = "none"
EOF
systemctl restart virt${drv}d.service;
done
# sh edit_polkit.sh
 
2. Add user:
# useradd test1
# passwd test1
 
3. Add polkit rules:
# cat /etc/polkit-1/rules.d/100-libvirt.rules 
polkit.addRule(function(action, subject) {
    if (action.id == 'org.libvirt.api.network.stop' && subject.user == 'test1') {
        if (action.lookup('connect_driver') == 'QEMU' && action.lookup('network_name') == 'default') {
            return polkit.Result.YES;
        } else {
            return polkit.Result.NO;
        }
    }
});
 
4. Try to destroy the default network:
# su - test1 -c '/usr/bin/virsh -c network:///system net-destroy default'
error: Failed to destroy network default
error: access denied: 'network' denied access

# su - test1 -c '/usr/bin/virsh -c qemu:///system net-destroy  default'
error: Failed to destroy network default
error: access denied: 'network' denied access
 
If change to monolithic daemon libvirtd, the command executed successfully by:
# su - test1 -c '/usr/bin/virsh -c qemu:///system net-destroy  default'

Comment 5 yalzhang@redhat.com 2021-10-28 02:33:53 UTC
After discuss with yafu, the configuration in comment 4 is incorrect.

Update the connect_driver to be "network", the command succeed:
# cat /etc/polkit-1/rules.d/100-libvirt.rules 
polkit.addRule(function(action, subject) {
    if (action.id == 'org.libvirt.api.network.stop' && subject.user == 'test1') {
        if (action.lookup('connect_driver') == 'network' && action.lookup('network_name') == 'default') {
            return polkit.Result.YES;
        } else {
            return polkit.Result.NO;
        }
    }
});

Both works:
# su - test1 -c '/usr/bin/virsh -c qemu:///system net-destroy default'
Network default destroyed

(start network default on another terminal)

# su - test1 -c '/usr/bin/virsh -c network:///system net-destroy default'
Network default destroyed

Comment 6 yalzhang@redhat.com 2021-10-28 05:23:02 UTC
The positive scenario in comment 4 and 5 proves the statement in comment 3 from Daniel.

But the issue on comment 0 still exists on libvirt-7.8.0-1.el9.x86_64, which I think may be a security issue.

1. Enable polkit *only* in /etc/libvirt/virtqemud.conf, but do not add any polkit rules;

2. Try to destroy network with unprivileged user:

# su - test1 -c '/usr/bin/virsh -c network:///system net-destroy default'
Error creating textual authentication agent: Error opening current controlling terminal for the process (`/dev/tty'): No such device or address (polkit-error-quark, 0)
error: failed to connect to the hypervisor
error: authentication unavailable: no polkit agent available to authenticate action 'org.libvirt.unix.manage'

# su - test1 -c '/usr/bin/virsh -c qemu:///system net-destroy default'
Network default destroyed

When we connect to qemu:///system, it succeeds unexpectedly. Same with nwfilter, nodedev, 

# su - test1 -c '/usr/bin/virsh -c qemu:///system nwfilter-undefine  qemu-announce-self'
Network filter qemu-announce-self undefined

# su - test1 -c '/usr/bin/virsh -c qemu:///system nodedev-list --cap net'
net_eno1_34_48_ed_f8_d8_b8
net_eno2_34_48_ed_f8_d8_b9
...

# su - test1 -c '/usr/bin/virsh -c qemu:///system nodedev-detach pci_0000_3b_00_1'
error: Failed to detach device pci_0000_3b_00_1
error: access denied: 'QEMU' denied access

Comment 7 yalzhang@redhat.com 2021-10-28 06:49:52 UTC
And I have another question about the polkit rule setting. 
"action.lookup('connect_driver') == 'QEMU'" works well with monolithic daemon libvirtd. When we transfer to modular daemon, it can not work and needs to be updated to "action.lookup('connect_driver') == 'network'". Is there any backward compatibility concern here?

Comment 8 Daniel Berrangé 2021-10-28 08:41:39 UTC
(In reply to yalzhang from comment #6)
> The positive scenario in comment 4 and 5 proves the statement in comment 3
> from Daniel.
> 
> But the issue on comment 0 still exists on libvirt-7.8.0-1.el9.x86_64, which
> I think may be a security issue.
> 
> 1. Enable polkit *only* in /etc/libvirt/virtqemud.conf, but do not add any
> polkit rules;

As per my earlier comment, this is considered a configuration mistake. It needs to be enabled all all the modular daemons that you will use.
(In reply to yalzhang from comment #7)
> And I have another question about the polkit rule setting. 
> "action.lookup('connect_driver') == 'QEMU'" works well with monolithic
> daemon libvirtd. When we transfer to modular daemon, it can not work and
> needs to be updated to "action.lookup('connect_driver') == 'network'". Is
> there any backward compatibility concern here?

Existing deployments using libvirtd will continue to use libvirt after in-place upgrades. So this change only affects new deployments, and we consider that an acceptable change in behaviour - arguably it is now a more accurate check.

Comment 9 yalzhang@redhat.com 2021-10-29 09:15:24 UTC
(In reply to Daniel Berrangé from comment #8)
> (In reply to yalzhang from comment #6)
> > The positive scenario in comment 4 and 5 proves the statement in comment 3
> > from Daniel.
> > 
> > But the issue on comment 0 still exists on libvirt-7.8.0-1.el9.x86_64, which
> > I think may be a security issue.
> > 
> > 1. Enable polkit *only* in /etc/libvirt/virtqemud.conf, but do not add any
> > polkit rules;
> 
> As per my earlier comment, this is considered a configuration mistake. It
> needs to be enabled all all the modular daemons that you will use.

Hi Daniel, Thank you for quick the answer. Yes, this is a configuration mistake. But with this configuration mistake, unprivileged user without polkit rules can destroy and start the network, I think it's not safe and need a fix, what do you think?

Comment 11 RHEL Program Management 2022-02-21 07:27:24 UTC
After evaluating this issue, there are no plans to address it further or fix it in an upcoming release.  Therefore, it is being closed.  If plans change such that this issue will be fixed in an upcoming release, then the bug can be reopened.

Comment 14 yalzhang@redhat.com 2022-08-01 02:02:48 UTC
Hi Daniel, do you think we need a fix to this bug? Or we can close it as won't fix?

Comment 16 Daniel Berrangé 2022-08-05 15:21:57 UTC
There are no code changes planned, given that this is just a config mistake (comment #8). I was leaving it open as a documentation task though.

Comment 17 RHEL Program Management 2022-08-22 07:28:28 UTC
After evaluating this issue, there are no plans to address it further or fix it in an upcoming release.  Therefore, it is being closed.  If plans change such that this issue will be fixed in an upcoming release, then the bug can be reopened.

Comment 30 yalzhang@redhat.com 2022-12-19 03:43:27 UTC
Hi Jiri, the command does not work as expected.
# find /etc/libvirt/ -name virt*d.conf | sed -i 's/#access_drivers = [ "polkit" ]/access_drivers = [ "polkit" ]'
sed: -e expression #1, char 62: unterminated `s' command

And I have tried this one works well:
# find /etc/libvirt/ -name virt*d.conf -exec sed -i 's/#access_drivers = \[ "polkit" \]/access_drivers = \[ "polkit" \]/g' {} +

After the update, the file updated as expected:
# find /etc/libvirt/ -name virt*d.conf   -exec  grep 'access_drivers'  {} +
/etc/libvirt/virtproxyd.conf:access_drivers = [ "polkit" ]
/etc/libvirt/virtstoraged.conf:access_drivers = [ "polkit" ]
/etc/libvirt/virtnetworkd.conf:access_drivers = [ "polkit" ]
/etc/libvirt/virtnwfilterd.conf:access_drivers = [ "polkit" ]
/etc/libvirt/virtinterfaced.conf:access_drivers = [ "polkit" ]
/etc/libvirt/virtnodedevd.conf:access_drivers = [ "polkit" ]
/etc/libvirt/virtsecretd.conf:access_drivers = [ "polkit" ]
/etc/libvirt/virtqemud.conf:access_drivers = [ "polkit" ]

Comment 31 yalzhang@redhat.com 2022-12-19 08:29:06 UTC
and for rhel 8, the same issue:
# sed -i 's/#access_drivers = [ "polkit" ]/access_drivers = [ "polkit" ]' /etc/libvirt/libvirtd.conf

use below command instead can update the file as expected.
# sed -i 's/#access_drivers = \[ "polkit" \]/access_drivers = \[ "polkit" \]/' /etc/libvirt/libvirtd.conf

And the file name suffix it better to be ".rules" instead of ".conf"
> Create a new .conf file in the /etc/polkit-1/rules.d/ directory.