cilium/cilium · critical

setsockopt(SO_MARK) failed: %w

Error message

setsockopt(SO_MARK) failed: %w

What it means

listenConfig marks sockets with a magic fwmark (e.g. MagicMarkEgress 0x0b00) so the kernel/BPF datapath recognizes proxy return traffic and routes it correctly. Setting SO_MARK requires CAP_NET_ADMIN; failure produces 'setsockopt(SO_MARK) failed: %w' and the socket is not created.

Source

Thrown at pkg/fqdn/dnsproxy/udp.go:108

	}

	return nil
}

// listenConfig sets the socket options for the fqdn proxy transparent socket.
// Note that it is also used for TCP sockets.
func listenConfig(mark uint32, ipFamily ipfamily.IPFamily) *net.ListenConfig {
	return &net.ListenConfig{
		Control: func(_, _ string, c syscall.RawConn) error {
			var opErr error
			err := c.Control(func(fd uintptr) {
				if err := transparentSetsockopt(int(fd), ipFamily); err != nil {
					opErr = err
					return
				}
				if mark != 0 {
					if err := unix.SetsockoptUint64(int(fd), unix.SOL_SOCKET, unix.SO_MARK, uint64(mark)); err != nil {
						opErr = fmt.Errorf("setsockopt(SO_MARK) failed: %w", err)
						return
					}
				}
				if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1); err != nil {
					opErr = fmt.Errorf("setsockopt(SO_REUSEADDR) failed: %w", err)
					return
				}
				if !option.Config.EnableBPFTProxy {
					if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil {
						opErr = fmt.Errorf("setsockopt(SO_REUSEPORT) failed: %w", err)
						return
					}
				}
			})
			if err != nil {
				return err
			}

View on GitHub (pinned to ac7b90affa)

Solutions

  1. Add CAP_NET_ADMIN to the container securityContext
  2. Allow setsockopt(SO_MARK) in seccomp/apparmor policy
  3. Verify kernel support: SO_MARK requires Linux ≥ 2.6.25; SetsockoptUint64 form needs a recent kernel/libc (SO_MARK as u64 since 5.17, otherwise pass u32 via SetsockoptInt)
  4. Check the wrapped errno: EPERM → capability missing

Example fix

// before
capabilities:
  add: ["SYS_ADMIN"]
// after
capabilities:
  add: ["SYS_ADMIN", "NET_ADMIN", "NET_RAW"]
Defensive patterns

Strategy: validation

Validate before calling

// SO_MARK requires CAP_NET_ADMIN
if !hasCap_NET_ADMIN() {
    return errors.New("setting SO_MARK requires CAP_NET_ADMIN")
}

Type guard

func isMarkSockoptError(err error) bool {
    return err != nil && strings.Contains(err.Error(), "setsockopt(SO_MARK)")
}

Try / catch

if err := listenConfig(mark, family).ListenPacket(ctx, "ip:udp", addr); err != nil {
    if isMarkSockoptError(err) {
        return fmt.Errorf("cannot fwmark proxy sockets (need CAP_NET_ADMIN): %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Any listen/bind through listenConfig with mark != 0 (e.g. bindResponseUDPConnection) on a system where SetsockoptUint64(SO_MARK) fails — EPERM without CAP_NET_ADMIN, or kernels/runtimes where SO_MARK is blocked (some seccomp profiles, older WSL/gVisor).

Common situations: Containers missing NET_ADMIN, security profiles blocking SO_MARK, or non-mainstream kernels (some cloud sandboxed runtimes) that do not implement SO_MARK.

Related errors


AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31). Data as JSON: /api/errors/e19db68705c85e25. Report an issue: GitHub.