mount namespace

https://www.junmajinlong.com/virtual/namespace/mount_namespace/

 

root@cloud:~# ls -1 /proc/$$/mount*
/proc/3374/mountinfo
/proc/3374/mounts
/proc/3374/mountstats
root@cloud:~# mkdir iso
root@cloud:~# cd iso/
root@cloud:~/iso# ls
root@cloud:~/iso# mkdir -p iso1/dir
root@cloud:~/iso# mkdir -p iso2/dir2 
root@cloud:~/iso# ls
iso1  iso2
root@cloud:~/iso# ls iso1
dir

 

root@cloud:~/iso# mkisofs -o 1.iso iso1
I: -input-charset not specified, using utf-8 (detected in locale settings)
Total translation table size: 0
Total rockridge attributes bytes: 0
Total directory bytes: 2152
Path table size(bytes): 22
Max brk space used 0
175 extents written (0 MB)
root@cloud:~/iso# ls
1.iso  iso1  iso2
root@cloud:~/iso# mkisofs -o 2.iso iso2
I: -input-charset not specified, using utf-8 (detected in locale settings)
Total translation table size: 0
Total rockridge attributes bytes: 0
Total directory bytes: 2154
Path table size(bytes): 22
Max brk space used 0
175 extents written (0 MB)
root@cloud:~/iso# ls
1.iso  2.iso  iso1  iso2
root@cloud:~/iso# 

 

root@cloud:~/iso# ls -1 /proc/$$/mount*
/proc/3374/mountinfo
/proc/3374/mounts
/proc/3374/mountstats
root@cloud:~/iso# ls -l /proc/$$/ns/mnt
lrwxrwxrwx 1 root root 0 Dec  4 10:27 /proc/3374/ns/mnt -> 'mnt:[4026531840]'
root@cloud:~/iso# 

 

root@cloud:~/iso# ls -1 /proc/$$/mount*
/proc/3374/mountinfo
/proc/3374/mounts
/proc/3374/mountstats
root@cloud:~/iso# ls -l /proc/$$/ns/mnt
lrwxrwxrwx 1 root root 0 Dec  4 10:27 /proc/3374/ns/mnt -> 'mnt:[4026531840]'
root@cloud:~/iso# mount 1.iso /mnt/iso1 
mount: /mnt/iso1: WARNING: device write-protected, mounted read-only.
root@cloud:~/iso# mount | grep iso1
/root/iso/1.iso on /mnt/iso1 type iso9660 (ro,relatime,nojoliet,check=s,map=n,blocksize=2048)
root@cloud:~/iso# unshare -m -u /bin/bash
root@cloud:~/iso# ls -l /proc/$$/ns
total 0
lrwxrwxrwx 1 root root 0 Dec  4 10:29 cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx 1 root root 0 Dec  4 10:29 ipc -> 'ipc:[4026531839]'
lrwxrwxrwx 1 root root 0 Dec  4 10:29 mnt -> 'mnt:[4026533784]'
lrwxrwxrwx 1 root root 0 Dec  4 10:29 net -> 'net:[4026531896]'
lrwxrwxrwx 1 root root 0 Dec  4 10:29 pid -> 'pid:[4026531836]'
lrwxrwxrwx 1 root root 0 Dec  4 10:29 pid_for_children -> 'pid:[4026531836]'
lrwxrwxrwx 1 root root 0 Dec  4 10:29 user -> 'user:[4026531837]'
lrwxrwxrwx 1 root root 0 Dec  4 10:29 uts -> 'uts:[4026533786]'
root@cloud:~/iso# 

 

 

 

 

root@cloud:~/iso# mount 2.iso /mnt/iso2/
mount: /mnt/iso2: WARNING: device write-protected, mounted read-only.
root@cloud:~/iso# mount | grep 'iso[12]'
/root/iso/1.iso on /mnt/iso1 type iso9660 (ro,relatime,nojoliet,check=s,map=n,blocksize=2048)
/root/iso/2.iso on /mnt/iso2 type iso9660 (ro,relatime,nojoliet,check=s,map=n,blocksize=2048)
root@cloud:~/iso# 

 

