func MsMoveRoot(rootfs string) error { if err := system.Mount(rootfs, "/", "", syscall.MS_MOVE, ""); err != nil { return fmt.Errorf("mount move %s into / %s", rootfs, err) } if err := system.Chroot("."); err != nil { return fmt.Errorf("chroot . %s", err) } return system.Chdir("/") }
// setupNewMountNamespace is used to initialize a new mount namespace for an new // container in the rootfs that is specified. // // There is no need to unmount the new mounts because as soon as the mount namespace // is no longer in use, the mounts will be removed automatically func setupNewMountNamespace(rootfs, console string, readonly bool) error { // mount as slave so that the new mounts do not propagate to the host if err := system.Mount("", "/", "", syscall.MS_SLAVE|syscall.MS_REC, ""); err != nil { return fmt.Errorf("mounting / as slave %s", err) } if err := system.Mount(rootfs, rootfs, "bind", syscall.MS_BIND|syscall.MS_REC, ""); err != nil { return fmt.Errorf("mouting %s as bind %s", rootfs, err) } if readonly { if err := system.Mount(rootfs, rootfs, "bind", syscall.MS_BIND|syscall.MS_REMOUNT|syscall.MS_RDONLY|syscall.MS_REC, ""); err != nil { return fmt.Errorf("mounting %s as readonly %s", rootfs, err) } } if err := mountSystem(rootfs); err != nil { return fmt.Errorf("mount system %s", err) } if err := copyDevNodes(rootfs); err != nil { return fmt.Errorf("copy dev nodes %s", err) } // In non-privileged mode, this fails. Discard the error. setupLoopbackDevices(rootfs) if err := setupDev(rootfs); err != nil { return err } if console != "" { if err := setupPtmx(rootfs, console); err != nil { return err } } if err := system.Chdir(rootfs); err != nil { return fmt.Errorf("chdir into %s %s", rootfs, err) } if err := system.Mount(rootfs, "/", "", syscall.MS_MOVE, ""); err != nil { return fmt.Errorf("mount move %s into / %s", rootfs, err) } if err := system.Chroot("."); err != nil { return fmt.Errorf("chroot . %s", err) } if err := system.Chdir("/"); err != nil { return fmt.Errorf("chdir / %s", err) } system.Umask(0022) return nil }