I'm making a go library wrapper on namespaces. There were no problems with the.net ns, with ips ns and with uts ns, but there are problems with the others:
UserNs:
MntNS:
ProcNS:
TimeNS:
Create Namespace code:
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()
}
Get Current NS Code:
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
}
Set NS Code:
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
}
Mount proc code:
func mountProc() error {
if err := syscall.Mount("proc", "/proc", "proc", 0, ""); err != nil {
return err
}
return nil
}
Flags:
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
)
I think I'm missing something but I can't figure out what, perhaps a combination of ns is needed.
UserNs:
- When trying to create, I get "invalid argument"(syscall error).
Per man 2 unshare
, " CLONE_NEWUSER
requires that the calling process is not threaded", but your process is threaded, as you can tell by the clone
syscall with CLONE_THREAD
in your strace output.
MntNS:
- mnt ns is being created, but doesn't work, I checked using mount proc.
I don't know exactly without knowing what you checked, but I'm guessing what you're running into is that systemd changes the default mount propagation in a way that makes mount namespaces effectively not work , so every time you make one, the first thing you need to do immediately afterwards is to change it back. See if doing something like syscall.Mount("none", "/", nil, syscall.MS_REC | syscall.MS_PRIVATE, "")
right after creating the mount namespace helps.
ProcNS:
- proc ns is also created, but shows host processes, mounting does not work.
I assume you mean PID namespace, since there's no such thing as a proc namespace. This time, I can think of two reasons things could be going wrong. First, again per man 2 unshare
, "the calling process has a new PID namespace for its children" and "The calling process is not moved into the new namespace." So that won't affect your process, and for it to do anything, you need to start a child process. Second, per man 7 pid_namespaces
, you need to mount a new instance of the proc filesystem from within the PID namespace to see the PIDs within it.
TimeNS:
- time ns is not created with the error "too many users"(syscall error).
It looks like this is being created and is just failing to set. It's hard to find documentation that explicitly says this, but by reading kernel source code, it looks like as with user namespaces, you can't set time namespaces on a multithreaded process, but as with PID namespaces, if you spawn a child process, it should have it set.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.