func unshareAndBind(workingRootDir string) bool { if *unshare { // Re-exec myself using the unshare syscall while on a locked thread. // This hack is required because syscall.Unshare() operates on only one // thread in the process, and Go switches execution between threads // randomly. Thus, the namespace can be suddenly switched for running // code. This is an aspect of Go that was not well thought out. runtime.LockOSThread() err := syscall.Unshare(syscall.CLONE_NEWNS) if err != nil { fmt.Printf("Unable to unshare mount namesace\t%s\n", err) return false } args := append(os.Args, "-unshare=false") err = syscall.Exec(args[0], args, os.Environ()) if err != nil { fmt.Printf("Unable to Exec:%s\t%s\n", args[0], err) return false } } err := syscall.Mount("none", "/", "", syscall.MS_REC|syscall.MS_PRIVATE, "") if err != nil { fmt.Printf("Unable to set mount sharing to private\t%s\n", err) return false } syscall.Unmount(workingRootDir, 0) err = syscall.Mount(*rootDir, workingRootDir, "", syscall.MS_BIND, "") if err != nil { fmt.Printf("Unable to bind mount %s to %s\t%s\n", *rootDir, workingRootDir, err) return false } return true }
func switchRoot(rootfs, subdir string, rmUsr bool) error { if err := syscall.Unmount(config.OEM, 0); err != nil { log.Debugf("Not umounting OEM: %v", err) } if subdir != "" { fullRootfs := path.Join(rootfs, subdir) if _, err := os.Stat(fullRootfs); os.IsNotExist(err) { if err := os.MkdirAll(fullRootfs, 0755); err != nil { log.Errorf("Failed to create directory %s: %v", fullRootfs, err) return err } } log.Debugf("Bind mounting mount %s to %s", fullRootfs, rootfs) if err := syscall.Mount(fullRootfs, rootfs, "", syscall.MS_BIND, ""); err != nil { log.Errorf("Failed to bind mount subdir for %s: %v", fullRootfs, err) return err } } for _, i := range []string{"/dev", "/sys", "/proc", "/run"} { log.Debugf("Moving mount %s to %s", i, path.Join(rootfs, i)) if err := os.MkdirAll(path.Join(rootfs, i), 0755); err != nil { return err } if err := syscall.Mount(i, path.Join(rootfs, i), "", syscall.MS_MOVE, ""); err != nil { return err } } if err := copyMoveRoot(rootfs, rmUsr); err != nil { return err } log.Debugf("chdir %s", rootfs) if err := syscall.Chdir(rootfs); err != nil { return err } log.Debugf("mount MS_MOVE %s", rootfs) if err := syscall.Mount(rootfs, "/", "", syscall.MS_MOVE, ""); err != nil { return err } log.Debug("chroot .") if err := syscall.Chroot("."); err != nil { return err } log.Debug("chdir /") if err := syscall.Chdir("/"); err != nil { return err } log.Debugf("Successfully moved to new root at %s", path.Join(rootfs, subdir)) os.Unsetenv("DOCKER_RAMDISK") return nil }
func deviceMountDisk(srcPath string, dstPath string, readonly bool, recursive bool) error { var err error // Prepare the mount flags flags := 0 if readonly { flags |= syscall.MS_RDONLY } // Detect the filesystem fstype := "none" if deviceIsBlockdev(srcPath) { fstype, err = shared.BlockFsDetect(srcPath) if err != nil { return err } } else { flags |= syscall.MS_BIND if recursive { flags |= syscall.MS_REC } } // Mount the filesystem if err = syscall.Mount(srcPath, dstPath, fstype, uintptr(flags), ""); err != nil { return fmt.Errorf("Unable to mount %s at %s: %s", srcPath, dstPath, err) } flags = syscall.MS_REC | syscall.MS_SLAVE if err = syscall.Mount("", dstPath, "", uintptr(flags), ""); err != nil { return fmt.Errorf("unable to make mount %s private: %s", dstPath, err) } return nil }
func setupSharedMounts() error { path := shared.VarPath("shmounts") isShared, err := shared.IsOnSharedMount(path) if err != nil { return err } if isShared { // / may already be ms-shared, or shmounts may have // been mounted by a previous lxd run return nil } if err := syscall.Mount(path, path, "none", syscall.MS_BIND, ""); err != nil { return err } var flags uintptr = syscall.MS_SHARED | syscall.MS_REC if err := syscall.Mount(path, path, "none", flags, ""); err != nil { return err } return nil }
// ConfigureTaskDir creates the necessary directory structure for a proper // chroot. cleanTaskDir should be called after. func (e *LinuxExecutor) ConfigureTaskDir(taskName string, alloc *allocdir.AllocDir) error { e.taskName = taskName e.allocDir = alloc.AllocDir taskDir, ok := alloc.TaskDirs[taskName] if !ok { fmt.Errorf("Couldn't find task directory for task %v", taskName) } e.taskDir = taskDir if err := alloc.MountSharedDir(taskName); err != nil { return err } // Embed ourselves if this is a test. This needs to be done so the test // binary is inside the chroot. if isTest(&e.cmd) { bin := e.cmd.Args[0] alloc.Embed(taskName, map[string]string{bin: bin}) } if err := alloc.Embed(taskName, chrootEnv); err != nil { return err } // Mount dev dev := filepath.Join(taskDir, "dev") if !e.pathExists(dev) { if err := os.Mkdir(dev, 0777); err != nil { return fmt.Errorf("Mkdir(%v) failed: %v", dev, err) } if err := syscall.Mount("", dev, "devtmpfs", syscall.MS_RDONLY, ""); err != nil { return fmt.Errorf("Couldn't mount /dev to %v: %v", dev, err) } } // Mount proc proc := filepath.Join(taskDir, "proc") if !e.pathExists(proc) { if err := os.Mkdir(proc, 0777); err != nil { return fmt.Errorf("Mkdir(%v) failed: %v", proc, err) } if err := syscall.Mount("", proc, "proc", syscall.MS_RDONLY, ""); err != nil { return fmt.Errorf("Couldn't mount /proc to %v: %v", proc, err) } } // Set the tasks AllocDir environment variable. env, err := environment.ParseFromList(e.cmd.Env) if err != nil { return err } env.SetAllocDir(filepath.Join("/", allocdir.SharedAllocName)) env.SetTaskLocalDir(filepath.Join("/", allocdir.TaskLocal)) e.cmd.Env = env.List() return nil }
func (container *Container) setupIpcDirs() error { shmPath, err := container.shmPath() if err != nil { return err } if err := os.MkdirAll(shmPath, 0700); err != nil { return err } if err := syscall.Mount("shm", shmPath, "tmpfs", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), label.FormatMountLabel("mode=1777,size=65536k", container.getMountLabel())); err != nil { return fmt.Errorf("mounting shm tmpfs: %s", err) } mqueuePath, err := container.mqueuePath() if err != nil { return err } if err := os.MkdirAll(mqueuePath, 0700); err != nil { return err } if err := syscall.Mount("mqueue", mqueuePath, "mqueue", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), ""); err != nil { return fmt.Errorf("mounting mqueue mqueue : %s", err) } return nil }
// InitializeMountNamespace sets up the devices, mount points, and filesystems for use inside a // new mount namespace. func InitializeMountNamespace(rootfs, console string, sysReadonly bool, mountConfig *MountConfig) error { var ( err error flag = syscall.MS_PRIVATE ) if mountConfig.NoPivotRoot { flag = syscall.MS_SLAVE } if err := syscall.Mount("", "/", "", uintptr(flag|syscall.MS_REC), ""); err != nil { return fmt.Errorf("mounting / with flags %X %s", (flag | syscall.MS_REC), err) } if err := syscall.Mount(rootfs, rootfs, "bind", syscall.MS_BIND|syscall.MS_REC, ""); err != nil { return fmt.Errorf("mouting %s as bind %s", rootfs, err) } if err := mountSystem(rootfs, sysReadonly, mountConfig); err != nil { return fmt.Errorf("mount system %s", err) } if err := setupBindmounts(rootfs, mountConfig); err != nil { return fmt.Errorf("bind mounts %s", err) } if err := nodes.CreateDeviceNodes(rootfs, mountConfig.DeviceNodes); err != nil { return fmt.Errorf("create device nodes %s", err) } if err := SetupPtmx(rootfs, console, mountConfig.MountLabel); err != nil { return err } // stdin, stdout and stderr could be pointing to /dev/null from parent namespace. // Re-open them inside this namespace. if err := reOpenDevNull(rootfs); err != nil { return fmt.Errorf("Failed to reopen /dev/null %s", err) } if err := setupDevSymlinks(rootfs); err != nil { return fmt.Errorf("dev symlinks %s", err) } if err := syscall.Chdir(rootfs); err != nil { return fmt.Errorf("chdir into %s %s", rootfs, err) } if mountConfig.NoPivotRoot { err = MsMoveRoot(rootfs) } else { err = PivotRoot(rootfs) } if err != nil { return err } if mountConfig.ReadonlyFs { if err := SetReadonly(); err != nil { return fmt.Errorf("set readonly %s", err) } } syscall.Umask(0022) return nil }
// Do the mount operation followed by additional mounts required to take care // of propagation flags. func mountPropagate(m *configs.Mount, rootfs string, mountLabel string) error { var ( dest = m.Destination data = label.FormatMountLabel(m.Data, mountLabel) flags = m.Flags ) if libcontainerUtils.CleanPath(dest) == "/dev" { flags &= ^syscall.MS_RDONLY } copyUp := m.Extensions&configs.EXT_COPYUP == configs.EXT_COPYUP if !(copyUp || strings.HasPrefix(dest, rootfs)) { dest = filepath.Join(rootfs, dest) } if err := syscall.Mount(m.Source, dest, m.Device, uintptr(flags), data); err != nil { return err } for _, pflag := range m.PropagationFlags { if err := syscall.Mount("", dest, "", uintptr(pflag), ""); err != nil { return err } } return nil }
func containerSetupRoot(fsPath string) error { err := syscall.Mount("", "/", "", syscall.MS_SLAVE|syscall.MS_REC, "") if err != nil { return err } return syscall.Mount(fsPath, fsPath, "bind", syscall.MS_BIND|syscall.MS_REC, "") }
func PlaygroundCreate(systemdir, envdir string) (string, error) { basedir := POE_TEMPORARY_BASE + "/" + strconv.Itoa(os.Getpid()) if _, err := os.Stat(POE_TEMPORARY_BASE); err == nil { if err := os.RemoveAll(basedir); err != nil { return "", err } } if err := os.MkdirAll(basedir, 0755); err != nil { return "", err } if err := syscall.Mount("none", basedir, "tmpfs", syscall.MS_NOSUID, "size=32m"); err != nil { return "", err } workdir := basedir + "/work" if err := os.Mkdir(workdir, 0755); err != nil { return "", err } upperdir := basedir + "/upper" if err := os.Mkdir(upperdir, 0755); err != nil { return "", err } mergeddir := basedir + "/merged" if err := os.Mkdir(mergeddir, 0755); err != nil { return "", err } opts := fmt.Sprintf("lowerdir=%s:%s,upperdir=%s,workdir=%s", envdir, systemdir, upperdir, workdir) if err := syscall.Mount("none", mergeddir, "overlay", syscall.MS_NOSUID, opts); err != nil { return "", err } return mergeddir, nil }
// MountSpecialDirs mounts the dev and proc file system from the host to the // chroot func (d *AllocDir) MountSpecialDirs(taskDir string) error { // Mount dev dev := filepath.Join(taskDir, "dev") if !d.pathExists(dev) { if err := os.MkdirAll(dev, 0777); err != nil { return fmt.Errorf("Mkdir(%v) failed: %v", dev, err) } if err := syscall.Mount("none", dev, "devtmpfs", syscall.MS_RDONLY, ""); err != nil { return fmt.Errorf("Couldn't mount /dev to %v: %v", dev, err) } } // Mount proc proc := filepath.Join(taskDir, "proc") if !d.pathExists(proc) { if err := os.MkdirAll(proc, 0777); err != nil { return fmt.Errorf("Mkdir(%v) failed: %v", proc, err) } if err := syscall.Mount("none", proc, "proc", syscall.MS_RDONLY, ""); err != nil { return fmt.Errorf("Couldn't mount /proc to %v: %v", proc, err) } } return nil }
func setupRootfs(fsys *fs.Filesystem) error { if err := os.MkdirAll(fsys.Root(), 0755); err != nil { return fmt.Errorf("could not create rootfs path '%s': %v", fsys.Root(), err) } if err := syscall.Mount("", "/", "", syscall.MS_PRIVATE|syscall.MS_REC, ""); err != nil { return fmt.Errorf("failed to set MS_PRIVATE on '%s': %v", "/", err) } flags := uintptr(syscall.MS_NOSUID | syscall.MS_NOEXEC | syscall.MS_NODEV) if err := syscall.Mount("", fsys.Root(), "tmpfs", flags, "mode=755,gid=0"); err != nil { return fmt.Errorf("failed to mount tmpfs on '%s': %v", fsys.Root(), err) } if err := syscall.Mount("", fsys.Root(), "", syscall.MS_PRIVATE, ""); err != nil { return fmt.Errorf("failed to set MS_PRIVATE on '%s': %v", fsys.Root(), err) } for _, p := range basicBindDirs { if err := fsys.BindPath(p, fs.BindReadOnly, nil); err != nil { return fmt.Errorf("failed to bind directory '%s': %v", p, err) } } for _, p := range basicEmptyDirs { if err := fsys.CreateEmptyDir(p); err != nil { return fmt.Errorf("failed to create empty directory '%s': %v", p, err) } } dp := path.Join(fsys.Root(), "dev") if err := syscall.Mount("", dp, "tmpfs", syscall.MS_NOSUID|syscall.MS_NOEXEC, "mode=755"); err != nil { return err } for _, d := range basicDevices { if err := fsys.CreateDevice(d.path, d.dev, d.mode); err != nil { return err } } for _, sl := range append(basicSymlinks, deviceSymlinks...) { if err := fsys.CreateSymlink(sl[0], sl[1]); err != nil { return err } } if err := fsys.CreateBlacklistPaths(); err != nil { return err } for _, bl := range basicBlacklist { if err := fsys.BlacklistPath(bl, nil); err != nil { return err } } return nil }
// maskPath masks the top of the specified path inside a container to avoid // security issues from processes reading information from non-namespace aware // mounts ( proc/kcore ). // For files, maskPath bind mounts /dev/null over the top of the specified path. // For directories, maskPath mounts read-only tmpfs over the top of the specified path. func maskPath(path string) error { if err := syscall.Mount("/dev/null", path, "", syscall.MS_BIND, ""); err != nil && !os.IsNotExist(err) { if err == syscall.ENOTDIR { return syscall.Mount("tmpfs", path, "tmpfs", syscall.MS_RDONLY, "") } return err } return nil }
func doBindMount(source, destination string, readOnly bool) error { if err := syscall.Mount(source, destination, "bind", syscall.MS_BIND, ""); err != nil { return err } if readOnly { return syscall.Mount(source, destination, "bind", syscall.MS_REMOUNT|syscall.MS_RDONLY|syscall.MS_BIND, "") } return nil }
func aufsMount(ro []string, rw, target, mountLabel string) (err error) { defer func() { if err != nil { aufsUnmount(target) } }() // Mount options are clipped to page size(4096 bytes). If there are more // layers then these are remounted individually using append. offset := 54 if useDirperm() { offset += len("dirperm1") } b := make([]byte, syscall.Getpagesize()-len(mountLabel)-offset) // room for xino & mountLabel bp := copy(b, fmt.Sprintf("br:%s=rw", rw)) firstMount := true i := 0 for { for ; i < len(ro); i++ { layer := fmt.Sprintf(":%s=ro+wh", ro[i]) if firstMount { if bp+len(layer) > len(b) { break } bp += copy(b[bp:], layer) } else { data := utils.FormatMountLabel(fmt.Sprintf("append%s", layer), mountLabel) if err = syscall.Mount("none", target, "aufs", MsRemount, data); err != nil { return } } } if firstMount { opts := "dio,xino=/dev/shm/aufs.xino" if useDirperm() { opts += ",dirperm1" } data := utils.FormatMountLabel(fmt.Sprintf("%s,%s", string(b[:bp]), opts), mountLabel) if err = syscall.Mount("none", target, "aufs", 0, data); err != nil { return } firstMount = false } if i == len(ro) { break } } return }
func prepareRoot(config *configs.Config) error { flag := syscall.MS_SLAVE | syscall.MS_REC if config.Privatefs { flag = syscall.MS_PRIVATE | syscall.MS_REC } if err := syscall.Mount("", "/", "", uintptr(flag), ""); err != nil { return err } return syscall.Mount(config.Rootfs, config.Rootfs, "bind", syscall.MS_BIND|syscall.MS_REC, "") }
func containerMountDefaults(fsPath string) error { log.Debug("mountDefaults: %v", fsPath) var err error err = syscall.Mount("proc", filepath.Join(fsPath, "proc"), "proc", syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV, "") if err != nil { log.Errorln(err) return err } err = syscall.Mount("tmpfs", filepath.Join(fsPath, "dev"), "tmpfs", syscall.MS_NOEXEC|syscall.MS_STRICTATIME, "mode=755") if err != nil { log.Errorln(err) return err } err = os.MkdirAll(filepath.Join(fsPath, "dev", "shm"), 0755) if err != nil { log.Errorln(err) return err } err = os.MkdirAll(filepath.Join(fsPath, "dev", "mqueue"), 0755) if err != nil { log.Errorln(err) return err } err = os.MkdirAll(filepath.Join(fsPath, "dev", "pts"), 0755) if err != nil { log.Errorln(err) return err } err = syscall.Mount("tmpfs", filepath.Join(fsPath, "dev", "shm"), "tmpfs", syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV, "mode=1777,size=65536k") if err != nil { log.Errorln(err) return err } err = syscall.Mount("pts", filepath.Join(fsPath, "dev", "pts"), "devpts", syscall.MS_NOEXEC|syscall.MS_NOSUID, "newinstance,ptmxmode=666,gid=5,mode=620") if err != nil { log.Errorln(err) return err } err = syscall.Mount("sysfs", filepath.Join(fsPath, "sys"), "sysfs", syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV|syscall.MS_RDONLY, "") if err != nil { log.Errorln(err) return err } return nil }
func (devices *DeviceSet) MountDevice(hash, path, mountLabel string) error { info, err := devices.lookupDevice(hash) if err != nil { return err } info.lock.Lock() defer info.lock.Unlock() devices.Lock() defer devices.Unlock() if info.mountCount > 0 { if path != info.mountPath { return fmt.Errorf("Trying to mount devmapper device in multple places (%s, %s)", info.mountPath, path) } info.mountCount++ return nil } if err := devices.activateDeviceIfNeeded(info); err != nil { return fmt.Errorf("Error activating devmapper device for '%s': %s", hash, err) } var flags uintptr = syscall.MS_MGC_VAL fstype, err := ProbeFsType(info.DevName()) if err != nil { return err } options := "" if fstype == "xfs" { // XFS needs nouuid or it can't mount filesystems with the same fs options = joinMountOptions(options, "nouuid") } options = joinMountOptions(options, devices.mountOptions) options = joinMountOptions(options, label.FormatMountLabel("", mountLabel)) err = syscall.Mount(info.DevName(), path, fstype, flags, joinMountOptions("discard", options)) if err != nil && err == syscall.EINVAL { err = syscall.Mount(info.DevName(), path, fstype, flags, options) } if err != nil { return fmt.Errorf("Error mounting '%s' on '%s': %s", info.DevName(), path, err) } info.mountCount = 1 info.mountPath = path return nil }
func TestAttachFiles(t *testing.T) { Cleanup() if err := Init(); err != nil { t.Fatalf(err.Error()) } if err := CreateNewDevice(containerId, devPrefix, dmRootDir); err != nil { t.Fatalf(err.Error()) } parms := fmt.Sprintf("mkfs.ext4 \"/dev/mapper/%s-%s\"", devPrefix, containerId) if err := exec.Command("/bin/sh", "-c", parms).Run(); err != nil { t.Fatalf(err.Error()) } var ( flags uintptr = syscall.MS_MGC_VAL idMountPath = path.Join(dmRootDir, "mnt", containerId) rootFs = path.Join(idMountPath, "rootfs") toDir = "/" targetDir = path.Join(rootFs, toDir) devFullName = "/dev/mapper/" + devPrefix + "-" + containerId ) if err := AttachFiles(containerId, devPrefix, "/etc/os-release", toDir, dmRootDir, "0755", "0", "0"); err != nil { t.Fatalf(err.Error()) } fstype, err := ProbeFsType("/dev/mapper/dm-1:1-1234567-123") if err != nil { t.Fatalf(err.Error()) } options := "" if fstype == "xfs" { // XFS needs nouuid or it can't mount filesystems with the same fs options = joinMountOptions(options, "nouuid") } err = syscall.Mount(devFullName, idMountPath, fstype, flags, joinMountOptions("discard", options)) if err != nil && err == syscall.EINVAL { err = syscall.Mount(devFullName, idMountPath, fstype, flags, options) } if err != nil { t.Fatalf("Error mounting '%s' on '%s': %s", devFullName, idMountPath, err) } targetFile := targetDir + "/os-release" if _, err := os.Stat(targetFile); err != nil { t.Log(targetFile) t.Fatalf(err.Error()) } syscall.Unmount(idMountPath, syscall.MNT_DETACH) defer func() { if err := Cleanup(); err != nil { t.Fatalf(err.Error()) } }() }
func mount(device, target, mType string, flag uintptr, data string) error { if err := syscall.Mount(device, target, mType, flag, data); err != nil { return err } // If we have a bind mount or remount, remount... if flag&syscall.MS_BIND == syscall.MS_BIND && flag&syscall.MS_RDONLY == syscall.MS_RDONLY { return syscall.Mount(device, target, mType, flag|syscall.MS_REMOUNT, data) } return nil }
func Mount(src, dst string, readOnly bool) error { if _, err := os.Stat(dst); os.IsNotExist(err) { os.MkdirAll(dst, 0755) } err := syscall.Mount(src, dst, "", syscall.MS_BIND|syscall.MS_REC, "") if err == nil && readOnly { err = syscall.Mount(src, dst, "", syscall.MS_BIND|syscall.MS_RDONLY|syscall.MS_REMOUNT|syscall.MS_REC, "") } return err }
func (m *Mount) bindMount(rootfs, mountLabel string) error { var ( flags = syscall.MS_BIND | syscall.MS_REC dest = filepath.Join(rootfs, m.Destination) ) if !m.Writable { flags = flags | syscall.MS_RDONLY } if m.Slave { flags = flags | syscall.MS_SLAVE } stat, err := os.Stat(m.Source) if err != nil { return err } // FIXME: (crosbymichael) This does not belong here and should be done a layer above dest, err = symlink.FollowSymlinkInScope(dest, rootfs) if err != nil { return err } if err := createIfNotExists(dest, stat.IsDir()); err != nil { return fmt.Errorf("creating new bind mount target %s", err) } if err := syscall.Mount(m.Source, dest, "bind", uintptr(flags), ""); err != nil { return fmt.Errorf("mounting %s into %s %s", m.Source, dest, err) } if !m.Writable { if err := syscall.Mount(m.Source, dest, "bind", uintptr(flags|syscall.MS_REMOUNT), ""); err != nil { return fmt.Errorf("remounting %s into %s %s", m.Source, dest, err) } } if m.Relabel != "" { if err := label.Relabel(m.Source, mountLabel, m.Relabel); err != nil { return fmt.Errorf("relabeling %s to %s %s", m.Source, mountLabel, err) } } if m.Private { if err := syscall.Mount("", dest, "none", uintptr(syscall.MS_PRIVATE), ""); err != nil { return fmt.Errorf("mounting %s private %s", dest, err) } } return nil }
func (devices *RbdSet) MountDevice(hash, mountPoint, mountLabel string) error { info, err := devices.lookupDevice(hash) if err != nil { return err } info.lock.Lock() defer info.lock.Unlock() if info.mountCount > 0 { if mountPoint != info.mountPath { return fmt.Errorf("Trying to mount rbd device in multple places (%s, %s)", info.mountPath, info.Device) } info.mountCount++ return nil } log.Debugf("[rbdset] Mount image %s with device %s to %s", info.Hash, info.Device, info.mountPath) if err := devices.mapImageToRbdDevice(info); err != nil { return err } var flags uintptr = syscall.MS_MGC_VAL fstype, err := ProbeFsType(info.Device) if err != nil { return err } options := "" if fstype == "xfs" { // XFS needs nouuid or it can't mount filesystems with the same fs options = joinMountOptions(options, "nouuid") } options = joinMountOptions(options, devices.mountOptions) options = joinMountOptions(options, label.FormatMountLabel("", mountLabel)) err = syscall.Mount(info.Device, mountPoint, fstype, flags, joinMountOptions("discard", options)) if err != nil && err == syscall.EINVAL { err = syscall.Mount(info.Device, mountPoint, fstype, flags, options) } if err != nil { return fmt.Errorf("Error mounting '%s' on '%s': %s", info.Device, mountPoint, err) } info.mountCount = 1 info.mountPath = mountPoint return nil }
// SetupNamespaceMountDir prepares a new root for use as a mount // source for bind mounting namespace fd to an outside path func SetupNamespaceMountDir(root string) error { if err := os.MkdirAll(root, 0666); err != nil { return err } // make sure mounts are not unmounted by other mnt namespaces if err := syscall.Mount("", root, "none", syscall.MS_SHARED|syscall.MS_REC, ""); err != nil && err != syscall.EINVAL { return err } if err := syscall.Mount(root, root, "none", syscall.MS_BIND, ""); err != nil { return err } return nil }
func (e *LinuxExecutor) ConfigureTaskDir(taskName string, alloc *allocdir.AllocDir) error { e.taskName = taskName taskDir, ok := alloc.TaskDirs[taskName] if !ok { fmt.Errorf("Couldn't find task directory for task %v", taskName) } e.taskDir = taskDir if err := alloc.MountSharedDir(taskName); err != nil { return err } if err := alloc.Embed(taskName, chrootEnv); err != nil { return err } // Mount dev dev := filepath.Join(taskDir, "dev") if err := os.Mkdir(dev, 0777); err != nil { return fmt.Errorf("Mkdir(%v) failed: %v", dev, err) } if err := syscall.Mount("", dev, "devtmpfs", syscall.MS_RDONLY, ""); err != nil { return fmt.Errorf("Couldn't mount /dev to %v: %v", dev, err) } // Mount proc proc := filepath.Join(taskDir, "proc") if err := os.Mkdir(proc, 0777); err != nil { return fmt.Errorf("Mkdir(%v) failed: %v", proc, err) } if err := syscall.Mount("", proc, "proc", syscall.MS_RDONLY, ""); err != nil { return fmt.Errorf("Couldn't mount /proc to %v: %v", proc, err) } // Set the tasks AllocDir environment variable. env, err := environment.ParseFromList(e.Cmd.Env) if err != nil { return err } env.SetAllocDir(filepath.Join("/", allocdir.SharedAllocName)) env.SetTaskLocalDir(filepath.Join("/", allocdir.TaskLocal)) e.Cmd.Env = env.List() e.alloc = alloc e.mounts = true 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, "") }
func InjectFile(src io.Reader, containerId, devPrefix, target, rootPath string, perm, uid, gid int) error { if containerId == "" { return fmt.Errorf("Please make sure the arguments are not NULL!\n") } permDir := perm | 0111 // Define the basic directory, need to get them via the 'info' command var ( mntPath = fmt.Sprintf("%s/mnt/", rootPath) devName = fmt.Sprintf("%s-%s", devPrefix, containerId) ) // Get the mount point for the container ID idMountPath := path.Join(mntPath, containerId) rootFs := path.Join(idMountPath, "rootfs") targetFile := path.Join(rootFs, target) // Whether we have the mounter directory if _, err := os.Stat(idMountPath); err != nil && os.IsNotExist(err) { if err := os.MkdirAll(idMountPath, os.FileMode(permDir)); err != nil { return err } } // Mount the block device to that mount point var flags uintptr = syscall.MS_MGC_VAL devFullName := fmt.Sprintf("/dev/mapper/%s", devName) fstype, err := ProbeFsType(devFullName) if err != nil { return err } glog.V(3).Infof("The filesytem type is %s", fstype) options := "" if fstype == "xfs" { // XFS needs nouuid or it can't mount filesystems with the same fs options = joinMountOptions(options, "nouuid") } err = syscall.Mount(devFullName, idMountPath, fstype, flags, joinMountOptions("discard", options)) if err != nil && err == syscall.EINVAL { err = syscall.Mount(devFullName, idMountPath, fstype, flags, options) } if err != nil { return fmt.Errorf("Error mounting '%s' on '%s': %s", devFullName, idMountPath, err) } defer syscall.Unmount(idMountPath, syscall.MNT_DETACH) return storage.WriteFile(src, targetFile, perm, uid, gid) }
// overlayRender renders the image that corresponds to the given hash using the // overlay filesystem. // It writes the manifest in the specified directory and mounts an overlay // filesystem from the cached tree of the image as rootfs. func overlayRender(cfg RunConfig, img types.Hash, cdir string, dest string) error { if err := writeManifest(cfg.CommonConfig, img, dest); err != nil { return err } destRootfs := path.Join(dest, "rootfs") if err := os.MkdirAll(destRootfs, 0755); err != nil { return err } cachedTreePath := cfg.Store.GetTreeStoreRootFS(img.String()) overlayDir := path.Join(cdir, "overlay", img.String()) if err := os.MkdirAll(overlayDir, 0755); err != nil { return err } upperDir := path.Join(overlayDir, "upper") if err := os.MkdirAll(upperDir, 0755); err != nil { return err } workDir := path.Join(overlayDir, "work") if err := os.MkdirAll(workDir, 0755); err != nil { return err } opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", cachedTreePath, upperDir, workDir) opts = label.FormatMountLabel(opts, cfg.MountLabel) if err := syscall.Mount("overlay", destRootfs, "overlay", 0, opts); err != nil { return fmt.Errorf("error mounting: %v", err) } return nil }
// 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 pivotRoot(rootfs, pivotBaseDir string) error { if pivotBaseDir == "" { pivotBaseDir = "/" } tmpDir := filepath.Join(rootfs, pivotBaseDir) if err := os.MkdirAll(tmpDir, 0755); err != nil { return fmt.Errorf("can't create tmp dir %s, error %v", tmpDir, err) } pivotDir, err := ioutil.TempDir(tmpDir, ".pivot_root") if err != nil { return fmt.Errorf("can't create pivot_root dir %s, error %v", pivotDir, err) } if err := syscall.PivotRoot(rootfs, pivotDir); err != nil { return fmt.Errorf("pivot_root %s", err) } if err := syscall.Chdir("/"); err != nil { return fmt.Errorf("chdir / %s", err) } // path to pivot dir now changed, update pivotDir = filepath.Join(pivotBaseDir, filepath.Base(pivotDir)) // Make pivotDir rprivate to make sure any of the unmounts don't // propagate to parent. if err := syscall.Mount("", pivotDir, "", syscall.MS_PRIVATE|syscall.MS_REC, ""); err != nil { return err } if err := syscall.Unmount(pivotDir, syscall.MNT_DETACH); err != nil { return fmt.Errorf("unmount pivot_root dir %s", err) } return os.Remove(pivotDir) }