net_util: Only set host MAC address from user input

In case the host MAC address associated with a TAP device wasn't
explicitly provided by the user, Cloud Hypervisor would get the host MAC
associated by default with this TAP device and store it through the
network config. Problem is, in the context of a snapshot/restore, that
meant the network config provided by the user was different on the
destination host compared to the source host. This was causing an issue
when Cloud Hypervisor wasn't started with CAP_NET_ADMIN permissions as
it couldn't set the host MAC address on the destination, while the
source never needed these permissions since the MAC was automatically
allocated by the kernel.

We're fixing this issue by setting the host MAC address when it's
explicitly requested by the user through the network config, and making
the host MAC immutable so that it can't be changed at runtime.

Signed-off-by: Sebastien Boeuf <sboeuf@meta.com>
This commit is contained in:
Sebastien Boeuf
2026-07-17 05:42:50 -07:00
committed by Rob Bradford
parent b0369bf2da
commit e37f63282c
6 changed files with 10 additions and 14 deletions

View File

@@ -3261,7 +3261,7 @@ pub(crate) fn _test_tap_from_fd(guest: &Guest) {
Ipv4Addr::from_str(&guest.network.host_ip0).unwrap(),
)),
None,
&mut None,
None,
None,
num_queue_pairs,
Some(libc::O_RDWR | libc::O_NONBLOCK),

View File

@@ -9461,7 +9461,7 @@ mod common_sequential {
Ipv4Addr::from_str(&guest.network.host_ip0).unwrap(),
)),
None,
&mut None,
None,
None,
num_queue_pairs,
Some(libc::O_RDWR | libc::O_NONBLOCK),
@@ -9565,7 +9565,7 @@ mod common_sequential {
Ipv4Addr::from_str(&guest.network.host_ip0).unwrap(),
)),
None,
&mut None,
None,
None,
num_queue_pairs,
Some(libc::O_RDWR | libc::O_NONBLOCK),

View File

@@ -27,8 +27,6 @@ pub enum Error {
TapSetIpNetmask(#[source] TapError),
#[error("Setting MAC address failed")]
TapSetMac(#[source] TapError),
#[error("Getting MAC address failed")]
TapGetMac(#[source] TapError),
#[error("Setting vnet header size failed")]
TapSetVnetHdrSize(#[source] TapError),
#[error("Setting MTU failed")]
@@ -66,7 +64,7 @@ fn open_tap_rx_q_0(
if_name: Option<&str>,
ip_addr: Option<IpAddr>,
netmask: Option<IpAddr>,
host_mac: &mut Option<MacAddr>,
host_mac: Option<MacAddr>,
mtu: Option<u16>,
num_rx_q: usize,
flags: Option<i32>,
@@ -90,9 +88,7 @@ fn open_tap_rx_q_0(
.map_err(Error::TapSetIpNetmask)?;
}
if let Some(mac) = host_mac {
tap.set_mac_addr(*mac).map_err(Error::TapSetMac)?;
} else {
*host_mac = Some(tap.get_mac_addr().map_err(Error::TapGetMac)?);
tap.set_mac_addr(mac).map_err(Error::TapSetMac)?;
}
if let Some(mtu) = mtu {
tap.set_mtu(mtu as i32).map_err(Error::TapSetMtu)?;
@@ -111,7 +107,7 @@ pub fn open_tap(
if_name: Option<&str>,
ip_addr: Option<IpAddr>,
netmask: Option<IpAddr>,
host_mac: &mut Option<MacAddr>,
host_mac: Option<MacAddr>,
mtu: Option<u16>,
num_rx_q: usize,
flags: Option<i32>,

View File

@@ -134,7 +134,7 @@ impl VhostUserNetBackend {
ifname,
Some(ip_addr),
Some(netmask),
&mut Some(host_mac),
Some(host_mac),
mtu,
num_queues / 2,
None,

View File

@@ -656,7 +656,7 @@ impl Net {
ip_addr: Option<IpAddr>,
netmask: Option<IpAddr>,
guest_mac: Option<MacAddr>,
host_mac: &mut Option<MacAddr>,
host_mac: Option<MacAddr>,
mtu: Option<u16>,
access_platform_enabled: bool,
num_queues: usize,

View File

@@ -2979,7 +2979,7 @@ impl DeviceManager {
net_cfg.ip,
net_cfg.mask,
Some(net_cfg.mac),
&mut net_cfg.host_mac,
net_cfg.host_mac,
net_cfg.mtu,
self.force_access_platform | net_cfg.pci_common.iommu,
net_cfg.num_queues,
@@ -3030,7 +3030,7 @@ impl DeviceManager {
net_cfg.ip,
net_cfg.mask,
Some(net_cfg.mac),
&mut net_cfg.host_mac,
net_cfg.host_mac,
net_cfg.mtu,
self.force_access_platform | net_cfg.pci_common.iommu,
net_cfg.num_queues,