root@cloud:~/iso# ls /mnt/iso1/
dir
root@cloud:~/iso# ls /mnt/iso2/
dir2
root@cloud:~/iso# 

 

 

重新打开一个shell

root@cloud:~# mount | grep 'iso[12]'
/root/iso/1.iso on /mnt/iso1 type iso9660 (ro,relatime,nojoliet,check=s,map=n,blocksize=2048)
root@cloud:~# 

 

 

 

root@cloud:~/iso# ls /mnt/iso1/
dir
root@cloud:~/iso# ls /mnt/iso2/
dir2
root@cloud:~/iso# umount /mnt/iso1/
root@cloud:~/iso# mount | grep 'iso[12]'
/root/iso/2.iso on /mnt/iso2 type iso9660 (ro,relatime,nojoliet,check=s,map=n,blocksize=2048)
root@cloud:~/iso# ls /mnt/iso1/
root@cloud:~/iso# ls /mnt/iso2/
dir2
root@cloud:~/iso# 

 

重新打开一个shell

root@cloud:~# mount | grep 'iso[12]'
/root/iso/1.iso on /mnt/iso1 type iso9660 (ro,relatime,nojoliet,check=s,map=n,blocksize=2048)
root@cloud:~# ls /mnt/iso1/
dir
root@cloud:~# 

 

mnt namespace: shared subtrees

root@cloud:~/iso# ls
1.iso  2.iso  iso1  iso2
root@cloud:~/iso# mount --bind  iso1 iso2
root@cloud:~/iso# ls iso2/
dir
root@cloud:~/iso# mount --make-shared  iso2
root@cloud:~/iso# unshare -m -u --propagation unchanged /bin/bash
root@cloud:~/iso# grep 'iso1' /proc/self/mountinfo
563 513 7:0 / /mnt/iso1 ro,relatime shared:228 - iso9660 /dev/loop0 ro,nojoliet,check=s,map=n,blocksize=2048
564 513 8:34 /root/iso/iso1 /root/iso/iso2 rw,relatime shared:1 - ext4 /dev/sdc2 rw,errors=remount-ro,stripe=64
root@cloud:~/iso# mkdir sub
root@cloud:~/iso# ls
1.iso  2.iso  iso1  iso2  sub
root@cloud:~/iso# mount --bind sub  iso2/subfoo
mount: iso2/subfoo: mount point does not exist.
root@cloud:~/iso# mkdir -p iso2/subfoo
root@cloud:~/iso# mount --bind sub  iso2/subfoo

 

root@cloud:~/iso# tree iso2
iso2
├── dir
└── subfoo

2 directories, 0 files
root@cloud:~/iso# tree iso1
iso1
├── dir
└── subfoo

2 directories, 0 files
root@cloud:~/iso# 

 

 

root@cloud:~/iso# tree iso2
iso2
├── dir
└── subfoo

2 directories, 0 files
root@cloud:~/iso# tree iso1
iso1
├── dir
└── subfoo

2 directories, 0 files
root@cloud:~/iso# 

 

syscall.MS_PRIVATE

