Golang使用syscall.CLONE_NEWUSER启动sudo报无效参数如何解决
错误原因
你遇到的fork/exec /usr/bin/sudo: invalid argument错误由两个核心问题共同导致:
- 你在新创建的user namespace内执行sudo二进制:sudo属于setuid root程序,非特权用户创建的user namespace默认没有权限执行setuid操作,内核会直接拦截执行请求返回无效参数错误。
- 你的配置存在逻辑冲突:同时设置了
Credential: cred指定进程身份为root,又配置了user namespace的uid/gid映射,两个配置的优先级冲突会导致fork失败。
UidMappings、GidMappings配置错误点
- 映射逻辑冗余:你将容器内uid 1映射到宿主机root uid 0,属于完全不必要的配置,普通用户创建user namespace时,仅需要将容器内uid 0映射到当前宿主进程的uid即可,无权限映射到宿主机的root uid。
GidMappingsEnableSetgroups设置错误:普通用户创建user namespace时,该参数必须设为false,否则内核会拒绝namespace创建请求。
可行解决方案
根据你的使用场景,优先推荐更简单的方案:不需要自行创建各类namespace,直接调用sudo执行命令即可,你本身已经拥有sudo权限,自行创建namespace属于冗余操作,修正后的代码如下:
if rootless.IsRootless() && scpOpts.Root { var out bytes.Buffer var stderr bytes.Buffer cmd := exec.Command("/usr/bin/sudo", "podman", "image", "load", "--input="+scpOpts.Save.Output) fmt.Println(cmd.Args) cmd.Stdout = &out cmd.Env = os.Environ() cmd.Stderr = &stderr err = cmd.Run() if err != nil { fmt.Println(fmt.Sprint(err) + ": " + stderr.String()) return } fmt.Println("Result: " + out.String()) }
如果你确实需要保留namespace做资源隔离,调整配置后去掉sudo即可,因为user namespace内的uid 0已经拥有对应权限,不需要再调用sudo提权,修正后的namespace配置如下:
sys := &syscall.SysProcAttr{Setpgid: true, GidMappingsEnableSetgroups: false, Cloneflags: syscall.CLONE_NEWNS | syscall.CLONE_NEWUTS | syscall.CLONE_NEWIPC | syscall.CLONE_NEWPID | syscall.CLONE_NEWNET | syscall.CLONE_NEWUSER, UidMappings: []syscall.SysProcIDMap{ { ContainerID: 0, HostID: syscall.Getuid(), Size: 1, }, }, GidMappings: []syscall.SysProcIDMap{ { ContainerID: 0, HostID: syscall.Getgid(), Size: 1, }, }, } cmd := exec.Command("podman", "image", "load", "--input="+scpOpts.Save.Output)
内容的提问来源于stack exchange,提问作者cbd123
相关产品推荐
相关产品推荐

