[lxc-devel] [distrobuilder/master] chroot: Don't bind-mount /dev

monstermunchkin on Github lxc-bot at linuxcontainers.org
Tue Mar 3 10:58:38 UTC 2020


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 527 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200303/8f8e55e5/attachment.bin>
-------------- next part --------------
From 3affb6bb9aa8020eaabc7d3a4746bb3b59d3297a Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.hipp at canonical.com>
Date: Tue, 3 Mar 2020 11:28:33 +0100
Subject: [PATCH] chroot: Don't bind-mount /dev

Instead of bind-mounting /dev, it now creates necessary /dev files using
mknod. When creating VMs, it bind-mounts the loop device and its
partitions as well.

Signed-off-by: Thomas Hipp <thomas.hipp at canonical.com>
---
 distrobuilder/main_lxd.go | 16 +++++++++++++
 distrobuilder/vm.go       |  4 ++++
 shared/chroot.go          | 48 ++++++++++++++++++++++++++++++++++++++-
 3 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/distrobuilder/main_lxd.go b/distrobuilder/main_lxd.go
index 2fa2648..0bd314f 100644
--- a/distrobuilder/main_lxd.go
+++ b/distrobuilder/main_lxd.go
@@ -9,6 +9,7 @@ import (
 	lxd "github.com/lxc/lxd/shared"
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
+	"golang.org/x/sys/unix"
 
 	"github.com/lxc/distrobuilder/generators"
 	"github.com/lxc/distrobuilder/image"
@@ -269,6 +270,21 @@ func (c *cmdLXD) run(cmd *cobra.Command, args []string, overlayDir string) error
 		rootfsDir = vmDir
 
 		mounts = []shared.ChrootMount{
+			{
+				Source: vm.getLoopDev(),
+				Target: filepath.Join("/", "dev", filepath.Base(vm.getLoopDev())),
+				Flags:  unix.MS_BIND,
+			},
+			{
+				Source: vm.getRootfsDevFile(),
+				Target: filepath.Join("/", "dev", filepath.Base(vm.getRootfsDevFile())),
+				Flags:  unix.MS_BIND,
+			},
+			{
+				Source: vm.getUEFIDevFile(),
+				Target: filepath.Join("/", "dev", filepath.Base(vm.getUEFIDevFile())),
+				Flags:  unix.MS_BIND,
+			},
 			{
 				Source: vm.getUEFIDevFile(),
 				Target: "/boot/efi",
diff --git a/distrobuilder/vm.go b/distrobuilder/vm.go
index 1bcda60..f6ba300 100644
--- a/distrobuilder/vm.go
+++ b/distrobuilder/vm.go
@@ -38,6 +38,10 @@ func newVM(imageFile, rootfsDir, fs string, size uint64) (*vm, error) {
 	return &vm{imageFile: imageFile, rootfsDir: rootfsDir, rootFS: fs, size: size}, nil
 }
 
+func (v *vm) getLoopDev() string {
+	return v.loopDevice
+}
+
 func (v *vm) getRootfsDevFile() string {
 	if v.loopDevice == "" {
 		return ""
diff --git a/shared/chroot.go b/shared/chroot.go
index 13b215b..73282b8 100644
--- a/shared/chroot.go
+++ b/shared/chroot.go
@@ -174,7 +174,6 @@ func SetupChroot(rootfs string, envs DefinitionEnv, m []ChrootMount) (func() err
 	mounts := []ChrootMount{
 		{"none", "/proc", "proc", 0, "", true},
 		{"none", "/sys", "sysfs", 0, "", true},
-		{"/dev", "/dev", "", unix.MS_BIND | unix.MS_REC, "", true},
 		{"none", "/run", "tmpfs", 0, "", true},
 		{"none", "/tmp", "tmpfs", 0, "", true},
 		{"/etc/resolv.conf", "/etc/resolv.conf", "", unix.MS_BIND, "", false},
@@ -219,6 +218,12 @@ func SetupChroot(rootfs string, envs DefinitionEnv, m []ChrootMount) (func() err
 		return nil, err
 	}
 
+	// Populate /dev directory instead of bind mounting it from the host
+	err = populateDev()
+	if err != nil {
+		return nil, errors.Wrap(err, "Failed to populate /dev")
+	}
+
 	var env Environment
 
 	if envs.ClearDefaults {
@@ -329,3 +334,44 @@ exit 101
 
 	return exitFunc, nil
 }
+
+func populateDev() error {
+	devs := []struct {
+		Path  string
+		Major uint32
+		Minor uint32
+		Mode  uint32
+	}{
+		{"/dev/console", 5, 1, unix.S_IFCHR | 0640},
+		{"/dev/full", 1, 7, unix.S_IFCHR | 0666},
+		{"/dev/null", 1, 3, unix.S_IFCHR | 0666},
+		{"/dev/random", 1, 8, unix.S_IFCHR | 0666},
+		{"/dev/tty", 5, 0, unix.S_IFCHR | 0666},
+		{"/dev/urandom", 1, 9, unix.S_IFCHR | 0666},
+		{"/dev/zero", 1, 5, unix.S_IFCHR | 0666},
+	}
+
+	for _, d := range devs {
+		if lxd.PathExists(d.Path) {
+			continue
+		}
+
+		dev := unix.Mkdev(d.Major, d.Minor)
+
+		err := unix.Mknod(d.Path, d.Mode, int(dev))
+		if err != nil {
+			return errors.Wrapf(err, "Failed to create %q", d.Path)
+		}
+	}
+
+	if lxd.PathExists("/dev/fd") {
+		return nil
+	}
+
+	err := os.Symlink("/proc/self/fd", "/dev/fd")
+	if err != nil {
+		return errors.Wrapf(err, "Failed to link %q -> %q", "/dev/fd", "/proc/self/fd")
+	}
+
+	return nil
+}


More information about the lxc-devel mailing list