[lxc-devel] [lxd/master] seccomp: retry with mount hotplug
brauner on Github
lxc-bot at linuxcontainers.org
Mon Jun 17 18:05:09 UTC 2019
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 438 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190617/a49b2628/attachment.bin>
-------------- next part --------------
From 8f33d911f2bd74f943d0b029d644fe9df939385b Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Mon, 17 Jun 2019 19:58:57 +0200
Subject: [PATCH 1/2] container_lxc: add insertMount() helpers
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
lxd/container_lxc.go | 119 ++++++++++++++++++++++++-------------------
1 file changed, 66 insertions(+), 53 deletions(-)
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index f5cad36e9e..1c8b113c2e 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -7064,76 +7064,89 @@ func (c *containerLXC) StorageStop() (bool, error) {
}
// Mount handling
-func (c *containerLXC) insertMount(source, target, fstype string, flags int) error {
- var err error
-
- // Get the init PID
- pid := c.InitPID()
- if pid == -1 {
- // Container isn't running
- return fmt.Errorf("Can't insert mount into stopped container")
- }
+func (c *containerLXC) insertMountLXD(source, target, fstype string, flags int, mntnsPID int) error {
- if c.state.OS.LXCFeatures["mount_injection_file"] {
- cname := projectPrefix(c.Project(), c.Name())
- configPath := filepath.Join(c.LogPath(), "lxc.conf")
- if fstype == "" {
- fstype = "none"
- }
-
- if !strings.HasPrefix(target, "/") {
- target = "/" + target
+ pid := mntnsPID
+ if pid <= 0 {
+ // Get the init PID
+ pid = c.InitPID()
+ if pid == -1 {
+ // Container isn't running
+ return fmt.Errorf("Can't insert mount into stopped container")
}
+ }
- _, err := shared.RunCommand(c.state.OS.ExecPath, "forkmount", "lxc-mount", cname, c.state.OS.LxcPath, configPath, source, target, fstype, fmt.Sprintf("%d", flags))
+ // Create the temporary mount target
+ var tmpMount string
+ var err error
+ if shared.IsDir(source) {
+ tmpMount, err = ioutil.TempDir(c.ShmountsPath(), "lxdmount_")
if err != nil {
- return err
+ return fmt.Errorf("Failed to create shmounts path: %s", err)
}
} else {
- // Create the temporary mount target
- var tmpMount string
- if shared.IsDir(source) {
- tmpMount, err = ioutil.TempDir(c.ShmountsPath(), "lxdmount_")
- if err != nil {
- return fmt.Errorf("Failed to create shmounts path: %s", err)
- }
- } else {
- f, err := ioutil.TempFile(c.ShmountsPath(), "lxdmount_")
- if err != nil {
- return fmt.Errorf("Failed to create shmounts path: %s", err)
- }
-
- tmpMount = f.Name()
- f.Close()
- }
- defer os.Remove(tmpMount)
-
- // Mount the filesystem
- err = unix.Mount(source, tmpMount, fstype, uintptr(flags), "")
+ f, err := ioutil.TempFile(c.ShmountsPath(), "lxdmount_")
if err != nil {
- return fmt.Errorf("Failed to setup temporary mount: %s", err)
+ return fmt.Errorf("Failed to create shmounts path: %s", err)
}
- defer unix.Unmount(tmpMount, unix.MNT_DETACH)
- // Move the mount inside the container
- mntsrc := filepath.Join("/dev/.lxd-mounts", filepath.Base(tmpMount))
- pidStr := fmt.Sprintf("%d", pid)
+ tmpMount = f.Name()
+ f.Close()
+ }
+ defer os.Remove(tmpMount)
- out, err := shared.RunCommand(c.state.OS.ExecPath, "forkmount", "lxd-mount", pidStr, mntsrc, target)
+ // Mount the filesystem
+ err = unix.Mount(source, tmpMount, fstype, uintptr(flags), "")
+ if err != nil {
+ return fmt.Errorf("Failed to setup temporary mount: %s", err)
+ }
+ defer unix.Unmount(tmpMount, unix.MNT_DETACH)
- if out != "" {
- for _, line := range strings.Split(strings.TrimRight(out, "\n"), "\n") {
- logger.Debugf("forkmount: %s", line)
- }
- }
- if err != nil {
- return err
+ // Move the mount inside the container
+ mntsrc := filepath.Join("/dev/.lxd-mounts", filepath.Base(tmpMount))
+ pidStr := fmt.Sprintf("%d", pid)
+
+ out, err := shared.RunCommand(c.state.OS.ExecPath, "forkmount", "lxd-mount", pidStr, mntsrc, target)
+
+ if out != "" {
+ for _, line := range strings.Split(strings.TrimRight(out, "\n"), "\n") {
+ logger.Debugf("forkmount: %s", line)
}
}
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (c *containerLXC) insertMountLXC(source, target, fstype string, flags int) error {
+ cname := projectPrefix(c.Project(), c.Name())
+ configPath := filepath.Join(c.LogPath(), "lxc.conf")
+ if fstype == "" {
+ fstype = "none"
+ }
+
+ if !strings.HasPrefix(target, "/") {
+ target = "/" + target
+ }
+
+ _, err := shared.RunCommand(c.state.OS.ExecPath, "forkmount", "lxc-mount", cname, c.state.OS.LxcPath, configPath, source, target, fstype, fmt.Sprintf("%d", flags))
+ if err != nil {
+ return err
+ }
return nil
}
+func (c *containerLXC) insertMount(source, target, fstype string, flags int) error {
+ if c.state.OS.LXCFeatures["mount_injection_file"] {
+ return c.insertMountLXC(source, target, fstype, flags)
+ }
+
+ return c.insertMountLXD(source, target, fstype, flags, -1)
+}
+
func (c *containerLXC) removeMount(mount string) error {
// Get the init PID
pid := c.InitPID()
From 41df0a784ff1376c3a77cc95556d6ed4afc5dfa0 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Mon, 17 Jun 2019 19:59:55 +0200
Subject: [PATCH 2/2] seccomp: retry with mount hotplug
When device creation via mknod fails, fallback to messing with mounts.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
lxd/container.go | 2 ++
lxd/container_lxc.go | 24 ++++++++++++++++++++++++
lxd/seccomp.go | 37 +++++++++++++++++++++++++++++--------
3 files changed, 55 insertions(+), 8 deletions(-)
diff --git a/lxd/container.go b/lxd/container.go
index a526d2bee6..3fba380612 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -729,6 +729,8 @@ type container interface {
CurrentIdmap() (*idmap.IdmapSet, error)
DiskIdmap() (*idmap.IdmapSet, error)
NextIdmap() (*idmap.IdmapSet, error)
+
+ InsertSeccompUnixDevice(prefix string, m types.Device, pid int) error
}
// Loader functions
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 1c8b113c2e..97227025c1 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -7400,6 +7400,30 @@ func (c *containerLXC) insertUnixDevice(prefix string, m types.Device, defaultMo
return nil
}
+func (c *containerLXC) InsertSeccompUnixDevice(prefix string, m types.Device, pid int) error {
+
+ if pid < 0 {
+ return fmt.Errorf("Invalid request PID specified")
+ }
+
+ cwdLink := fmt.Sprintf("/proc/%d/cwd", pid)
+ prefixPath, err := os.Readlink(cwdLink)
+ if err != nil {
+ return err
+ }
+
+ m["path"] = fmt.Sprintf("%s/%s", prefixPath, m["path"])
+ paths, err := c.createUnixDevice(prefix, m, true)
+ if err != nil {
+ return fmt.Errorf("Failed to setup device: %s", err)
+ }
+ devPath := paths[0]
+ tgtPath := paths[1]
+
+ // Bind-mount it into the container
+ return c.insertMountLXD(devPath, tgtPath, "none", unix.MS_BIND, pid)
+}
+
func (c *containerLXC) insertUnixDeviceNum(name string, m types.Device, major int, minor int, path string, defaultMode bool) error {
temp := types.Device{}
if err := shared.DeepCopy(&m, &temp); err != nil {
diff --git a/lxd/seccomp.go b/lxd/seccomp.go
index 32397b9729..b0766ea63d 100644
--- a/lxd/seccomp.go
+++ b/lxd/seccomp.go
@@ -15,6 +15,7 @@ import (
"golang.org/x/sys/unix"
+ "github.com/lxc/lxd/lxd/types"
"github.com/lxc/lxd/lxd/util"
"github.com/lxc/lxd/shared"
"github.com/lxc/lxd/shared/logger"
@@ -130,6 +131,7 @@ static int seccomp_notify_mknod_set_response(int fd_mem, struct seccomp_notify_p
resp->id = req->id;
resp->flags = req->flags;
resp->val = 0;
+ resp->error = 0;
switch (req->data.nr) {
#ifdef LXD_MUST_CHECK_MKNOD
@@ -457,21 +459,40 @@ func (s *SeccompServer) Handler(c net.Conn, ucred *ucred, buf []byte, fdMem int)
unix.PathMax, &cMode,
&cDev, &cPid)
if ret == 0 {
+ devPath := C.GoString(&cPathBuf[0])
errnoMsg, err := shared.RunCommand(util.GetExecPath(),
"forkmknod",
fmt.Sprintf("%d", cPid),
- C.GoString(&cPathBuf[0]),
+ devPath,
fmt.Sprintf("%d", cMode),
fmt.Sprintf("%d", cDev))
if err != nil {
- cErrno := C.int(-C.EPERM)
- goErrno, err2 := strconv.Atoi(errnoMsg)
- if err2 == nil {
- cErrno = -C.int(goErrno)
- }
+ // Do not call functions that would call into liblxc since this would timeout the seccomp notifier
+ c, err := findContainerForPid(int32(msg.monitor_pid), s.d)
+ if err != nil {
+ cErrno := C.int(-C.EPERM)
+ goErrno, err2 := strconv.Atoi(errnoMsg)
+ if err2 == nil {
+ cErrno = -C.int(goErrno)
+ }
+
+ C.seccomp_notify_mknod_update_response(&msg, cErrno)
+ logger.Errorf("Failed to create device node: %s", err)
+ } else {
+ dev := types.Device{}
+ dev["type"] = "unix-char"
+ dev["path"] = devPath
+ dev["major"] = fmt.Sprintf("%d", unix.Major(uint64(cDev)))
+ dev["minor"] = fmt.Sprintf("%d", unix.Minor(uint64(cDev)))
- C.seccomp_notify_mknod_update_response(&msg, cErrno)
- logger.Errorf("Failed to create device node: %s", err)
+ err = c.InsertSeccompUnixDevice("forkmknod-unix-char", dev, int(cPid))
+ if err != nil {
+ C.seccomp_notify_mknod_update_response(&msg, C.ENOSYS)
+ logger.Errorf("Failed to create device node: %s", err)
+ }
+
+ os.Remove(dev["hostpath"])
+ }
}
}
More information about the lxc-devel
mailing list