Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calling setns from Go returns EINVAL for mnt namespace #8676

Closed
gopherbot opened this issue Sep 6, 2014 · 4 comments
Closed

Calling setns from Go returns EINVAL for mnt namespace #8676

gopherbot opened this issue Sep 6, 2014 · 4 comments

Comments

@gopherbot
Copy link

by iain.lowe:

The C code works fine and correctly enters the namespace, but the Go code always seems
to return EINVAL from the `setns` call to enter the `mnt` namespace. I've tried a number
of permutations (including embedded C code with cgo and external `.so`) on Go `1.2`,
`1.3` and the current tip.

Stepping through the code in `gdb` shows that both sequences are calling `setns` in
`libc` the exact same way (or so it appears to me).

I have boiled what seems to be the issue down to the code below. What am I doing wrong?

## Setup

I have a shell alias for starting quick busybox containers:

    alias startbb='docker inspect --format "{{ .State.Pid }}" $(docker run -d busybox sleep 1000000)'

After running this, `startbb` will start a container and output it's PID.

`lxc-checkconfig` outputs:

    Found kernel config file /boot/config-3.8.0-44-generic
    --- Namespaces ---
    Namespaces: enabled
    Utsname namespace: enabled
    Ipc namespace: enabled
    Pid namespace: enabled
    User namespace: missing
    Network namespace: enabled
    Multiple /dev/pts instances: enabled
    
    --- Control groups ---
    Cgroup: enabled
    Cgroup clone_children flag: enabled
    Cgroup device: enabled
    Cgroup sched: enabled
    Cgroup cpu account: enabled
    Cgroup memory controller: missing
    Cgroup cpuset: enabled
    
    --- Misc ---
    Veth pair device: enabled
    Macvlan: enabled
    Vlan: enabled
    File capabilities: enabled

`uname -a` produces:

    Linux gecko 3.8.0-44-generic #66~precise1-Ubuntu SMP Tue Jul 15 04:01:04 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

## Working C code

The attached C code works fine.

After compiling with `gcc -o checkns checkns.c`, the output of `sudo ./checkns
<PID>` is:

    setns on ipc namespace succeeded
    setns on uts namespace succeeded
    setns on net namespace succeeded
    setns on pid namespace succeeded
    setns on mnt namespace succeeded

## Failing Go code

Conversely, the attached Go code (which should be identical) doesn't work quite as well.

Instead, running `sudo go run main.go <PID>` produces:

    setns on ipc namespace succeeded
    setns on uts namespace succeeded
    setns on net namespace succeeded
    setns on pid namespace succeeded
    setns on mnt namespace failed: invalid argument

Attachments:

  1. checkns.c (786 bytes)
  2. checkns.go (730 bytes)
@gopherbot
Copy link
Author

Comment 1 by iain.lowe:

Adding calls to runtime.LockOSThread have no effect.

@minux
Copy link
Member

minux commented Sep 6, 2014

Comment 2:

is it possible that this is something to do with Go programs being multithreaded?
Try using the cgo constructor trick to do this.
/*
__attribute__((constructor)) void enter_namespace(void) {
   // set ns here
}
*/
import "C"
this should make sure the C code runs before Go's main, thus
it will enter the namespace before Go runtime starts new threads.

@gopherbot
Copy link
Author

Comment 3 by iain.lowe:

Thanks, that was it.

@ianlancetaylor
Copy link
Contributor

Comment 4:

Status changed to WontFix.

@golang golang locked and limited conversation to collaborators Jun 25, 2016
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants