创建和使用Linux名称空间的问题

1cklez4t  于 2023-06-05  发布在  Linux
关注(0)|答案(1)|浏览(313)

我正在做一个命名空间的go库 Package 器。网络ns、ips ns和uts ns没有问题,但其他网络ns存在问题:
用户名:

  • 当尝试创建时,我得到“无效参数”(系统调用错误)。

MntNS:

  • mnt ns正在创建,但不工作,我使用mount proc检查。

ProcNS:

  • proc ns也被创建,但显示主机进程,挂载不工作。

时间NS:

  • 时间ns未创建,并出现错误“用户太多”(系统调用错误)。

创建命名空间代码:

func NewNamespace(NSs []string) (*Namespace, error) {
    var flag int = 0
    for _, ns := range NSs {
        if val, ok := CloneFlags[ns]; ok == true {
            flag = flag | val
            continue
        }
        return nil, errors.New("unsupported ns " + ns)
    }
    if err := unix.Unshare(flag); err != nil {
        return nil, err
    }
    return GetCurrent()
}

获取当前NS代码:

func GetCurrent() (*Namespace, error) {
    return GetFromThread(os.Getpid(), unix.Gettid())
}

func GetFromThread(pid, tid int) (*Namespace, error) {
    ns := newNamespace()
    for _, n := range NSs {
        if entry, ok := ns.ns[n]; ok {
            entry.path = fmt.Sprintf("/proc/%d/task/%d/ns/%s", pid, tid, n)
            fd, err := OpenNS(entry.path)
            if err != nil {
                return nil, err
            }
            entry.fd = fd
            ns.ns[n] = entry
        }
    }
    return ns, nil
}

设置NS代码:

func SetNamespace(ns *Namespace, NSs []string) error {
    for _, n := range NSs {
        if entry, ok := ns.ns[n]; ok {
            entry.share = true

            ns.ns[n] = entry
        }
    }
    for key, val := range ns.ns {
        if !val.share {
            continue
        }
        fmt.Printf("Preparing %s...\n", key)
        err := unix.Setns(val.fd, CloneFlags[key])
        if err != nil {
            return err
        }
        fmt.Printf("Set %s\n", key)
    }
    return nil
}

装载过程代码:

func mountProc() error {
    if err := syscall.Mount("proc", "/proc", "proc", 0, ""); err != nil {
        return err
    }
    return nil
}

标志:

const (
    CLONE_NEWUTS    = unix.CLONE_NEWUTS //Work
    CLONE_NEWNS     = unix.CLONE_NEWNS
    CLONE_NEWCGROUP = unix.CLONE_NEWCGROUP
    CLONE_NEWTIME   = unix.CLONE_NEWTIME
    CLONE_NEWIPC    = unix.CLONE_NEWIPC //Work
    CLONE_NEWUSER   = unix.CLONE_NEWUSER
    CLONE_NEWPID    = unix.CLONE_NEWPID
    CLONE_NEWNET    = unix.CLONE_NEWNET //Work
    CLONE_IO        = unix.CLONE_IO
)

我想我错过了一些东西,但我不能弄清楚是什么,也许需要一个组合的ns。

14ifxucb

14ifxucb1#

用户名:

  • 当尝试创建时,我得到“无效参数”(系统调用错误)。

根据man 2 unshare,“CLONE_NEWUSER要求调用进程不是线程化的”,但您的进程是线程化的,您可以通过strace输出中带有CLONE_THREADclone系统调用来判断。
MntNS:

  • mnt ns正在创建,但不工作,我使用mount proc检查。

我不知道你检查了什么,但我猜你遇到的是systemd改变了默认的挂载传播方式,使挂载命名空间实际上无法工作,所以每次你做一个,你需要做的第一件事就是立即将它更改回来。看看在创建挂载名称空间后立即执行类似syscall.Mount("none", "/", nil, syscall.MS_REC | syscall.MS_PRIVATE, "")的操作是否有帮助。
ProcNS:

  • proc ns也被创建,但显示主机进程,挂载不工作。

我假设您指的是PID名称空间,因为没有proc名称空间这样的东西。这一次,我能想到两个可能出错的原因。首先,同样按照man 2 unshare,“调用进程为其子进程具有新的PID命名空间”和“调用进程未移动到新的命名空间中”。因此,这不会影响您的进程,并且要使其执行任何操作,您需要启动子进程。其次,对于man 7 pid_namespaces,您需要从PID名称空间中挂载一个新的proc文件系统示例,以查看其中的PID。
时间NS:

  • 时间ns未创建,并出现错误“用户太多”(系统调用错误)。

它看起来像是正在创建,只是无法设置。很难找到明确说明这一点的文档,但是通过阅读内核源代码,看起来像用户名称空间一样,您不能在多线程进程上设置时间名称空间,但是与PID名称空间一样,如果您生成子进程,则应该设置它。

相关问题