{"record":{"id":"ace17a8d230fdfee","repo":"slackhq/nebula","slug":"so-reuseport-failed-v","errorCode":null,"errorMessage":"SO_REUSEPORT failed: %v","messagePattern":"SO_REUSEPORT failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"udp/udp_android.go","lineNumber":26,"sourceCode":"\t\"log/slog\"\n\t\"net\"\n\t\"syscall\"\n\n\t\"golang.org/x/sys/unix\"\n)\n\nfunc NewListener(l *slog.Logger, s Settings) (Conn, error) {\n\treturn NewGenericListener(l, s)\n}\n\nfunc NewListenConfig(multi bool) net.ListenConfig {\n\treturn net.ListenConfig{\n\t\tControl: func(network, address string, c syscall.RawConn) error {\n\t\t\tif multi {\n\t\t\t\tvar controlErr error\n\t\t\t\terr := c.Control(func(fd uintptr) {\n\t\t\t\t\tif err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil {\n\t\t\t\t\t\tcontrolErr = fmt.Errorf(\"SO_REUSEPORT failed: %v\", err)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tif controlErr != nil {\n\t\t\t\t\treturn controlErr\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t}\n}\n\nfunc (u *GenericConn) Rebind() error {\n\treturn nil\n}","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/udp/udp_android.go#L8-L44","documentation":"On Android, nebula's UDP listen path sets SO_REUSEPORT on the socket fd via the net.ListenConfig Control hook so multiple sockets can bind the same port. If syscall.SetsockoptInt fails, the error is wrapped as 'SO_REUSEPORT failed'. This typically reflects a kernel or SELinux restriction rather than application misuse.","triggerScenarios":"Creating a UDP listener with multi=true on Android when setsockopt(SOL_SOCKET, SO_REUSEPORT) returns an error — e.g. kernel lacking SO_REUSEPORT support, permission denied from SELinux policy, or fd validity issues.","commonSituations":"Running nebula on very old Android kernels (<3.9) without SO_REUSEPORT; hardened SELinux policies blocking socket options; custom ROMs with restricted network syscalls.","solutions":["Update the device/OS to a kernel >= 3.9 that supports SO_REUSEPORT","Check SELinux denials (dmesg / adb logcat for avc denied) and adjust the policy or run in permissive mode for testing","Run with multi=false if lightfire/multiple-socket binding is not needed, so the socket option is skipped","Verify the error value (permission denied vs invalid argument) to target the actual restriction"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// Before relying on multi-socket binding, confirm kernel support:\n// grep -q SO_REUSEPORT /proc/kallsyms 2>/dev/null || uname -r (require >= 3.9)\n// On Android also check `adb shell getenforce` for SELinux enforcing mode","typeGuard":null,"tryCatchPattern":"ln, err := listenUDP(lc, \"0.0.0.0:0\")\nif err != nil {\n\tif strings.Contains(err.Error(), \"SO_REUSEPORT failed\") {\n\t\t// fall back to a single socket (multi=false) or surface a device/kernel requirement\n\t\treturn listenSingle()\n\t}\n\treturn err\n}","preventionTips":["Target devices with kernel >= 3.9 where SO_REUSEPORT exists","Review SELinux policy for socket option denials before shipping to hardened ROMs","Set multi=false when concurrent UDP listeners on the same port are not required","Capture the wrapped errno in logs to distinguish permission-denied from invalid-argument"],"tags":["android","udp","socket-options","kernel","nebula"],"backgroundTag":"so-reuseport-failed","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}