// Get the parent mount point of directory passed in as argument. Also return
// optional fields.
func getParentMount(rootfs string) (string, string, error) {
    var path string
    mountinfos, err := mount.GetMounts()
    if err != nil {
        return "", "", err
    }
    mountinfo := getMountInfo(mountinfos, rootfs)
    if mountinfo != nil {
        return rootfs, mountinfo.Optional, nil
    }
    path = rootfs
    for {
        path = filepath.Dir(path)
        mountinfo = getMountInfo(mountinfos, path)
        if mountinfo != nil {
            return path, mountinfo.Optional, nil
        }
        if path == "/" {
            break
        }
    }
    // If we are here, we did not find parent mount. Something is wrong.
    return "", "", fmt.Errorf("Could not find parent mount of %s", rootfs)
}
// Make parent mount private if it was shared
func rootfsParentMountPrivate(config *configs.Config) error {
    sharedMount := false
    parentMount, optionalOpts, err := getParentMount(config.Rootfs)
    if err != nil {
        return err
    }
    optsSplit := strings.Split(optionalOpts, " ")
    for _, opt := range optsSplit {
        if strings.HasPrefix(opt, "shared:") {
            sharedMount = true
            break
        }
    }
    // Make parent mount PRIVATE if it was shared. It is needed for two
    // reasons. First of all pivot_root() will fail if parent mount is
    // shared. Secondly when we bind mount rootfs it will propagate to
    // parent namespace and we don't want that to happen.
    if sharedMount {
        return syscall.Mount("", parentMount, "", syscall.MS_PRIVATE, "")
    }
    return nil
}

 

func prepareRoot(config *configs.Config) error {
    flag := syscall.MS_SLAVE | syscall.MS_REC
    if config.RootPropagation != 0 {
        flag = config.RootPropagation
    }
    if err := syscall.Mount("", "/", "", uintptr(flag), ""); err != nil {
        return err
    }
    if err := rootfsParentMountPrivate(config); err != nil {
        return err
    }
    return syscall.Mount(config.Rootfs, config.Rootfs, "bind", syscall.MS_BIND|syscall.MS_REC, "")
}

 

 

Hands on Docker Hack

Now, a bit hack will change the container’s mount namespace from slave/private to shared, and making container-initiated filesystem mount event propagate to the host.

diff –git a/contrib/init/systemd/docker.service b/contrib/init/systemd/docker.service
index bc73448..ee1b43b 100644
— a/contrib/init/systemd/docker.service
+++ b/contrib/init/systemd/docker.service
@@ -6,7 +6,7 @@ Requires=docker.socket
 [Service]
 ExecStart=/usr/bin/docker -d -H fd://
-MountFlags=slave
+MountFlags=shared
 LimitNOFILE=1048576
 LimitNPROC=1048576
 LimitCORE=infinity
diff –git a/vendor/src/github.com/docker/libcontainer/standard_init_linux.go b/vendor/src/github.com/docker/libcontainer/standard_init_linux.go
index 282832b..652f278 100644
— a/vendor/src/github.com/docker/libcontainer/standard_init_linux.go
+++ b/vendor/src/github.com/docker/libcontainer/standard_init_linux.go
@@ -48,7 +48,7 @@ func (l *linuxStandardInit) Init() error {
        }
        label.Init()
        // InitializeMountNamespace() can be executed only for a new mount namespaceif l.config.Config.Namespaces.Contains(configs.NEWNS) {
+       if !l.config.Config.Namespaces.Contains(configs.NEWNS) {
                if err := setupRootfs(l.config.Config, console); err != nil {
                        return err
                }

 

  // Finish the rootfs setup.
        if l.config.Config.Namespaces.Contains(configs.NEWNS) {
                if err := finalizeRootfs(l.config.Config); err != nil {
                        return err
                }
        }

 

// finalizeRootfs sets anything to ro if necessary. You must call
// prepareRootfs first.
func finalizeRootfs(config *configs.Config) (err error) {
        // remount dev as ro if specified
        for _, m := range config.Mounts {
                if libcontainerUtils.CleanPath(m.Destination) == "/dev" {
                        if m.Flags&unix.MS_RDONLY == unix.MS_RDONLY {
                                if err := remountReadonly(m); err != nil {
                                        return newSystemErrorWithCausef(err, "remounting %q as readonly", m.Destination)
                                }
                        }
                        break
                }
        }

        // set rootfs ( / ) as readonly
        if config.Readonlyfs {
                if err := setReadonly(); err != nil {
                        return newSystemErrorWithCause(err, "setting rootfs as readonly")
                }
        }

        unix.Umask(0022)
        return nil
}

 

posted on 2020-12-04 10:43  tycoon3  阅读(183)  评论(0)    收藏  举报

导航