1

I have the following code mnt.go

package main

import (
    "fmt"
    "log"
    "os"
    "os/exec"
    "syscall"
)

func main() {
    fmt.Println("Entering go program")

    cmd := exec.Command("/bin/bash")
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    cmd.Stdin = os.Stdin

    cmd.SysProcAttr = &syscall.SysProcAttr{ 
        Cloneflags: syscall.CLONE_NEWNS,
    }

    if err := cmd.Run(); err != nil {
        log.Fatal(err)
    }

    fmt.Println("Exiting go program")
}

I want to run the above code to spawn a bash shell, and run the following commands:

./mnt
mkdir /tmp/testmount
mount -n -o size=1m -t tmpfs tmpfs /tmp/testmount
cd /tmp/testmount
touch 1.txt 2.txt 3.txt

Now when I launch another shell and run the command

ls /tmp/testmount

I should not be able to see the files 1.txt, 2.txt and 3.txt. Since the temp file system has been mounted inside a mount namespace, it should not be visible from the outside.

But that is not how it works for me. Why is the syscall.CLONE_NEWNS not working as expected? What should I do differently?

One of the comments mentions that this code works fine for them. FWIW, I am running a "bento/centos-7" Vagrant box with golang installed and no other customizations.

ashwnacharya
  • 14,601
  • 23
  • 89
  • 112
  • Actually I run your example, it works as expected. `mnt` requires `sudo` to run and after executing your commands, the three `txt` files cannot be seen from other processes (only the folder `/tmp/testmount` is accessible). – ivzhh Nov 19 '19 at 15:48
  • @etc-100g Very interesting. I am running this in a "bento/centos-7" vagrant box. I have no idea why it is working for you. What OS are you trying it on? – ashwnacharya Nov 19 '19 at 16:59
  • WSL2/Ubuntu 18.04. You are right, after testing on other CentOS-7/Virtualbox, the result is the same as you. – ivzhh Nov 19 '19 at 18:27
  • Maybe because of this: https://stackoverflow.com/a/45524409/225692 – ivzhh Nov 19 '19 at 18:28

1 Answers1

0

I was right about the solution. But I did not know why. For documentation purpose, I will make this post complete.If you can read Chinese, go directly read this Zhihu Zhuanlan post. That author is very professional on Linux container and docker.

The knowledge keywords are: Shared Subtrees and propagation types: MS_SHARED, MS_PRIVATE, and MS_SLAVE. By default, system assumes you want to reuse the mounted file systems. But if you don't want that, you have to do some extra work:

A process wants to clone its own namespace, but still wants to access the CD that got mounted recently. Shared subtree semantics provide the necessary mechanism to accomplish the above.

On command line, you can mount --make-rprivate /; in code, you need to use syscall.MS_PRIVATE | syscall.MS_REC to create an isolated mount.

ivzhh
  • 331
  • 5
  • 11