我正在做一个命名空间的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。
1条答案
按热度按时间14ifxucb1#
用户名:
根据
man 2 unshare
,“CLONE_NEWUSER
要求调用进程不是线程化的”,但您的进程是线程化的,您可以通过strace输出中带有CLONE_THREAD
的clone
系统调用来判断。MntNS:
我不知道你检查了什么,但我猜你遇到的是systemd改变了默认的挂载传播方式,使挂载命名空间实际上无法工作,所以每次你做一个,你需要做的第一件事就是立即将它更改回来。看看在创建挂载名称空间后立即执行类似
syscall.Mount("none", "/", nil, syscall.MS_REC | syscall.MS_PRIVATE, "")
的操作是否有帮助。ProcNS:
我假设您指的是PID名称空间,因为没有proc名称空间这样的东西。这一次,我能想到两个可能出错的原因。首先,同样按照
man 2 unshare
,“调用进程为其子进程具有新的PID命名空间”和“调用进程未移动到新的命名空间中”。因此,这不会影响您的进程,并且要使其执行任何操作,您需要启动子进程。其次,对于man 7 pid_namespaces
,您需要从PID名称空间中挂载一个新的proc文件系统示例,以查看其中的PID。时间NS:
它看起来像是正在创建,只是无法设置。很难找到明确说明这一点的文档,但是通过阅读内核源代码,看起来像用户名称空间一样,您不能在多线程进程上设置时间名称空间,但是与PID名称空间一样,如果您生成子进程,则应该设置它。