Hello, I'm puzzled by how libvirtd manages access control. As far as I can tell, on my Fedora system it runs qemu and virtiofsd instances as user qemu. Yet, the qemu process apparently has read/write access to storage devices in /dev that only root has rw access for. Similarly, virtiofsd is able to write into shared directories that the qemu user does not have access to (confirmed by switching to qemu user with sudo). What is libvirtd (or virt-manager) doing to make this work? Then, as far as I can tell, there's lots of sockets with different permissions created by systemd in /run/libvirt (e.g. libvirt-admin-sock, libvirt-sock, libvirt-sock-ro). But since they're all passed to libvirtd as open file descriptors, I don't understand how they can give different levels of access (since libvirtd has no way of knowing which socket was used). What am I missing? Best, -Nikolaus
On Thu, Dec 04, 2025 at 19:22:12 -0000, nikolaus@rath.org wrote:
Hello,
I'm puzzled by how libvirtd manages access control.
As far as I can tell, on my Fedora system it runs qemu and virtiofsd instances as user qemu. Yet, the qemu process apparently has read/write access to storage devices in /dev that only root has rw access for. Similarly, virtiofsd is able to write into shared directories that the qemu user does not have access to (confirmed by switching to qemu user with sudo).
What is libvirtd (or virt-manager) doing to make this work?
For entries in /dev/ libvirt creates a separate mount namespace for the qemu process to run in and then adds all nodes which the VM definition points to (the XML). These are then chown'd to 'qemu' user so that the qemu process has access to it. All of that without modifying the host /dev/. In case mount namespaces are disabled you'd see some node files to be chown'd to qemu. Files in the regular filesystem are chown'd to the qemu user, so they should be accessible. In the "system" (qemu:///system) privileged instance of libvirt 'virtiofsd' still runs as root IIRC because it also wants to to be able to honour UID changes from the guest on the host. In the unprivileged instance uid mapping can be used to map users from the VM to the host.
Then, as far as I can tell, there's lots of sockets with different permissions created by systemd in /run/libvirt (e.g. libvirt-admin-sock, libvirt-sock, libvirt-sock-ro). But since they're all passed to libvirtd as open file descriptors, I don't understand how they can give different levels of access (since libvirtd has no way of knowing which socket was used).
Libvirt actually does know what socket you've used to connect to it and actually also knows the UID of the connecting client. This allows filtering access on a granular level with our ACL support.
On Fri, 5 Dec 2025, at 07:59, Peter Krempa wrote:
On Thu, Dec 04, 2025 at 19:22:12 -0000, nikolaus@rath.org wrote:
Hello,
I'm puzzled by how libvirtd manages access control.
As far as I can tell, on my Fedora system it runs qemu and virtiofsd instances as user qemu. Yet, the qemu process apparently has read/write access to storage devices in /dev that only root has rw access for. Similarly, virtiofsd is able to write into shared directories that the qemu user does not have access to (confirmed by switching to qemu user with sudo).
What is libvirtd (or virt-manager) doing to make this work?
For entries in /dev/ libvirt creates a separate mount namespace for the qemu process to run in and then adds all nodes which the VM definition points to (the XML). These are then chown'd to 'qemu' user so that the qemu process has access to it. All of that without modifying the host /dev/. In case mount namespaces are disabled you'd see some node files to be chown'd to qemu.
Ah, that makes sense. Thanks!
In the "system" (qemu:///system) privileged instance of libvirt 'virtiofsd' still runs as root IIRC because it also wants to to be able to honour UID changes from the guest on the host.
Ah, right you are. Somehow I was assuming this would run as qemu as well.
Then, as far as I can tell, there's lots of sockets with different permissions created by systemd in /run/libvirt (e.g. libvirt-admin-sock, libvirt-sock, libvirt-sock-ro). But since they're all passed to libvirtd as open file descriptors, I don't understand how they can give different levels of access (since libvirtd has no way of knowing which socket was used).
Libvirt actually does know what socket you've used to connect to it and actually also knows the UID of the connecting client. This allows filtering access on a granular level with our ACL support.
Hmm.. I'm still confused that none of the socket names are mentioned anywhere in the libvirtd config. For example, if I grep for `sock-ro` or `admin-sock` in /etc/libvirt, I get no matches. Do you know how I could find out what the default permissions are for each socket? And lastly, how do I tell virt-manager what socket to use? The qemu://system URL doesn't seem to directly map to any socket.... Thanks for all your help! Best, -Nikolaus
On Fri, Dec 05, 2025 at 12:34:37 +0000, Nikolaus Rath wrote:
On Fri, 5 Dec 2025, at 07:59, Peter Krempa wrote:
On Thu, Dec 04, 2025 at 19:22:12 -0000, nikolaus@rath.org wrote
[...]
Then, as far as I can tell, there's lots of sockets with different permissions created by systemd in /run/libvirt (e.g. libvirt-admin-sock, libvirt-sock, libvirt-sock-ro). But since they're all passed to libvirtd as open file descriptors, I don't understand how they can give different levels of access (since libvirtd has no way of knowing which socket was used).
Libvirt actually does know what socket you've used to connect to it and actually also knows the UID of the connecting client. This allows filtering access on a granular level with our ACL support.
Hmm.. I'm still confused that none of the socket names are mentioned anywhere in the libvirtd config. For example, if I grep for `sock-ro` or `admin-sock` in /etc/libvirt, I get no matches.
The full names are not mentioned, but the corresponing settings in each config file for the daemon are: unix_sock_group unix_sock_ro_perms unix_sock_rw_perms etc. The documentation also outlines the settings. Also if you use socket activation (e.g. virtqemud.socket unit) then the corresponding unit file is taken for config
Do you know how I could find out what the default permissions are for each socket?
In short if polkit authentication is enabled then both sockets have 0777 mode and authentication is delegated to polkit. By default polkit ought to allow users having admin privileges to also access the write-enabled libvirt daemon system instance socket. If polkit is not in use you can set the group and default permission either in the config file or in the corresponding '.socket' systemd unit file if you use systemd socket activation.
And lastly, how do I tell virt-manager what socket to use? The qemu://system URL doesn't seem to directly map to any socket....
Normally you don't. The socket gets picked based on the URI and whether you are opening a read-only or read write connection and the socket is placed in a well-known path. ( /run/libvirt/libvirt-sock (virtqemud/virtstoraged etc for per-daemon versions) for qemu://system (or the -ro variant), or e.g. /run/user/1000/libvirt/virtqemud-sock or the appropriate XDG runtime directory for the qemu:///session instances.)
Hi,
And lastly, how do I tell virt-manager what socket to use? The qemu://system URL doesn't seem to directly map to any socket....
Normally you don't. The socket gets picked based on the URI and whether you are opening a read-only or read write connection and the socket is placed in a well-known path.
Searching for the definition of how to declare a "read only" URL, I looked at https://libvirt.org/uri.html ; but it doesn't mention the option (instead referring to virConnectReadOnly() ). I also searched the code base, but couldn't find where "readonliness" is extracted from the URL. If you can provide the URL parameter for read-only, I'll want to send a patch for the docs to list it. Regards, -- Bye, Erik. http://efficito.com -- Hosted accounting and ERP. Robust and Flexible. No vendor lock-in.
On Fri, Dec 05, 2025 at 15:54:40 +0100, Erik Huelsmann wrote:
Hi,
And lastly, how do I tell virt-manager what socket to use? The qemu://system URL doesn't seem to directly map to any socket....
Normally you don't. The socket gets picked based on the URI and whether you are opening a read-only or read write connection and the socket is placed in a well-known path.
Searching for the definition of how to declare a "read only" URL, I looked at https://libvirt.org/uri.html ; but it doesn't mention the option (instead referring to virConnectReadOnly() ). I also searched the code base, but couldn't find where "readonliness" is extracted from the URL. If you can provide the URL parameter for read-only, I'll want to send a patch for the docs to list it.
Yes, the read-only connection is opened by using the API you mention. That's the reason why the socket paths are also not something we expose because the URI and method used to open connection will infer it.
And lastly, how do I tell virt-manager what socket to use? The qemu://system URL doesn't seem to directly map to any socket....
Normally you don't. The socket gets picked based on the URI and whether you are opening a read-only or read write connection
In my virt-manager, there is no read-only option when I click on "Add-Connection". There's a "Hypervisor" dropdown and an ͺ"Autoconnect" checkbox, but nothing about read-only. Are we talking about a different element of the UI? Best, -Nikolaus
On Fri, 5 Dec 2025, at 14:31, Peter Krempa wrote:
Then, as far as I can tell, there's lots of sockets with different permissions created by systemd in /run/libvirt (e.g. libvirt-admin-sock, libvirt-sock, libvirt-sock-ro). But since they're all passed to libvirtd as open file descriptors, I don't understand how they can give different levels of access (since libvirtd has no way of knowing which socket was used).
Libvirt actually does know what socket you've used to connect to it and actually also knows the UID of the connecting client. This allows filtering access on a granular level with our ACL support.
Hmm.. I'm still confused that none of the socket names are mentioned anywhere in the libvirtd config. For example, if I grep for `sock-ro` or `admin-sock` in /etc/libvirt, I get no matches.
The full names are not mentioned, but the corresponing settings in each config file for the daemon are:
unix_sock_group unix_sock_ro_perms unix_sock_rw_perms
etc.
The documentation also outlines the settings.
Right. But these define the permissions of the socket when unit activation is not used. What I'm asking is, assuming someone has permission to connect to a socket, which operations can be done through the different sockets? I assume there has to be a difference, otherwise why have different sockets. Best, -Nikolaus
participants (5)
-
brent s. -
Erik Huelsmann -
Nikolaus Rath -
nikolaus@rath.org -
Peter Krempa