Пример #1
0
func (a *Driver) aufsMount(ro []string, rw, target, mountLabel string) (err error) {
	defer func() {
		if err != nil {
			Unmount(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 := label.FormatMountLabel(fmt.Sprintf("append%s", layer), mountLabel)
				if err = mount("none", target, "aufs", MsRemount, data); err != nil {
					return
				}
			}
		}

		if firstMount {
			opts := "dio,xino=/dev/shm/aufs.xino"
			if useDirperm() {
				opts += ",dirperm1"
			}
			data := label.FormatMountLabel(fmt.Sprintf("%s,%s", string(b[:bp]), opts), mountLabel)
			if err = mount("none", target, "aufs", 0, data); err != nil {
				return
			}
			firstMount = false
		}

		if i == len(ro) {
			break
		}
	}

	return
}
Пример #2
0
// Try to mount using the aufs fast path, if this fails then
// append ro layers.
func (a *Driver) tryMount(ro []string, rw, target, mountLabel string) (err error) {
	var (
		rwBranch   = fmt.Sprintf("%s=rw", rw)
		roBranches = fmt.Sprintf("%s=ro+wh:", strings.Join(ro, "=ro+wh:"))
		data       = label.FormatMountLabel(fmt.Sprintf("br:%v:%v,xino=/dev/shm/aufs.xino", rwBranch, roBranches), mountLabel)
	)
	return mount("none", target, "aufs", 0, data)
}
Пример #3
0
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
}
Пример #4
0
// Get creates and mounts the required file system for the given id and returns the mount path.
func (d *Driver) Get(id string, mountLabel string) (string, error) {
	// Protect the d.active from concurrent access
	d.Lock()
	defer d.Unlock()

	mount := d.active[id]
	if mount != nil {
		mount.count++
		return mount.path, nil
	}

	mount = &ActiveMount{count: 1}

	dir := d.dir(id)
	if _, err := os.Stat(dir); err != nil {
		return "", err
	}

	// If id has a root, just return it
	rootDir := path.Join(dir, "root")
	if _, err := os.Stat(rootDir); err == nil {
		mount.path = rootDir
		d.active[id] = mount
		return mount.path, nil
	}

	lowerID, err := ioutil.ReadFile(path.Join(dir, "lower-id"))
	if err != nil {
		return "", err
	}
	lowerDir := path.Join(d.dir(string(lowerID)), "root")
	upperDir := path.Join(dir, "upper")
	workDir := path.Join(dir, "work")
	mergedDir := path.Join(dir, "merged")

	opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", lowerDir, upperDir, workDir)
	if err := syscall.Mount("overlay", mergedDir, "overlay", 0, label.FormatMountLabel(opts, mountLabel)); err != nil {
		return "", fmt.Errorf("error creating overlay mount to %s: %v", mergedDir, err)
	}

	mount.path = mergedDir
	mount.mounted = true
	d.active[id] = mount

	return mount.path, nil
}
Пример #5
0
func (d *Driver) Get(id, mountLabel string) (string, error) {
	mountpoint := d.MountPath(id)
	filesystem := d.ZfsPath(id)
	options := label.FormatMountLabel("", mountLabel)
	log.Debugf(`[zfs] mount("%s", "%s", "%s")`, filesystem, mountpoint, options)

	// Create the target directories if they don't exist
	if err := os.MkdirAll(mountpoint, 0755); err != nil && !os.IsExist(err) {
		return "", err
	}

	err := mount.Mount(filesystem, mountpoint, "zfs", options)
	if err != nil {
		return "", fmt.Errorf("error creating zfs mount of %s to %s: %v", filesystem, mountpoint, err)
	}

	return mountpoint, nil
}
Пример #6
0
func (a *Driver) aufsMount(ro []string, rw, target, mountLabel string) (err error) {
	defer func() {
		if err != nil {
			Unmount(target)
		}
	}()

	if err = a.tryMount(ro, rw, target, mountLabel); err != nil {
		if err = a.mountRw(rw, target, mountLabel); err != nil {
			return
		}

		for _, layer := range ro {
			data := label.FormatMountLabel(fmt.Sprintf("append:%s=ro+wh", layer), mountLabel)
			if err = mount("none", target, "aufs", MsRemount, data); err != nil {
				return
			}
		}
	}
	return
}
Пример #7
0
func (m *Mount) tmpfsMount(rootfs, mountLabel string) error {
	var (
		err  error
		l    = label.FormatMountLabel("", mountLabel)
		dest = filepath.Join(rootfs, m.Destination)
	)

	// FIXME: (crosbymichael) This does not belong here and should be done a layer above
	if dest, err = symlink.FollowSymlinkInScope(dest, rootfs); err != nil {
		return err
	}

	if err := createIfNotExists(dest, true); err != nil {
		return fmt.Errorf("creating new tmpfs mount target %s", err)
	}

	if err := syscall.Mount("tmpfs", dest, "tmpfs", uintptr(defaultMountFlags), l); err != nil {
		return fmt.Errorf("%s mounting %s in tmpfs", err, dest)
	}

	return nil
}
Пример #8
0
func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
	var (
		dest = m.Destination
		data = label.FormatMountLabel(m.Data, mountLabel)
	)
	if !strings.HasPrefix(dest, rootfs) {
		dest = filepath.Join(rootfs, dest)
	}

	switch m.Device {
	case "proc", "sysfs":
		if err := os.MkdirAll(dest, 0755); err != nil && !os.IsExist(err) {
			return err
		}
		return syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), "")
	case "mqueue":
		if err := os.MkdirAll(dest, 0755); err != nil && !os.IsExist(err) {
			return err
		}
		if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), ""); err != nil {
			return err
		}
		return label.SetFileLabel(dest, mountLabel)
	case "tmpfs":
		stat, err := os.Stat(dest)
		if err != nil {
			if err := os.MkdirAll(dest, 0755); err != nil && !os.IsExist(err) {
				return err
			}
		}
		if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data); err != nil {
			return err
		}
		if stat != nil {
			if err = os.Chmod(dest, stat.Mode()); err != nil {
				return err
			}
		}
		return nil
	case "devpts":
		if err := os.MkdirAll(dest, 0755); err != nil && !os.IsExist(err) {
			return err
		}
		return syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data)
	case "bind":
		stat, err := os.Stat(m.Source)
		if err != nil {
			// error out if the source of a bind mount does not exist as we will be
			// unable to bind anything to it.
			return err
		}
		// ensure that the destination of the bind mount is resolved of symlinks at mount time because
		// any previous mounts can invalidate the next mount's destination.
		// this can happen when a user specifies mounts within other mounts to cause breakouts or other
		// evil stuff to try to escape the container's rootfs.
		if dest, err = symlink.FollowSymlinkInScope(filepath.Join(rootfs, m.Destination), rootfs); err != nil {
			return err
		}
		if err := checkMountDestination(rootfs, dest); err != nil {
			return err
		}
		if err := createIfNotExists(dest, stat.IsDir()); err != nil {
			return err
		}
		if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data); err != nil {
			return err
		}
		if m.Flags&syscall.MS_RDONLY != 0 {
			if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags|syscall.MS_REMOUNT), ""); err != nil {
				return err
			}
		}
		if m.Relabel != "" {
			if err := label.Relabel(m.Source, mountLabel, m.Relabel); err != nil {
				return err
			}
		}
		if m.Flags&syscall.MS_PRIVATE != 0 {
			if err := syscall.Mount("", dest, "none", uintptr(syscall.MS_PRIVATE), ""); err != nil {
				return err
			}
		}
	case "cgroup":
		mounts, err := cgroups.GetCgroupMounts()
		if err != nil {
			return err
		}
		var binds []*configs.Mount
		for _, mm := range mounts {
			dir, err := mm.GetThisCgroupDir()
			if err != nil {
				return err
			}
			binds = append(binds, &configs.Mount{
				Device:      "bind",
				Source:      filepath.Join(mm.Mountpoint, dir),
				Destination: filepath.Join(m.Destination, strings.Join(mm.Subsystems, ",")),
				Flags:       syscall.MS_BIND | syscall.MS_REC | syscall.MS_RDONLY,
			})
		}
		tmpfs := &configs.Mount{
			Device:      "tmpfs",
			Destination: m.Destination,
			Flags:       syscall.MS_NOEXEC | syscall.MS_NOSUID | syscall.MS_NODEV,
		}
		if err := mountToRootfs(tmpfs, rootfs, mountLabel); err != nil {
			return err
		}
		for _, b := range binds {
			if err := mountToRootfs(b, rootfs, mountLabel); err != nil {
				return err
			}
		}
	default:
		return fmt.Errorf("unknown mount device %q to %q", m.Device, m.Destination)
	}
	return nil
}
Пример #9
0
func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
	var (
		dest = m.Destination
		data = label.FormatMountLabel(m.Data, mountLabel)
	)
	if !strings.HasPrefix(dest, rootfs) {
		dest = filepath.Join(rootfs, dest)
	}

	switch m.Device {
	case "proc", "mqueue", "sysfs":
		if err := os.MkdirAll(dest, 0755); err != nil && !os.IsExist(err) {
			return err
		}
		return syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), "")
	case "tmpfs":
		stat, err := os.Stat(dest)
		if err != nil {
			if err := os.MkdirAll(dest, 0755); err != nil && !os.IsExist(err) {
				return err
			}
		}
		if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data); err != nil {
			return err
		}
		if stat != nil {
			if err = os.Chmod(dest, stat.Mode()); err != nil {
				return err
			}
		}
		return nil
	case "devpts":
		if err := os.MkdirAll(dest, 0755); err != nil && !os.IsExist(err) {
			return err
		}
		return syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data)
	case "bind":
		stat, err := os.Stat(m.Source)
		if err != nil {
			// error out if the source of a bind mount does not exist as we will be
			// unable to bind anything to it.
			return err
		}
		if err := createIfNotExists(dest, stat.IsDir()); err != nil {
			return err
		}
		if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data); err != nil {
			return err
		}
		if m.Flags&syscall.MS_RDONLY != 0 {
			if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags|syscall.MS_REMOUNT), ""); err != nil {
				return err
			}
		}
		if m.Relabel != "" {
			if err := label.Relabel(m.Source, mountLabel, m.Relabel); err != nil {
				return err
			}
		}
		if m.Flags&syscall.MS_PRIVATE != 0 {
			if err := syscall.Mount("", dest, "none", uintptr(syscall.MS_PRIVATE), ""); err != nil {
				return err
			}
		}
	default:
		return fmt.Errorf("unknown mount device %q to %q", m.Device, m.Destination)
	}
	return nil
}
Пример #10
0
func (a *Driver) mountRw(rw, target, mountLabel string) error {
	data := label.FormatMountLabel(fmt.Sprintf("br:%s,xino=/dev/shm/aufs.xino", rw), mountLabel)
	return mount("none", target, "aufs", 0, data)
}
Пример #11
0
// TODO: this is crappy right now and should be cleaned up with a better way of handling system and
// standard bind mounts allowing them to be more dynamic
func newSystemMounts(rootfs, mountLabel string, sysReadonly bool, mounts Mounts) []mount {
	systemMounts := []mount{
		{source: "proc", path: filepath.Join(rootfs, "proc"), device: "proc", flags: defaultMountFlags},
		{source: "tmpfs", path: filepath.Join(rootfs, "dev"), device: "tmpfs", flags: syscall.MS_NOSUID | syscall.MS_STRICTATIME, data: label.FormatMountLabel("mode=755", mountLabel)},
		{source: "shm", path: filepath.Join(rootfs, "dev", "shm"), device: "tmpfs", flags: defaultMountFlags, data: label.FormatMountLabel("mode=1777,size=65536k", mountLabel)},
		{source: "devpts", path: filepath.Join(rootfs, "dev", "pts"), device: "devpts", flags: syscall.MS_NOSUID | syscall.MS_NOEXEC, data: label.FormatMountLabel("newinstance,ptmxmode=0666,mode=620,gid=5", mountLabel)},
	}

	sysMountFlags := defaultMountFlags
	if sysReadonly {
		sysMountFlags |= syscall.MS_RDONLY
	}
	systemMounts = append(systemMounts, mount{source: "sysfs", path: filepath.Join(rootfs, "sys"), device: "sysfs", flags: sysMountFlags})

	return systemMounts
}
Пример #12
0
func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
	var (
		dest = m.Destination
		data = label.FormatMountLabel(m.Data, mountLabel)
	)
	if !strings.HasPrefix(dest, rootfs) {
		dest = filepath.Join(rootfs, dest)
	}

	switch m.Device {
	case "proc", "mqueue", "sysfs":
		if err := os.MkdirAll(dest, 0755); err != nil && !os.IsExist(err) {
			return err
		}
		return syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), "")
	case "tmpfs":
		stat, err := os.Stat(dest)
		if err != nil {
			if err := os.MkdirAll(dest, 0755); err != nil && !os.IsExist(err) {
				return err
			}
		}
		if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data); err != nil {
			return err
		}
		if stat != nil {
			if err = os.Chmod(dest, stat.Mode()); err != nil {
				return err
			}
		}
		return nil
	case "devpts":
		if err := os.MkdirAll(dest, 0755); err != nil && !os.IsExist(err) {
			return err
		}
		return syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data)
	case "bind":
		stat, err := os.Stat(m.Source)
		if err != nil {
			// error out if the source of a bind mount does not exist as we will be
			// unable to bind anything to it.
			return err
		}
		// ensure that the destination of the bind mount is resolved of symlinks at mount time because
		// any previous mounts can invalidate the next mount's destination.
		// this can happen when a user specifies mounts within other mounts to cause breakouts or other
		// evil stuff to try to escape the container's rootfs.
		if dest, err = symlink.FollowSymlinkInScope(filepath.Join(rootfs, m.Destination), rootfs); err != nil {
			return err
		}
		if err := checkMountDestination(rootfs, dest); err != nil {
			return err
		}
		if err := createIfNotExists(dest, stat.IsDir()); err != nil {
			return err
		}
		if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data); err != nil {
			return err
		}
		if m.Flags&syscall.MS_RDONLY != 0 {
			if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags|syscall.MS_REMOUNT), ""); err != nil {
				return err
			}
		}
		if m.Relabel != "" {
			if err := label.Relabel(m.Source, mountLabel, m.Relabel); err != nil {
				return err
			}
		}
		if m.Flags&syscall.MS_PRIVATE != 0 {
			if err := syscall.Mount("", dest, "none", uintptr(syscall.MS_PRIVATE), ""); err != nil {
				return err
			}
		}
	default:
		return fmt.Errorf("unknown mount device %q to %q", m.Device, m.Destination)
	}
	return nil
}
Пример #13
0
// TODO: this is crappy right now and should be cleaned up with a better way of handling system and
// standard bind mounts allowing them to be more dynamic
func newSystemMounts(rootfs, mountLabel string, mounts libcontainer.Mounts) []mount {
	systemMounts := []mount{
		{source: "proc", path: filepath.Join(rootfs, "proc"), device: "proc", flags: defaultMountFlags},
		{source: "sysfs", path: filepath.Join(rootfs, "sys"), device: "sysfs", flags: defaultMountFlags},
		{source: "tmpfs", path: filepath.Join(rootfs, "dev"), device: "tmpfs", flags: syscall.MS_NOSUID | syscall.MS_STRICTATIME, data: label.FormatMountLabel("mode=755", mountLabel)},
		{source: "shm", path: filepath.Join(rootfs, "dev", "shm"), device: "tmpfs", flags: defaultMountFlags, data: label.FormatMountLabel("mode=1777,size=65536k", mountLabel)},
		{source: "devpts", path: filepath.Join(rootfs, "dev", "pts"), device: "devpts", flags: syscall.MS_NOSUID | syscall.MS_NOEXEC, data: label.FormatMountLabel("newinstance,ptmxmode=0666,mode=620,gid=5", mountLabel)},
	}

	return systemMounts
}
Пример #14
0
func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
	var (
		dest = m.Destination
		data = label.FormatMountLabel(m.Data, mountLabel)
	)
	if !strings.HasPrefix(dest, rootfs) {
		dest = filepath.Join(rootfs, dest)
	}

	switch m.Device {
	case "proc", "sysfs":
		if err := os.MkdirAll(dest, 0755); err != nil && !os.IsExist(err) {
			return err
		}
		return syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), "")
	case "mqueue":
		if err := os.MkdirAll(dest, 0755); err != nil && !os.IsExist(err) {
			return err
		}
		if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), ""); err != nil {
			return err
		}
		return label.SetFileLabel(dest, mountLabel)
	case "tmpfs":
		stat, err := os.Stat(dest)
		if err != nil {
			if err := os.MkdirAll(dest, 0755); err != nil && !os.IsExist(err) {
				return err
			}
		}
		if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data); err != nil {
			return err
		}
		if stat != nil {
			if err = os.Chmod(dest, stat.Mode()); err != nil {
				return err
			}
		}
		return nil
	case "devpts":
		if err := os.MkdirAll(dest, 0755); err != nil && !os.IsExist(err) {
			return err
		}
		return syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data)
	case "bind":
		stat, err := os.Stat(m.Source)
		if err != nil {
			// error out if the source of a bind mount does not exist as we will be
			// unable to bind anything to it.
			return err
		}
		if err := createIfNotExists(dest, stat.IsDir()); err != nil {
			return err
		}
		if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data); err != nil {
			return err
		}
		if m.Flags&syscall.MS_RDONLY != 0 {
			if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags|syscall.MS_REMOUNT), ""); err != nil {
				return err
			}
		}
		if m.Relabel != "" {
			if err := label.Relabel(m.Source, mountLabel, m.Relabel); err != nil {
				return err
			}
		}
		if m.Flags&syscall.MS_PRIVATE != 0 {
			if err := syscall.Mount("", dest, "none", uintptr(syscall.MS_PRIVATE), ""); err != nil {
				return err
			}
		}
	case "cgroup":
		mounts, err := cgroups.GetCgroupMounts()
		if err != nil {
			return err
		}
		var binds []*configs.Mount
		for _, mm := range mounts {
			dir, err := mm.GetThisCgroupDir()
			if err != nil {
				return err
			}
			binds = append(binds, &configs.Mount{
				Device:      "bind",
				Source:      filepath.Join(mm.Mountpoint, dir),
				Destination: filepath.Join(m.Destination, strings.Join(mm.Subsystems, ",")),
				Flags:       syscall.MS_BIND | syscall.MS_REC | syscall.MS_RDONLY,
			})
		}
		tmpfs := &configs.Mount{
			Device:      "tmpfs",
			Destination: m.Destination,
			Flags:       syscall.MS_NOEXEC | syscall.MS_NOSUID | syscall.MS_NODEV,
		}
		if err := mountToRootfs(tmpfs, rootfs, mountLabel); err != nil {
			return err
		}
		for _, b := range binds {
			if err := mountToRootfs(b, rootfs, mountLabel); err != nil {
				return err
			}
		}
	default:
		return fmt.Errorf("unknown mount device %q to %q", m.Device, m.Destination)
	}
	return nil
}