Skip to content

Bug: DynamicNetwork.NetworkSetup incorrectly blocks container startup when unrelated or stale "tap" interfaces exist in the network namespace #938

Description

@singhshresth26

Summary

When spawning a unikernel using the DynamicNetwork configuration, urunc attempts to ensure that only a single unikernel is run inside the current network namespace. It checks for existing TAP interfaces by calling getTapIndex(). If tapIndex > 0, it aborts container startup and throws the following error:
unsupported operation: can't spawn multiple unikernels in the same network namespace

However, the current check in getTapIndex() is too broad because it scans for any network interface containing the substring "tap" in its name:

for _, iface := range ifaces {
    if strings.Contains(iface.Name, "tap") {
        tapCount++
    }
}

Detailed Problem & Scenarios

This simplistic check introduces two main issues:

  1. False Positives with Unrelated Interfaces:
    In containerized or Kubernetes environments, CNI plugins or host systems often create virtual interfaces, bridges, or tunnels that contain the word "tap" (such as cni-tap0, vlan-tap, or tap-master). If any such interface is present in the network namespace, getTapIndex() will return 1, causing urunc to falsely believe a unikernel is already running and refuse to spawn the first container.

  2. Blocking on Stale Interfaces:
    If a previous urunc container execution crashes or is terminated uncleanly before it can delete its TAP device (tap0_urunc), the dead device remains in the namespace. On subsequent container launch attempts, getTapIndex() will detect the stale tap0_urunc device and fail to start any new containers, instead of reusing the name or cleaning it up.

Affected Code

  • getTapIndex() in pkg/network/network.go (around lines 65-80)
  • NetworkSetup() in pkg/network/network_dynamic.go (around lines 36-42)

Expected Behavior

urunc should only count TAP interfaces that match the naming pattern of its own created devices (i.e. ^tap\d+_urunc$).

Suggested Fix

Update getTapIndex() in pkg/network/network.go to compile and match the exact regex pattern of urunc tap devices (the same regex used in CleanupAllUruncTaps):

func getTapIndex() (int, error) {
	ifaces, err := net.Interfaces()
	if err != nil {
		return 0, err
	}
	tapRe := regexp.MustCompile(`^tap\d+_urunc$`)
	tapCount := 0
	for _, iface := range ifaces {
		if tapRe.MatchString(iface.Name) {
			tapCount++
		}
	}
	if tapCount > 255 {
		return tapCount, fmt.Errorf("TAP interfaces count higher than 255")
	}
	return tapCount, nil
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    invalidThis doesn't seem right

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions