From: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Date: Thu, 9 Apr 2026 10:52:00 +0800
Subject: dnsmasq-as-priv-user

Title: Run DNSMASQ as libvirt-dnsmasq user
DEP: 3
Drivers: Serge Hallyn
URL: https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/938255

Dropped in Artful for security reasons: https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/1690729
Readded in improved Bionic: https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/1743718
Debian nack: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=862340

Abstract:
 Generally it's bad form from a security perspective to run daemons as user
 nobody because a vulnerability in one daemon will possibly allow it, when
 compromised, to interfere with another daemon that is also running as nobody.
 The preferred solution is to run it as a service-specific system user. In this
 case, because there may be multiple dnsmasq daemons running, a separate
 libvirt-dnsmasq user (the dnsmasq package itself runs the dnsmasq daemon under
 a system user called unsurprisingly 'dnsmasq').
---
 src/network/bridge_driver.c                                        | 3 ++-
 tests/networkxml2confdata/dhcp6-nat-network.conf                   | 1 +
 tests/networkxml2confdata/dhcp6-network.conf                       | 1 +
 tests/networkxml2confdata/dhcp6host-routed-network.conf            | 1 +
 tests/networkxml2confdata/dnsmasq-options.conf                     | 1 +
 tests/networkxml2confdata/isolated-network.conf                    | 1 +
 tests/networkxml2confdata/leasetime-hours.conf                     | 1 +
 tests/networkxml2confdata/leasetime-infinite.conf                  | 1 +
 tests/networkxml2confdata/leasetime-minutes.conf                   | 1 +
 tests/networkxml2confdata/leasetime-seconds.conf                   | 1 +
 tests/networkxml2confdata/nat-network-dns-forward-plain.conf       | 1 +
 tests/networkxml2confdata/nat-network-dns-forwarder-no-resolv.conf | 1 +
 tests/networkxml2confdata/nat-network-dns-forwarders.conf          | 1 +
 tests/networkxml2confdata/nat-network-dns-hosts.conf               | 1 +
 tests/networkxml2confdata/nat-network-dns-local-domain.conf        | 1 +
 tests/networkxml2confdata/nat-network-dns-srv-record-minimal.conf  | 1 +
 tests/networkxml2confdata/nat-network-dns-srv-record.conf          | 1 +
 tests/networkxml2confdata/nat-network-dns-txt-record.conf          | 1 +
 tests/networkxml2confdata/nat-network-mtu.conf                     | 1 +
 tests/networkxml2confdata/nat-network-name-with-quotes.conf        | 1 +
 tests/networkxml2confdata/nat-network.conf                         | 1 +
 tests/networkxml2confdata/netboot-network.conf                     | 1 +
 tests/networkxml2confdata/netboot-proxy-network.conf               | 1 +
 tests/networkxml2confdata/netboot-tftp.conf                        | 1 +
 tests/networkxml2confdata/open-network.conf                        | 1 +
 tests/networkxml2confdata/ptr-domains-auto.conf                    | 1 +
 tests/networkxml2confdata/routed-network-no-dns.conf               | 1 +
 tests/networkxml2confdata/routed-network.conf                      | 1 +
 28 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 8b5dbb3..15d8b1e 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -1185,7 +1185,8 @@ networkDnsmasqConfContents(virNetworkObj *obj,
                       "##    virsh net-edit %s\n"
                       "## or other application using the libvirt API.\n"
                       "##\n## dnsmasq conf file created by libvirt\n"
-                      "strict-order\n",
+                      "strict-order\n"
+                      "user=libvirt-dnsmasq\n",
                       def->name);
 
     /* if dns is disabled, set its listening port to 0, which
diff --git a/tests/networkxml2confdata/dhcp6-nat-network.conf b/tests/networkxml2confdata/dhcp6-nat-network.conf
index 536974e..7df91b8 100644
--- a/tests/networkxml2confdata/dhcp6-nat-network.conf
+++ b/tests/networkxml2confdata/dhcp6-nat-network.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 except-interface=lo
 bind-dynamic
 interface=virbr0
diff --git a/tests/networkxml2confdata/dhcp6-network.conf b/tests/networkxml2confdata/dhcp6-network.conf
index 8270690..38f1690 100644
--- a/tests/networkxml2confdata/dhcp6-network.conf
+++ b/tests/networkxml2confdata/dhcp6-network.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 domain=mynet
 expand-hosts
 except-interface=lo
diff --git a/tests/networkxml2confdata/dhcp6host-routed-network.conf b/tests/networkxml2confdata/dhcp6host-routed-network.conf
index 87a1498..e62211a 100644
--- a/tests/networkxml2confdata/dhcp6host-routed-network.conf
+++ b/tests/networkxml2confdata/dhcp6host-routed-network.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 except-interface=lo
 bind-dynamic
 interface=virbr1
diff --git a/tests/networkxml2confdata/dnsmasq-options.conf b/tests/networkxml2confdata/dnsmasq-options.conf
index 867f355..dfa4a54 100644
--- a/tests/networkxml2confdata/dnsmasq-options.conf
+++ b/tests/networkxml2confdata/dnsmasq-options.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 except-interface=lo
 bind-dynamic
 interface=virbr0
diff --git a/tests/networkxml2confdata/isolated-network.conf b/tests/networkxml2confdata/isolated-network.conf
index ea66bb8..32b599b 100644
--- a/tests/networkxml2confdata/isolated-network.conf
+++ b/tests/networkxml2confdata/isolated-network.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 except-interface=lo
 bind-dynamic
 interface=virbr2
diff --git a/tests/networkxml2confdata/leasetime-hours.conf b/tests/networkxml2confdata/leasetime-hours.conf
index 1599d46..5d4f76a 100644
--- a/tests/networkxml2confdata/leasetime-hours.conf
+++ b/tests/networkxml2confdata/leasetime-hours.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 except-interface=lo
 bind-dynamic
 interface=virbr0
diff --git a/tests/networkxml2confdata/leasetime-infinite.conf b/tests/networkxml2confdata/leasetime-infinite.conf
index 883ced6..423b76c 100644
--- a/tests/networkxml2confdata/leasetime-infinite.conf
+++ b/tests/networkxml2confdata/leasetime-infinite.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 except-interface=lo
 bind-dynamic
 interface=virbr0
diff --git a/tests/networkxml2confdata/leasetime-minutes.conf b/tests/networkxml2confdata/leasetime-minutes.conf
index c093501..0f47496 100644
--- a/tests/networkxml2confdata/leasetime-minutes.conf
+++ b/tests/networkxml2confdata/leasetime-minutes.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 except-interface=lo
 bind-dynamic
 interface=virbr0
diff --git a/tests/networkxml2confdata/leasetime-seconds.conf b/tests/networkxml2confdata/leasetime-seconds.conf
index 8b2a81c..f844f64 100644
--- a/tests/networkxml2confdata/leasetime-seconds.conf
+++ b/tests/networkxml2confdata/leasetime-seconds.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 except-interface=lo
 bind-dynamic
 interface=virbr0
diff --git a/tests/networkxml2confdata/nat-network-dns-forward-plain.conf b/tests/networkxml2confdata/nat-network-dns-forward-plain.conf
index 9a000b8..97c0435 100644
--- a/tests/networkxml2confdata/nat-network-dns-forward-plain.conf
+++ b/tests/networkxml2confdata/nat-network-dns-forward-plain.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 except-interface=lo
 bind-dynamic
 interface=virbr0
diff --git a/tests/networkxml2confdata/nat-network-dns-forwarder-no-resolv.conf b/tests/networkxml2confdata/nat-network-dns-forwarder-no-resolv.conf
index 52d000a..d80b6f6 100644
--- a/tests/networkxml2confdata/nat-network-dns-forwarder-no-resolv.conf
+++ b/tests/networkxml2confdata/nat-network-dns-forwarder-no-resolv.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 server=/example.com/192.168.1.1
 except-interface=lo
 bind-dynamic
diff --git a/tests/networkxml2confdata/nat-network-dns-forwarders.conf b/tests/networkxml2confdata/nat-network-dns-forwarders.conf
index fcaf7e7..7627ae6 100644
--- a/tests/networkxml2confdata/nat-network-dns-forwarders.conf
+++ b/tests/networkxml2confdata/nat-network-dns-forwarders.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 server=8.8.8.8
 server=8.8.4.4
 server=/example.com/192.168.1.1
diff --git a/tests/networkxml2confdata/nat-network-dns-hosts.conf b/tests/networkxml2confdata/nat-network-dns-hosts.conf
index 021316f..15b668a 100644
--- a/tests/networkxml2confdata/nat-network-dns-hosts.conf
+++ b/tests/networkxml2confdata/nat-network-dns-hosts.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 domain=example.com
 expand-hosts
 domain-needed
diff --git a/tests/networkxml2confdata/nat-network-dns-local-domain.conf b/tests/networkxml2confdata/nat-network-dns-local-domain.conf
index 5f41b91..d48609b 100644
--- a/tests/networkxml2confdata/nat-network-dns-local-domain.conf
+++ b/tests/networkxml2confdata/nat-network-dns-local-domain.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 local=/example.com/
 domain=example.com
 expand-hosts
diff --git a/tests/networkxml2confdata/nat-network-dns-srv-record-minimal.conf b/tests/networkxml2confdata/nat-network-dns-srv-record-minimal.conf
index bd560ba..d47d401 100644
--- a/tests/networkxml2confdata/nat-network-dns-srv-record-minimal.conf
+++ b/tests/networkxml2confdata/nat-network-dns-srv-record-minimal.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 except-interface=lo
 bind-dynamic
 interface=virbr0
diff --git a/tests/networkxml2confdata/nat-network-dns-srv-record.conf b/tests/networkxml2confdata/nat-network-dns-srv-record.conf
index 22bf3b1..19d8689 100644
--- a/tests/networkxml2confdata/nat-network-dns-srv-record.conf
+++ b/tests/networkxml2confdata/nat-network-dns-srv-record.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 except-interface=lo
 bind-dynamic
 interface=virbr0
diff --git a/tests/networkxml2confdata/nat-network-dns-txt-record.conf b/tests/networkxml2confdata/nat-network-dns-txt-record.conf
index d9b981a..ae1f419 100644
--- a/tests/networkxml2confdata/nat-network-dns-txt-record.conf
+++ b/tests/networkxml2confdata/nat-network-dns-txt-record.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 except-interface=lo
 bind-dynamic
 interface=virbr0
diff --git a/tests/networkxml2confdata/nat-network-mtu.conf b/tests/networkxml2confdata/nat-network-mtu.conf
index 1dd4754..ffa5fe6 100644
--- a/tests/networkxml2confdata/nat-network-mtu.conf
+++ b/tests/networkxml2confdata/nat-network-mtu.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 except-interface=lo
 bind-dynamic
 interface=virbr0
diff --git a/tests/networkxml2confdata/nat-network-name-with-quotes.conf b/tests/networkxml2confdata/nat-network-name-with-quotes.conf
index 5c5ea7b..fa5d4ff 100644
--- a/tests/networkxml2confdata/nat-network-name-with-quotes.conf
+++ b/tests/networkxml2confdata/nat-network-name-with-quotes.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 except-interface=lo
 bind-dynamic
 interface=virbr0
diff --git a/tests/networkxml2confdata/nat-network.conf b/tests/networkxml2confdata/nat-network.conf
index 873a360..6c23f9a 100644
--- a/tests/networkxml2confdata/nat-network.conf
+++ b/tests/networkxml2confdata/nat-network.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 except-interface=lo
 bind-dynamic
 interface=virbr0
diff --git a/tests/networkxml2confdata/netboot-network.conf b/tests/networkxml2confdata/netboot-network.conf
index 32ef25b..caec6e6 100644
--- a/tests/networkxml2confdata/netboot-network.conf
+++ b/tests/networkxml2confdata/netboot-network.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 domain=example.com
 expand-hosts
 except-interface=lo
diff --git a/tests/networkxml2confdata/netboot-proxy-network.conf b/tests/networkxml2confdata/netboot-proxy-network.conf
index 280da32..ddd6445 100644
--- a/tests/networkxml2confdata/netboot-proxy-network.conf
+++ b/tests/networkxml2confdata/netboot-proxy-network.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 domain=example.com
 expand-hosts
 except-interface=lo
diff --git a/tests/networkxml2confdata/netboot-tftp.conf b/tests/networkxml2confdata/netboot-tftp.conf
index 45615f3..f92809c 100644
--- a/tests/networkxml2confdata/netboot-tftp.conf
+++ b/tests/networkxml2confdata/netboot-tftp.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 except-interface=lo
 bind-dynamic
 interface=virbr0
diff --git a/tests/networkxml2confdata/open-network.conf b/tests/networkxml2confdata/open-network.conf
index ff09984..0b221aa 100644
--- a/tests/networkxml2confdata/open-network.conf
+++ b/tests/networkxml2confdata/open-network.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 except-interface=lo
 bind-dynamic
 interface=virbr1
diff --git a/tests/networkxml2confdata/ptr-domains-auto.conf b/tests/networkxml2confdata/ptr-domains-auto.conf
index 86701c4..ddc0b43 100644
--- a/tests/networkxml2confdata/ptr-domains-auto.conf
+++ b/tests/networkxml2confdata/ptr-domains-auto.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 local=/122.168.192.in-addr.arpa/
 local=/1.0.e.f.0.1.c.a.8.b.d.0.1.0.0.2.ip6.arpa/
 except-interface=lo
diff --git a/tests/networkxml2confdata/routed-network-no-dns.conf b/tests/networkxml2confdata/routed-network-no-dns.conf
index 83cc85e..6f1e908 100644
--- a/tests/networkxml2confdata/routed-network-no-dns.conf
+++ b/tests/networkxml2confdata/routed-network-no-dns.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 port=0
 except-interface=lo
 bind-dynamic
diff --git a/tests/networkxml2confdata/routed-network.conf b/tests/networkxml2confdata/routed-network.conf
index 970aa3c..caffaee 100644
--- a/tests/networkxml2confdata/routed-network.conf
+++ b/tests/networkxml2confdata/routed-network.conf
@@ -5,6 +5,7 @@
 ##
 ## dnsmasq conf file created by libvirt
 strict-order
+user=libvirt-dnsmasq
 except-interface=lo
 bind-dynamic
 interface=virbr1
