The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/7770
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com>
From d95d70e35f8cf7d8a9b0e926cad9167eb76dc15a Mon Sep 17 00:00:00 2001 From: Christian Brauner <christian.brau...@ubuntu.com> Date: Thu, 13 Aug 2020 12:01:08 +0200 Subject: [PATCH 1/4] main_checkfeature: remove logging failed shiftfs mounts Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com> --- lxd/main_checkfeature.go | 1 - 1 file changed, 1 deletion(-) diff --git a/lxd/main_checkfeature.go b/lxd/main_checkfeature.go index 4cebf7a5d0..a11ac9de74 100644 --- a/lxd/main_checkfeature.go +++ b/lxd/main_checkfeature.go @@ -584,7 +584,6 @@ func canUseShiftfs() bool { err = unix.Mount(shared.VarPath(), shared.VarPath(), "shiftfs", 0, "mark") if err != nil { - logger.Debugf("%s - Failed to mount shiftfs", err) return false } From 2171b5e4714f8c1b7206a14628c12d043dbafdf1 Mon Sep 17 00:00:00 2001 From: Christian Brauner <christian.brau...@ubuntu.com> Date: Thu, 13 Aug 2020 12:04:13 +0200 Subject: [PATCH 2/4] seccomp: log errors to convert unix connection to file Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com> --- lxd/seccomp/seccomp.go | 1 + 1 file changed, 1 insertion(+) diff --git a/lxd/seccomp/seccomp.go b/lxd/seccomp/seccomp.go index abeb307cd2..7467912b07 100644 --- a/lxd/seccomp/seccomp.go +++ b/lxd/seccomp/seccomp.go @@ -1008,6 +1008,7 @@ func NewSeccompServer(s *state.State, path string, findPID func(pid int32, state unixFile, err := c.(*net.UnixConn).File() if err != nil { + logger.Debugf("Failed to turn unix socket client into file") return } From 0285fe3c23f1987f2238bdaee4fe9b865911b595 Mon Sep 17 00:00:00 2001 From: Christian Brauner <christian.brau...@ubuntu.com> Date: Thu, 13 Aug 2020 13:04:35 +0200 Subject: [PATCH 3/4] unixfd: improve SCM_RIGHTs file descriptor retrieval - Restrict the maximum number of file descriptors to be sent to us to 253. This is the limit the kernel enforces and so isn't an arbitrary number. If we receive more file descriptors than we will simple close all of the received fds and report -EFBIG to the caller. There's no reason we should receive insane amounts of file descriptors via the seccomp proxy even if the kernel were to ever lift this limit. - If we receive less file descriptors than we expect we'll place -EBADF into the additional slots so the caller can check how many valid fds they actually received. - If we receive more file descriptors than we expect we'll simply close the additional ones. The logic being that we might deal with a revised version of the seccomp proxy in LXC that sends additional file descriptors. A LXD version that doesn't know about the additional fds doesn't need to worry about them. Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com> --- shared/netutils/unixfd.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/shared/netutils/unixfd.c b/shared/netutils/unixfd.c index d3c3b1dacf..32f5c0ded6 100644 --- a/shared/netutils/unixfd.c +++ b/shared/netutils/unixfd.c @@ -64,6 +64,8 @@ ssize_t lxc_abstract_unix_recv_fds_iov(int fd, int *recvfds, int num_recvfds, struct iovec *iov, size_t iovlen) { __do_free char *cmsgbuf = NULL; + int new_fds[253]; /* Maximum number of supported fds to be sent in one message is 253. */ + size_t num_new_fds = 0; ssize_t ret; struct msghdr msg = { 0 }; struct cmsghdr *cmsg = NULL; @@ -95,14 +97,33 @@ ssize_t lxc_abstract_unix_recv_fds_iov(int fd, int *recvfds, int num_recvfds, // If SO_PASSCRED is set we will always get a ucred message. for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { - if (cmsg->cmsg_type != SCM_RIGHTS) - continue; - - memset(recvfds, -1, num_recvfds * sizeof(int)); - if (cmsg && - cmsg->cmsg_len == CMSG_LEN(num_recvfds * sizeof(int)) && - cmsg->cmsg_level == SOL_SOCKET) - memcpy(recvfds, CMSG_DATA(cmsg), num_recvfds * sizeof(int)); + if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { + num_new_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); + + /* + * We received an insane amount of file descriptors + * which exceeds the kernel limit we know about so + * close them and return an error. + */ + if (num_new_fds >= 253) { + int *fd_ptr = (int *)CMSG_DATA(cmsg); + for (size_t i = 0; i < num_new_fds; i++) + close(fd_ptr[i]); + return -EFBIG; + } + + if (num_recvfds > num_new_fds) { + for (int i = num_new_fds; i < num_recvfds; i++) + recvfds[i] = -EBADF; + num_recvfds = num_new_fds; + } + + memcpy(new_fds, CMSG_DATA(cmsg), num_new_fds * sizeof(int)); + for (int i = num_recvfds; i < num_new_fds; i++) + close(new_fds[i]); + + memcpy(recvfds, new_fds, num_recvfds * sizeof(int)); + } break; } From 63c950462ab011c833e6e75f3d63415db9c6ac00 Mon Sep 17 00:00:00 2001 From: Christian Brauner <christian.brau...@ubuntu.com> Date: Thu, 13 Aug 2020 13:09:31 +0200 Subject: [PATCH 4/4] seccomp: simplify the seccomp message retrieval Instead of checking whether the LXC version we're dealing with supports the seccomp_proxy_send_notify_fd API extension we can simply use the new SCM_RIGHTS file descriptor retrieval logic we introduced earlier. This allows us to simplify the code. Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com> --- lxd/seccomp/seccomp.go | 40 ++++------------------------------------ 1 file changed, 4 insertions(+), 36 deletions(-) diff --git a/lxd/seccomp/seccomp.go b/lxd/seccomp/seccomp.go index 7467912b07..61825f3abf 100644 --- a/lxd/seccomp/seccomp.go +++ b/lxd/seccomp/seccomp.go @@ -870,21 +870,8 @@ func (siov *Iovec) PutSeccompIovec() { C.free(unsafe.Pointer(siov.iov)) } -// ReceiveSeccompIovecV1 receives a v1 seccomp iovec. -func (siov *Iovec) ReceiveSeccompIovecV1(fd int) (uint64, error) { - bytes, fds, err := netutils.AbstractUnixReceiveFdData(fd, 2, unsafe.Pointer(siov.iov), 4) - if err != nil || err == io.EOF { - return 0, err - } - - siov.procFd = int(fds[0]) - siov.memFd = int(fds[1]) - - return bytes, nil -} - -// ReceiveSeccompIovecV2 receives a v2 seccomp iovec. -func (siov *Iovec) ReceiveSeccompIovecV2(fd int) (uint64, error) { +// ReceiveSeccompIovec receives a seccomp iovec. +func (siov *Iovec) ReceiveSeccompIovec(fd int) (uint64, error) { bytes, fds, err := netutils.AbstractUnixReceiveFdData(fd, 3, unsafe.Pointer(siov.iov), 4) if err != nil || err == io.EOF { return 0, err @@ -893,6 +880,7 @@ func (siov *Iovec) ReceiveSeccompIovecV2(fd int) (uint64, error) { siov.procFd = int(fds[0]) siov.memFd = int(fds[1]) siov.notifyFd = int(fds[2]) + logger.Debugf("Syscall handler received fds %d(/proc/<pid>), %d(/proc/<pid>/mem), and %d([seccomp notify])", siov.procFd, siov.memFd, siov.notifyFd) return bytes, nil } @@ -1013,15 +1001,8 @@ func NewSeccompServer(s *state.State, path string, findPID func(pid int32, state } for { - var bytes uint64 - var err error - siov := NewSeccompIovec(ucred) - if lxcSupportSeccompV2(server.s) { - bytes, err = siov.ReceiveSeccompIovecV2(int(unixFile.Fd())) - } else { - bytes, err = siov.ReceiveSeccompIovecV1(int(unixFile.Fd())) - } + bytes, err := siov.ReceiveSeccompIovec(int(unixFile.Fd())) if err != nil { logger.Debugf("Disconnected from seccomp socket after failed receive: pid=%v, err=%s", ucred.Pid, err) c.Close() @@ -1902,19 +1883,6 @@ func (s *Server) Stop() error { return s.l.Close() } -func lxcSupportSeccompV2(state *state.State) bool { - err := lxcSupportSeccompNotify(state) - if err != nil { - return false - } - - if !state.OS.LXCFeatures["seccomp_proxy_send_notify_fd"] { - return false - } - - return true -} - func lxcSupportSeccompNotifyContinue(state *state.State) error { err := lxcSupportSeccompNotify(state) if err != nil {
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel