diff --git a/common/libnetwork/cni/network.go b/common/libnetwork/cni/network.go index 94d13f7a0f..7e001fab0e 100644 --- a/common/libnetwork/cni/network.go +++ b/common/libnetwork/cni/network.go @@ -82,9 +82,23 @@ type InitConfig struct { // NewCNINetworkInterface creates the ContainerNetwork interface for the CNI backend. // Note: The networks are not loaded from disk until a method is called. func NewCNINetworkInterface(conf *InitConfig) (types.ContainerNetwork, error) { + var netns *rootlessnetns.Netns + var err error + // Do not use unshare.IsRootless() here. We only care if we are running re-exec in the userns, + // IsRootless() also returns true if we are root in a userns which is not what we care about and + // causes issues as this slower more complicated rootless-netns logic should not be used as root. + val, ok := os.LookupEnv(unshare.UsernsEnvName) + useRootlessNetns := ok && val == "done" + if useRootlessNetns { + netns, err = rootlessnetns.New(conf.RunDir, rootlessnetns.CNI, conf.Config) + if err != nil { + return nil, err + } + } + // root needs to use a globally unique lock because there is only one host netns lockPath := defaultRootLockPath - if unshare.IsRootless() { + if useRootlessNetns { lockPath = filepath.Join(conf.CNIConfigDir, "cni.lock") } @@ -112,14 +126,6 @@ func NewCNINetworkInterface(conf *InitConfig) (types.ContainerNetwork, error) { defaultSubnetPools = config.DefaultSubnetPools } - var netns *rootlessnetns.Netns - if unshare.IsRootless() { - netns, err = rootlessnetns.New(conf.RunDir, rootlessnetns.CNI, conf.Config) - if err != nil { - return nil, err - } - } - cni := libcni.NewCNIConfig(conf.Config.Network.CNIPluginDirs.Values, &cniExec{}) n := &cniNetwork{ cniConfigDir: conf.CNIConfigDir, diff --git a/common/libnetwork/netavark/network.go b/common/libnetwork/netavark/network.go index d79fdff43a..6ec4a9d15b 100644 --- a/common/libnetwork/netavark/network.go +++ b/common/libnetwork/netavark/network.go @@ -96,9 +96,23 @@ type InitConfig struct { // NewNetworkInterface creates the ContainerNetwork interface for the netavark backend. // Note: The networks are not loaded from disk until a method is called. func NewNetworkInterface(conf *InitConfig) (types.ContainerNetwork, error) { + var netns *rootlessnetns.Netns + var err error + // Do not use unshare.IsRootless() here. We only care if we are running re-exec in the userns, + // IsRootless() also returns true if we are root in a userns which is not what we care about and + // causes issues as this slower more complicated rootless-netns logic should not be used as root. + val, ok := os.LookupEnv(unshare.UsernsEnvName) + useRootlessNetns := ok && val == "done" + if useRootlessNetns { + netns, err = rootlessnetns.New(conf.NetworkRunDir, rootlessnetns.Netavark, conf.Config) + if err != nil { + return nil, err + } + } + // root needs to use a globally unique lock because there is only one host netns lockPath := defaultRootLockPath - if unshare.IsRootless() { + if useRootlessNetns { lockPath = filepath.Join(conf.NetworkConfigDir, "netavark.lock") } @@ -134,18 +148,6 @@ func NewNetworkInterface(conf *InitConfig) (types.ContainerNetwork, error) { defaultSubnetPools = config.DefaultSubnetPools } - var netns *rootlessnetns.Netns - // Do not use unshare.IsRootless() here. We only care if we are running re-exec in the userns, - // IsRootless() also returns true if we are root in a userns which is not what we care about and - // causes issues as this slower more complicated rootless-netns logic should not be used as root. - _, useRootlessNetns := os.LookupEnv(unshare.UsernsEnvName) - if useRootlessNetns { - netns, err = rootlessnetns.New(conf.NetworkRunDir, rootlessnetns.Netavark, conf.Config) - if err != nil { - return nil, err - } - } - n := &netavarkNetwork{ networkConfigDir: conf.NetworkConfigDir, networkRunDir: conf.NetworkRunDir,