Beispiel #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", syscall.MS_REMOUNT, 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
}
Beispiel #2
0
Datei: zfs.go Projekt: vmware/vic
// Get returns the mountpoint for the given id after creating the target directories if necessary.
func (d *Driver) Get(id, mountLabel string) (string, error) {
	mountpoint := d.mountPath(id)
	filesystem := d.zfsPath(id)
	options := label.FormatMountLabel("", mountLabel)
	logrus.Debugf(`[zfs] mount("%s", "%s", "%s")`, filesystem, mountpoint, options)

	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
	if err != nil {
		return "", err
	}
	// Create the target directories if they don't exist
	if err := idtools.MkdirAllAs(mountpoint, 0755, rootUID, rootGID); err != nil {
		return "", err
	}

	if err := mount.Mount(filesystem, mountpoint, "zfs", options); err != nil {
		return "", fmt.Errorf("error creating zfs mount of %s to %s: %v", filesystem, mountpoint, err)
	}
	// this could be our first mount after creation of the filesystem, and the root dir may still have root
	// permissions instead of the remapped root uid:gid (if user namespaces are enabled):
	if err := os.Chown(mountpoint, rootUID, rootGID); err != nil {
		return "", fmt.Errorf("error modifying zfs mountpoint (%s) directory ownership: %v", mountpoint, err)
	}

	return mountpoint, nil
}
Beispiel #3
0
func (d *driver) Mount(
	device, target, mountOptions, mountLabel string) error {

	if d.isNfsDevice(device) {

		if err := d.nfsMount(device, target); err != nil {
			return err
		}

		os.MkdirAll(d.volumeMountPath(target), d.fileModeMountPath())
		os.Chmod(d.volumeMountPath(target), d.fileModeMountPath())

		return nil
	}

	fsType, err := probeFsType(device)
	if err != nil {
		return err
	}

	options := label.FormatMountLabel("", mountLabel)
	options = fmt.Sprintf("%s,%s", mountOptions, mountLabel)
	if fsType == "xfs" {
		options = fmt.Sprintf("%s,nouuid", mountOptions)
	}

	if err := mount.Mount(device, target, fsType, options); err != nil {
		return fmt.Errorf("Couldn't mount directory %s at %s: %s", device, target, err)
	}

	os.MkdirAll(d.volumeMountPath(target), d.fileModeMountPath())
	os.Chmod(d.volumeMountPath(target), d.fileModeMountPath())

	return nil
}
Beispiel #4
0
// 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
}
Beispiel #5
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)
	}
	// chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a
	// user namespace requires this to move a directory from lower to upper.
	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
	if err != nil {
		return "", err
	}

	if err := os.Chown(path.Join(workDir, "work"), rootUID, rootGID); err != nil {
		return "", err
	}
	mount.path = mergedDir
	mount.mounted = true
	d.active[id] = mount

	return mount.path, nil
}
Beispiel #6
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) {
	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 {
		d.pathCacheLock.Lock()
		d.pathCache[id] = rootDir
		d.pathCacheLock.Unlock()
		return rootDir, 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 it's mounted already, just return
	mounted, err := d.mounted(mergedDir)
	if err != nil {
		return "", err
	}
	if mounted {
		return mergedDir, nil
	}

	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)
	}
	// chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a
	// user namespace requires this to move a directory from lower to upper.
	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
	if err != nil {
		return "", err
	}

	if err := os.Chown(path.Join(workDir, "work"), rootUID, rootGID); err != nil {
		return "", err
	}

	d.pathCacheLock.Lock()
	d.pathCache[id] = mergedDir
	d.pathCacheLock.Unlock()

	return mergedDir, nil
}
Beispiel #7
0
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
}
Beispiel #8
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) (s string, err error) {
	dir := d.dir(id)
	if _, err := os.Stat(dir); err != nil {
		return "", err
	}

	diffDir := path.Join(dir, "diff")
	lowers, err := ioutil.ReadFile(path.Join(dir, lowerFile))
	if err != nil {
		// If no lower, just return diff directory
		if os.IsNotExist(err) {
			return diffDir, nil
		}
		return "", err
	}

	mergedDir := path.Join(dir, "merged")
	if count := d.ctr.Increment(mergedDir); count > 1 {
		return mergedDir, nil
	}
	defer func() {
		if err != nil {
			if c := d.ctr.Decrement(mergedDir); c <= 0 {
				syscall.Unmount(mergedDir, 0)
			}
		}
	}()

	workDir := path.Join(dir, "work")
	opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", string(lowers), path.Join(id, "diff"), path.Join(id, "work"))
	mountLabel = label.FormatMountLabel(opts, mountLabel)
	if len(mountLabel) > syscall.Getpagesize() {
		return "", fmt.Errorf("cannot mount layer, mount label too large %d", len(mountLabel))
	}

	if err := mountFrom(d.home, "overlay", path.Join(id, "merged"), "overlay", mountLabel); err != nil {
		return "", fmt.Errorf("error creating overlay mount to %s: %v", mergedDir, err)
	}

	// chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a
	// user namespace requires this to move a directory from lower to upper.
	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
	if err != nil {
		return "", err
	}

	if err := os.Chown(path.Join(workDir, "work"), rootUID, rootGID); err != nil {
		return "", err
	}

	return mergedDir, nil
}
Beispiel #9
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) (s string, err error) {
	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 {
		return rootDir, nil
	}
	mergedDir := path.Join(dir, "merged")
	if count := d.ctr.Increment(mergedDir); count > 1 {
		return mergedDir, nil
	}
	defer func() {
		if err != nil {
			if c := d.ctr.Decrement(mergedDir); c <= 0 {
				syscall.Unmount(mergedDir, 0)
			}
		}
	}()
	lowerID, err := ioutil.ReadFile(path.Join(dir, "lower-id"))
	if err != nil {
		return "", err
	}
	var (
		lowerDir = path.Join(d.dir(string(lowerID)), "root")
		upperDir = path.Join(dir, "upper")
		workDir  = path.Join(dir, "work")
		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)
	}
	// chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a
	// user namespace requires this to move a directory from lower to upper.
	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
	if err != nil {
		return "", err
	}
	if err := os.Chown(path.Join(workDir, "work"), rootUID, rootGID); err != nil {
		return "", err
	}
	return mergedDir, nil
}
Beispiel #10
0
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
}
Beispiel #11
0
// Get returns the mountpoint for the given id after creating the target directories if necessary.
func (d *Driver) Get(id, mountLabel string) (string, error) {
	mountpoint := d.MountPath(id)
	filesystem := d.ZfsPath(id)
	options := label.FormatMountLabel("", mountLabel)
	logrus.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 {
		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
}
Beispiel #12
0
func (driver *Driver) Mount(device, target, mountOptions, mountLabel string) error {

	fsType, err := probeFsType(device)
	if err != nil {
		return err
	}

	options := label.FormatMountLabel("", mountLabel)
	options = fmt.Sprintf("%s,%s", mountOptions, mountLabel)
	if fsType == "xfs" {
		options = fmt.Sprintf("%s,nouuid", mountOptions)
	}

	if err := mount.Mount(device, target, fsType, options); err != nil {
		return fmt.Errorf("Couldn't mount directory %s at %s: %s", device, target, err)
	}

	return nil
}
Beispiel #13
0
// 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)
	)
	if !strings.HasPrefix(dest, rootfs) {
		dest = filepath.Join(rootfs, dest)
	}

	if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data); err != nil {
		return err
	}

	for _, pflag := range m.PropagationFlags {
		if err := syscall.Mount("", dest, "", uintptr(pflag), ""); err != nil {
			return err
		}
	}
	return nil
}
Beispiel #14
0
// Get returns the mountpoint for the given id after creating the target directories if necessary.
func (d *Driver) Get(id, mountLabel string) (string, error) {
	mountpoint := d.mountPath(id)
	filesystem := d.zfsPath(id)
	options := label.FormatMountLabel("", mountLabel)
	logrus.Debugf(`[zfs] mount("%s", "%s", "%s")`, filesystem, mountpoint, options)

	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
	if err != nil {
		return "", err
	}
	// Create the target directories if they don't exist
	if err := idtools.MkdirAllAs(mountpoint, 0755, rootUID, rootGID); err != nil {
		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
}
Beispiel #15
0
func (daemon *Daemon) setupIpcDirs(container *Container) error {
	rootUID, rootGID := daemon.GetRemappedUIDGID()
	if !container.hasMountFor("/dev/shm") {
		shmPath, err := container.shmPath()
		if err != nil {
			return err
		}

		if err := idtools.MkdirAllAs(shmPath, 0700, rootUID, rootGID); err != nil {
			return err
		}

		// When ShmSize is 0 or less, the SHM size is set to 64MB.
		if container.hostConfig.ShmSize <= 0 {
			container.hostConfig.ShmSize = 67108864
		}
		shmproperty := "mode=1777,size=" + strconv.FormatInt(container.hostConfig.ShmSize, 10)
		if err := syscall.Mount("shm", shmPath, "tmpfs", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), label.FormatMountLabel(shmproperty, container.getMountLabel())); err != nil {
			return fmt.Errorf("mounting shm tmpfs: %s", err)
		}
		if err := os.Chown(shmPath, rootUID, rootGID); err != nil {
			return err
		}
	}

	if !container.hasMountFor("/dev/mqueue") {
		mqueuePath, err := container.mqueuePath()
		if err != nil {
			return err
		}

		if err := idtools.MkdirAllAs(mqueuePath, 0700, rootUID, rootGID); 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)
		}
		if err := os.Chown(mqueuePath, rootUID, rootGID); err != nil {
			return err
		}
	}

	return nil
}
func (daemon *Daemon) setupIpcDirs(c *container.Container) error {
	rootUID, rootGID := daemon.GetRemappedUIDGID()
	if !c.HasMountFor("/dev/shm") {
		shmPath, err := c.ShmResourcePath()
		if err != nil {
			return err
		}

		if err := idtools.MkdirAllAs(shmPath, 0700, rootUID, rootGID); err != nil {
			return err
		}

		shmSize := container.DefaultSHMSize
		if c.HostConfig.ShmSize != 0 {
			shmSize = c.HostConfig.ShmSize
		}
		shmproperty := "mode=1777,size=" + strconv.FormatInt(shmSize, 10)
		if err := syscall.Mount("shm", shmPath, "tmpfs", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), label.FormatMountLabel(shmproperty, c.GetMountLabel())); err != nil {
			return fmt.Errorf("mounting shm tmpfs: %s", err)
		}
		if err := os.Chown(shmPath, rootUID, rootGID); err != nil {
			return err
		}
	}

	if !c.HasMountFor("/dev/mqueue") {
		mqueuePath, err := c.MqueueResourcePath()
		if err != nil {
			return err
		}

		if err := idtools.MkdirAllAs(mqueuePath, 0700, rootUID, rootGID); 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
}
Beispiel #17
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":
		binds, err := getCgroupMounts(m)
		if err != nil {
			return err
		}
		var merged []string
		for _, b := range binds {
			ss := filepath.Base(b.Destination)
			if strings.Contains(ss, ",") {
				merged = append(merged, ss)
			}
		}
		tmpfs := &configs.Mount{
			Source:      "tmpfs",
			Device:      "tmpfs",
			Destination: m.Destination,
			Flags:       defaultMountFlags,
		}
		if err := mountToRootfs(tmpfs, rootfs, mountLabel); err != nil {
			return err
		}
		for _, b := range binds {
			if err := mountToRootfs(b, rootfs, mountLabel); err != nil {
				return err
			}
		}
		// create symlinks for merged cgroups
		cwd, err := os.Getwd()
		if err != nil {
			return err
		}
		if err := os.Chdir(filepath.Join(rootfs, m.Destination)); err != nil {
			return err
		}
		for _, mc := range merged {
			for _, ss := range strings.Split(mc, ",") {
				if err := os.Symlink(mc, ss); err != nil {
					// if cgroup already exists, then okay(it could have been created before)
					if os.IsExist(err) {
						continue
					}
					os.Chdir(cwd)
					return err
				}
			}
		}
		if err := os.Chdir(cwd); err != nil {
			return err
		}
	default:
		return fmt.Errorf("unknown mount device %q to %q", m.Device, m.Destination)
	}
	return nil
}
Beispiel #18
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) (s string, err error) {
	dir := d.dir(id)
	if _, err := os.Stat(dir); err != nil {
		return "", err
	}

	diffDir := path.Join(dir, "diff")
	lowers, err := ioutil.ReadFile(path.Join(dir, lowerFile))
	if err != nil {
		// If no lower, just return diff directory
		if os.IsNotExist(err) {
			return diffDir, nil
		}
		return "", err
	}

	mergedDir := path.Join(dir, "merged")
	if count := d.ctr.Increment(mergedDir); count > 1 {
		return mergedDir, nil
	}
	defer func() {
		if err != nil {
			if c := d.ctr.Decrement(mergedDir); c <= 0 {
				syscall.Unmount(mergedDir, 0)
			}
		}
	}()

	workDir := path.Join(dir, "work")
	splitLowers := strings.Split(string(lowers), ":")
	absLowers := make([]string, len(splitLowers))
	for i, s := range splitLowers {
		absLowers[i] = path.Join(d.home, s)
	}
	opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", strings.Join(absLowers, ":"), path.Join(dir, "diff"), path.Join(dir, "work"))
	mountData := label.FormatMountLabel(opts, mountLabel)
	mount := syscall.Mount
	mountTarget := mergedDir

	pageSize := syscall.Getpagesize()

	// Go can return a larger page size than supported by the system
	// as of go 1.7. This will be fixed in 1.8 and this block can be
	// removed when building with 1.8.
	// See https://github.com/golang/go/commit/1b9499b06989d2831e5b156161d6c07642926ee1
	// See https://github.com/docker/docker/issues/27384
	if pageSize > 4096 {
		pageSize = 4096
	}

	// Use relative paths and mountFrom when the mount data has exceeded
	// the page size. The mount syscall fails if the mount data cannot
	// fit within a page and relative links make the mount data much
	// smaller at the expense of requiring a fork exec to chroot.
	if len(mountData) > pageSize {
		opts = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", string(lowers), path.Join(id, "diff"), path.Join(id, "work"))
		mountData = label.FormatMountLabel(opts, mountLabel)
		if len(mountData) > pageSize {
			return "", fmt.Errorf("cannot mount layer, mount label too large %d", len(mountData))
		}

		mount = func(source string, target string, mType string, flags uintptr, label string) error {
			return mountFrom(d.home, source, target, mType, flags, label)
		}
		mountTarget = path.Join(id, "merged")
	}

	if err := mount("overlay", mountTarget, "overlay", 0, mountData); err != nil {
		return "", fmt.Errorf("error creating overlay mount to %s: %v", mergedDir, err)
	}

	// chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a
	// user namespace requires this to move a directory from lower to upper.
	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
	if err != nil {
		return "", err
	}

	if err := os.Chown(path.Join(workDir, "work"), rootUID, rootGID); err != nil {
		return "", err
	}

	return mergedDir, nil
}
Beispiel #19
0
func (container *Container) setupIpcDirs() error {
	rootUID, rootGID := container.daemon.GetRemappedUIDGID()
	if !container.hasMountFor("/dev/shm") {
		shmPath, err := container.shmPath()
		if err != nil {
			return err
		}

		if err := idtools.MkdirAllAs(shmPath, 0700, rootUID, rootGID); 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)
		}
		if err := os.Chown(shmPath, rootUID, rootGID); err != nil {
			return err
		}
	}

	if !container.hasMountFor("/dev/mqueue") {
		mqueuePath, err := container.mqueuePath()
		if err != nil {
			return err
		}

		if err := idtools.MkdirAllAs(mqueuePath, 0700, rootUID, rootGID); 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)
		}
		if err := os.Chown(mqueuePath, rootUID, rootGID); err != nil {
			return err
		}
	}

	return nil
}
func (daemon *Daemon) setupIpcDirs(c *container.Container) error {
	var err error

	c.ShmPath, err = c.ShmResourcePath()
	if err != nil {
		return err
	}

	if c.HostConfig.IpcMode.IsContainer() {
		ic, err := daemon.getIpcContainer(c)
		if err != nil {
			return err
		}
		c.ShmPath = ic.ShmPath
	} else if c.HostConfig.IpcMode.IsHost() {
		if _, err := os.Stat("/dev/shm"); err != nil {
			return fmt.Errorf("/dev/shm is not mounted, but must be for --ipc=host")
		}
		c.ShmPath = "/dev/shm"
	} else {
		rootUID, rootGID := daemon.GetRemappedUIDGID()
		if !c.HasMountFor("/dev/shm") {
			shmPath, err := c.ShmResourcePath()
			if err != nil {
				return err
			}

			if err := idtools.MkdirAllAs(shmPath, 0700, rootUID, rootGID); err != nil {
				return err
			}

			shmSize := container.DefaultSHMSize
			if c.HostConfig.ShmSize != 0 {
				shmSize = c.HostConfig.ShmSize
			}
			shmproperty := "mode=1777,size=" + strconv.FormatInt(shmSize, 10)
			if err := syscall.Mount("shm", shmPath, "tmpfs", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), label.FormatMountLabel(shmproperty, c.GetMountLabel())); err != nil {
				return fmt.Errorf("mounting shm tmpfs: %s", err)
			}
			if err := os.Chown(shmPath, rootUID, rootGID); err != nil {
				return err
			}
		}

	}

	return nil
}
Beispiel #21
0
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
}
Beispiel #22
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",
			Source:      "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
}