{"record":{"id":"e001b3bff85d1aa7","repo":"hashicorp/nomad","slug":"error-from-unshare-v","errorCode":null,"errorMessage":"error from unshare: %v","messagePattern":"error from unshare: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/lib/nsutil/netns_linux.go","lineNumber":107,"sourceCode":"\t// the caller of this function\n\tgo (func() {\n\t\tdefer wg.Done()\n\t\truntime.LockOSThread()\n\t\t// Don't unlock. By not unlocking, golang will kill the OS thread when the\n\t\t// goroutine is done (for go1.10+)\n\n\t\tvar origNS NetNS\n\t\torigNS, err = GetNS(getCurrentThreadNetNSPath())\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"failed to get the current netns: %v\", err)\n\t\t\treturn\n\t\t}\n\t\tdefer origNS.Close()\n\n\t\t// create a new netns on the current thread\n\t\terr = unix.Unshare(unix.CLONE_NEWNET)\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"error from unshare: %v\", err)\n\t\t\treturn\n\t\t}\n\n\t\t// Put this thread back to the orig ns, since it might get reused (pre go1.10)\n\t\tdefer origNS.Set()\n\n\t\t// bind mount the netns from the current thread (from /proc) onto the\n\t\t// mount point. This causes the namespace to persist, even when there\n\t\t// are no threads in the ns.\n\t\terr = unix.Mount(getCurrentThreadNetNSPath(), nsPath, \"none\", unix.MS_BIND, \"\")\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"failed to bind mount ns at %s: %v\", nsPath, err)\n\t\t}\n\t})()\n\twg.Wait()\n\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create namespace: %v\", err)","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/lib/nsutil/netns_linux.go#L89-L125","documentation":"After saving the original namespace, NewNS calls unix.Unshare(CLONE_NEWNET) on the locked thread to create a fresh network namespace. If the kernel rejects the unshare, the error is wrapped as 'error from unshare'. This means the process lacks the privileges or the kernel disallows creating a new network namespace at that point.","triggerScenarios":"unix.Unshare(CLONE_NEWNET) returns an error during NewNS — EPERM because the process lacks CAP_SYS_ADMIN, or failure because namespace limits (max_user_namespaces) are exhausted.","commonSituations":"Unprivileged users without user namespaces enabled (kernel.unprivileged_userns_clone=0); containers without CAP_SYS_ADMIN; exhausted user.max_net_namespaces limits on multi-tenant hosts.","solutions":["Run the program with CAP_SYS_ADMIN or as root (or via a setuid helper)","Enable unprivileged namespace creation: sysctl -w kernel.unprivileged_userns_clone=1 (distro-dependent)","Raise user namespace limits: check/raise /proc/sys/user/max_user_namespaces","Confirm the kernel is compiled with CONFIG_NET_NS=y"],"exampleFix":"// before: EPERM from unshare in unprivileged container\n// after:\n// docker run --cap-add NET_ADMIN --cap-add SYS_ADMIN myimage\nns, err := nsutil.NewNS()","handlingStrategy":"try-catch","validationCode":"out, _ := exec.Command(\"unshare\", \"-n\", \"true\").CombinedOutput()\nif out != nil || execErr != nil {\n    return errors.New(\"this environment cannot create network namespaces (need CAP_SYS_ADMIN or userns)\")\n}","typeGuard":null,"tryCatchPattern":"ns, err := nsutil.NewNS()\nif err != nil && strings.Contains(err.Error(), \"error from unshare\") {\n    if errors.Is(err, os.ErrPermission) {\n        return fmt.Errorf(\"missing CAP_SYS_ADMIN for unshare(CLONE_NEWNET): %w\", err)\n    }\n    return err\n}","preventionTips":["Run with CAP_SYS_ADMIN or enable unprivileged user namespaces","Check /proc/sys/user/max_user_namespaces limits on multi-tenant hosts","Smoke-test namespace creation at service startup and fail fast with a clear message","Confirm kernel has CONFIG_NET_NS enabled"],"tags":["linux","network-namespace","unshare","privileges"],"backgroundTag":"unshare-epperm","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}