The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/5744
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) ===
From 2768b6646834078e4a702e7012d028965cb318dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com> Date: Wed, 8 May 2019 18:10:05 -0400 Subject: [PATCH 1/2] shared: Move network cgo to shared/netutils MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber <stgra...@ubuntu.com> --- lxd/container_exec.go | 3 ++- lxd/container_lxc.go | 3 ++- lxd/main_checkfeature.go | 2 +- lxd/main_forknet.go | 4 ++-- lxd/main_forkuevent.go | 2 +- shared/{ => netutils}/netns_getifaddrs.c | 0 shared/{ => netutils}/network.c | 2 +- shared/{ => netutils}/network_linux.go | 9 +++++---- shared/network.go | 6 +++--- 9 files changed, 17 insertions(+), 14 deletions(-) rename shared/{ => netutils}/netns_getifaddrs.c (100%) rename shared/{ => netutils}/network.c (99%) rename shared/{ => netutils}/network_linux.go (96%) diff --git a/lxd/container_exec.go b/lxd/container_exec.go index 238b1df3a0..76159915d5 100644 --- a/lxd/container_exec.go +++ b/lxd/container_exec.go @@ -21,6 +21,7 @@ import ( "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/api" "github.com/lxc/lxd/shared/logger" + "github.com/lxc/lxd/shared/netutils" "github.com/lxc/lxd/shared/version" log "github.com/lxc/lxd/shared/log15" @@ -238,7 +239,7 @@ func (s *execWs) Do(op *operation) error { s.connsLock.Unlock() logger.Debugf("Starting to mirror websocket") - readDone, writeDone := shared.WebsocketExecMirror(conn, ptys[0], ptys[0], attachedChildIsDead, int(ptys[0].Fd())) + readDone, writeDone := netutils.WebsocketExecMirror(conn, ptys[0], ptys[0], attachedChildIsDead, int(ptys[0].Fd())) <-readDone <-writeDone diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go index 508a8db697..6c0af09783 100644 --- a/lxd/container_lxc.go +++ b/lxd/container_lxc.go @@ -38,6 +38,7 @@ import ( "github.com/lxc/lxd/shared/api" "github.com/lxc/lxd/shared/idmap" "github.com/lxc/lxd/shared/logger" + "github.com/lxc/lxd/shared/netutils" "github.com/lxc/lxd/shared/osarch" log "github.com/lxc/lxd/shared/log15" @@ -6354,7 +6355,7 @@ func (c *containerLXC) networkState() map[string]api.ContainerStateNetwork { couldUseNetnsGetifaddrs := c.state.OS.NetnsGetifaddrs if couldUseNetnsGetifaddrs { - nw, err := shared.NetnsGetifaddrs(int32(pid)) + nw, err := netutils.NetnsGetifaddrs(int32(pid)) if err != nil { couldUseNetnsGetifaddrs = false logger.Error("Failed to retrieve network information via netlink", log.Ctx{"container": c.name, "pid": pid}) diff --git a/lxd/main_checkfeature.go b/lxd/main_checkfeature.go index 3b12811b0c..87fced5fd7 100644 --- a/lxd/main_checkfeature.go +++ b/lxd/main_checkfeature.go @@ -24,7 +24,7 @@ import ( #include <linux/audit.h> #include <sys/ptrace.h> -#include "../shared/netns_getifaddrs.c" +#include "../shared/netutils/netns_getifaddrs.c" #include "include/memory_utils.h" bool netnsid_aware = false; diff --git a/lxd/main_forknet.go b/lxd/main_forknet.go index e7ef06e664..1c04dea924 100644 --- a/lxd/main_forknet.go +++ b/lxd/main_forknet.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" - "github.com/lxc/lxd/shared" + "github.com/lxc/lxd/shared/netutils" ) /* @@ -93,7 +93,7 @@ func (c *cmdForknet) Command() *cobra.Command { } func (c *cmdForknet) RunInfo(cmd *cobra.Command, args []string) error { - networks, err := shared.NetnsGetifaddrs(-1) + networks, err := netutils.NetnsGetifaddrs(-1) if err != nil { return err } diff --git a/lxd/main_forkuevent.go b/lxd/main_forkuevent.go index ed2ab419d3..8c769bb259 100644 --- a/lxd/main_forkuevent.go +++ b/lxd/main_forkuevent.go @@ -25,7 +25,7 @@ import ( #include <time.h> #include <unistd.h> -#include "../shared/network.c" +#include "../shared/netutils/network.c" #include "include/memory_utils.h" #ifndef UEVENT_SEND diff --git a/shared/netns_getifaddrs.c b/shared/netutils/netns_getifaddrs.c similarity index 100% rename from shared/netns_getifaddrs.c rename to shared/netutils/netns_getifaddrs.c diff --git a/shared/network.c b/shared/netutils/network.c similarity index 99% rename from shared/network.c rename to shared/netutils/network.c index d0f40b0393..882a1972c4 100644 --- a/shared/network.c +++ b/shared/netutils/network.c @@ -19,7 +19,7 @@ #include <sys/socket.h> #include <unistd.h> -#include "../lxd/include/macro.h" +#include "../../lxd/include/macro.h" #ifndef NETNS_RTA #define NETNS_RTA(r) \ diff --git a/shared/network_linux.go b/shared/netutils/network_linux.go similarity index 96% rename from shared/network_linux.go rename to shared/netutils/network_linux.go index 3e920f3ccb..afe3aa31c6 100644 --- a/shared/network_linux.go +++ b/shared/netutils/network_linux.go @@ -1,7 +1,7 @@ // +build linux // +build cgo -package shared +package netutils import ( "fmt" @@ -12,12 +12,13 @@ import ( "github.com/gorilla/websocket" + "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/api" "github.com/lxc/lxd/shared/logger" ) /* -#include "../shared/netns_getifaddrs.c" +#include "../../shared/netutils/netns_getifaddrs.c" */ // #cgo CFLAGS: -std=gnu11 -Wvla import "C" @@ -173,10 +174,10 @@ func WebsocketExecMirror(conn *websocket.Conn, w io.WriteCloser, r io.ReadCloser readDone := make(chan bool, 1) writeDone := make(chan bool, 1) - go defaultWriter(conn, w, writeDone) + go shared.DefaultWriter(conn, w, writeDone) go func(conn *websocket.Conn, r io.ReadCloser) { - in := ExecReaderToChannel(r, -1, exited, fd) + in := shared.ExecReaderToChannel(r, -1, exited, fd) for { buf, ok := <-in if !ok { diff --git a/shared/network.go b/shared/network.go index 9a37468c0c..00e200001e 100644 --- a/shared/network.go +++ b/shared/network.go @@ -326,7 +326,7 @@ func defaultReader(conn *websocket.Conn, r io.ReadCloser, readDone chan<- bool) r.Close() } -func defaultWriter(conn *websocket.Conn, w io.WriteCloser, writeDone chan<- bool) { +func DefaultWriter(conn *websocket.Conn, w io.WriteCloser, writeDone chan<- bool) { for { mt, r, err := conn.NextReader() if err != nil { @@ -382,7 +382,7 @@ func WebsocketMirror(conn *websocket.Conn, w io.WriteCloser, r io.ReadCloser, Re WriteFunc := Writer if WriteFunc == nil { - WriteFunc = defaultWriter + WriteFunc = DefaultWriter } go ReadFunc(conn, r, readDone) @@ -395,7 +395,7 @@ func WebsocketConsoleMirror(conn *websocket.Conn, w io.WriteCloser, r io.ReadClo readDone := make(chan bool, 1) writeDone := make(chan bool, 1) - go defaultWriter(conn, w, writeDone) + go DefaultWriter(conn, w, writeDone) go func(conn *websocket.Conn, r io.ReadCloser) { in := ReaderToChannel(r, -1) From 36c779639ae4536aaa1d0e964112188098f65d9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com> Date: Wed, 8 May 2019 18:33:39 -0400 Subject: [PATCH 2/2] shared/netutils: Move send/recv fd functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #5725 Signed-off-by: Stéphane Graber <stgra...@ubuntu.com> --- lxd/main_forkproxy.go | 5 +- lxd/seccomp.go | 3 +- shared/netutils/network_linux.go | 40 +++++++++ shared/netutils/unixfd.c | 114 +++++++++++++++++++++++++ shared/util_linux_cgo.go | 142 ------------------------------- 5 files changed, 159 insertions(+), 145 deletions(-) create mode 100644 shared/netutils/unixfd.c diff --git a/lxd/main_forkproxy.go b/lxd/main_forkproxy.go index dc1563d6a7..696953068f 100644 --- a/lxd/main_forkproxy.go +++ b/lxd/main_forkproxy.go @@ -16,6 +16,7 @@ import ( "github.com/spf13/cobra" "github.com/lxc/lxd/shared" + "github.com/lxc/lxd/shared/netutils" ) /* @@ -508,7 +509,7 @@ func (c *cmdForkproxy) Run(cmd *cobra.Command, args []string) error { } sAgain: - err = shared.AbstractUnixSendFd(forkproxyUDSSockFDNum, int(file.Fd())) + err = netutils.AbstractUnixSendFd(forkproxyUDSSockFDNum, int(file.Fd())) if err != nil { errno, ok := shared.GetErrno(err) if ok && (errno == syscall.EAGAIN) { @@ -566,7 +567,7 @@ func (c *cmdForkproxy) Run(cmd *cobra.Command, args []string) error { files := []*os.File{} for range lAddr.addr { rAgain: - f, err := shared.AbstractUnixReceiveFd(forkproxyUDSSockFDNum) + f, err := netutils.AbstractUnixReceiveFd(forkproxyUDSSockFDNum) if err != nil { errno, ok := shared.GetErrno(err) if ok && (errno == syscall.EAGAIN) { diff --git a/lxd/seccomp.go b/lxd/seccomp.go index 90a934a750..13ebcb3458 100644 --- a/lxd/seccomp.go +++ b/lxd/seccomp.go @@ -20,6 +20,7 @@ import ( "github.com/lxc/lxd/lxd/util" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/logger" + "github.com/lxc/lxd/shared/netutils" "github.com/lxc/lxd/shared/osarch" ) @@ -361,7 +362,7 @@ func NewSeccompServer(d *Daemon, path string) (*SeccompServer, error) { for { buf := make([]byte, C.SECCOMP_PROXY_MSG_SIZE) - fdMem, err := shared.AbstractUnixReceiveFdData(int(unixFile.Fd()), buf) + fdMem, err := netutils.AbstractUnixReceiveFdData(int(unixFile.Fd()), buf) if err != nil || err == io.EOF { logger.Debugf("Disconnected from seccomp socket after receive: pid=%v", ucred.pid) c.Close() diff --git a/shared/netutils/network_linux.go b/shared/netutils/network_linux.go index afe3aa31c6..957080a239 100644 --- a/shared/netutils/network_linux.go +++ b/shared/netutils/network_linux.go @@ -9,6 +9,7 @@ import ( "net" "os" "strings" + "unsafe" "github.com/gorilla/websocket" @@ -19,6 +20,7 @@ import ( /* #include "../../shared/netutils/netns_getifaddrs.c" +#include "../../shared/netutils/unixfd.c" */ // #cgo CFLAGS: -std=gnu11 -Wvla import "C" @@ -208,3 +210,41 @@ func WebsocketExecMirror(conn *websocket.Conn, w io.WriteCloser, r io.ReadCloser return readDone, writeDone } + +func AbstractUnixSendFd(sockFD int, sendFD int) error { + fd := C.int(sendFD) + sk_fd := C.int(sockFD) + ret := C.lxc_abstract_unix_send_fds(sk_fd, &fd, C.int(1), nil, C.size_t(0)) + if ret < 0 { + return fmt.Errorf("Failed to send file descriptor via abstract unix socket") + } + + return nil +} + +func AbstractUnixReceiveFd(sockFD int) (*os.File, error) { + fd := C.int(-1) + sk_fd := C.int(sockFD) + ret := C.lxc_abstract_unix_recv_fds(sk_fd, &fd, C.int(1), nil, C.size_t(0)) + if ret < 0 { + return nil, fmt.Errorf("Failed to receive file descriptor via abstract unix socket") + } + + file := os.NewFile(uintptr(fd), "") + return file, nil +} + +func AbstractUnixReceiveFdData(sockFD int, buf []byte) (int, error) { + fd := C.int(-1) + sk_fd := C.int(sockFD) + ret := C.lxc_abstract_unix_recv_fds(sk_fd, &fd, C.int(1), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) + if ret < 0 { + return int(-C.EBADF), fmt.Errorf("Failed to receive file descriptor via abstract unix socket") + } + + if ret == 0 { + return int(-C.EBADF), io.EOF + } + + return int(fd), nil +} diff --git a/shared/netutils/unixfd.c b/shared/netutils/unixfd.c new file mode 100644 index 0000000000..6aac9da772 --- /dev/null +++ b/shared/netutils/unixfd.c @@ -0,0 +1,114 @@ +// +build none + +#define _GNU_SOURCE +#include <errno.h> +#include <fcntl.h> +#include <grp.h> +#include <limits.h> +#include <poll.h> +#include <pty.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <sys/un.h> + +#include "../../lxd/include/memory_utils.h" + +int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds, + void *data, size_t size) +{ + __do_free char *cmsgbuf = NULL; + struct msghdr msg; + struct iovec iov; + struct cmsghdr *cmsg = NULL; + char buf[1] = {0}; + size_t cmsgbufsize = CMSG_SPACE(num_sendfds * sizeof(int)); + + memset(&msg, 0, sizeof(msg)); + memset(&iov, 0, sizeof(iov)); + + cmsgbuf = malloc(cmsgbufsize); + if (!cmsgbuf) + return -1; + + msg.msg_control = cmsgbuf; + msg.msg_controllen = cmsgbufsize; + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(num_sendfds * sizeof(int)); + + msg.msg_controllen = cmsg->cmsg_len; + + memcpy(CMSG_DATA(cmsg), sendfds, num_sendfds * sizeof(int)); + + iov.iov_base = data ? data : buf; + iov.iov_len = data ? size : sizeof(buf); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + return sendmsg(fd, &msg, MSG_NOSIGNAL); +} + +int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds, + void *data, size_t size) +{ + __do_free char *cmsgbuf = NULL; + int ret; + struct msghdr msg; + struct iovec iov; + struct cmsghdr *cmsg = NULL; + char buf[1] = {0}; + size_t cmsgbufsize = CMSG_SPACE(sizeof(struct ucred)) + + CMSG_SPACE(num_recvfds * sizeof(int)); + + memset(&msg, 0, sizeof(msg)); + memset(&iov, 0, sizeof(iov)); + + cmsgbuf = malloc(cmsgbufsize); + if (!cmsgbuf) { + errno = ENOMEM; + return -1; + } + + msg.msg_control = cmsgbuf; + msg.msg_controllen = cmsgbufsize; + + iov.iov_base = data ? data : buf; + iov.iov_len = data ? size : sizeof(buf); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + +again: + ret = recvmsg(fd, &msg, 0); + if (ret < 0) { + if (errno == EINTR) + goto again; + + goto out; + } + if (ret == 0) + goto out; + + // 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)); + break; + } + +out: + return ret; +} diff --git a/shared/util_linux_cgo.go b/shared/util_linux_cgo.go index acd8f9b218..d648a58d66 100644 --- a/shared/util_linux_cgo.go +++ b/shared/util_linux_cgo.go @@ -35,16 +35,6 @@ import ( #include <sys/types.h> #include <sys/un.h> -#include "../lxd/include/memory_utils.h" - -#ifndef AT_SYMLINK_FOLLOW -#define AT_SYMLINK_FOLLOW 0x400 -#endif - -#ifndef AT_EMPTY_PATH -#define AT_EMPTY_PATH 0x1000 -#endif - #define ABSTRACT_UNIX_SOCK_LEN sizeof(((struct sockaddr_un *)0)->sun_path) // This is an adaption from https://codereview.appspot.com/4589049, to be @@ -144,100 +134,6 @@ again: return ret; } - -int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds, - void *data, size_t size) -{ - __do_free char *cmsgbuf = NULL; - struct msghdr msg; - struct iovec iov; - struct cmsghdr *cmsg = NULL; - char buf[1] = {0}; - size_t cmsgbufsize = CMSG_SPACE(num_sendfds * sizeof(int)); - - memset(&msg, 0, sizeof(msg)); - memset(&iov, 0, sizeof(iov)); - - cmsgbuf = malloc(cmsgbufsize); - if (!cmsgbuf) - return -1; - - msg.msg_control = cmsgbuf; - msg.msg_controllen = cmsgbufsize; - - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(num_sendfds * sizeof(int)); - - msg.msg_controllen = cmsg->cmsg_len; - - memcpy(CMSG_DATA(cmsg), sendfds, num_sendfds * sizeof(int)); - - iov.iov_base = data ? data : buf; - iov.iov_len = data ? size : sizeof(buf); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - return sendmsg(fd, &msg, MSG_NOSIGNAL); -} - -int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds, - void *data, size_t size) -{ - __do_free char *cmsgbuf = NULL; - int ret; - struct msghdr msg; - struct iovec iov; - struct cmsghdr *cmsg = NULL; - char buf[1] = {0}; - size_t cmsgbufsize = CMSG_SPACE(sizeof(struct ucred)) + - CMSG_SPACE(num_recvfds * sizeof(int)); - - memset(&msg, 0, sizeof(msg)); - memset(&iov, 0, sizeof(iov)); - - cmsgbuf = malloc(cmsgbufsize); - if (!cmsgbuf) { - errno = ENOMEM; - return -1; - } - - msg.msg_control = cmsgbuf; - msg.msg_controllen = cmsgbufsize; - - iov.iov_base = data ? data : buf; - iov.iov_len = data ? size : sizeof(buf); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - -again: - ret = recvmsg(fd, &msg, 0); - if (ret < 0) { - if (errno == EINTR) - goto again; - - goto out; - } - if (ret == 0) - goto out; - - // 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)); - break; - } - -out: - return ret; -} */ // #cgo CFLAGS: -std=gnu11 -Wvla import "C" @@ -264,44 +160,6 @@ func GetPollRevents(fd int, timeout int, flags int) (int, int, error) { return int(ret), int(revents), err } -func AbstractUnixSendFd(sockFD int, sendFD int) error { - fd := C.int(sendFD) - sk_fd := C.int(sockFD) - ret := C.lxc_abstract_unix_send_fds(sk_fd, &fd, C.int(1), nil, C.size_t(0)) - if ret < 0 { - return fmt.Errorf("Failed to send file descriptor via abstract unix socket") - } - - return nil -} - -func AbstractUnixReceiveFd(sockFD int) (*os.File, error) { - fd := C.int(-1) - sk_fd := C.int(sockFD) - ret := C.lxc_abstract_unix_recv_fds(sk_fd, &fd, C.int(1), nil, C.size_t(0)) - if ret < 0 { - return nil, fmt.Errorf("Failed to receive file descriptor via abstract unix socket") - } - - file := os.NewFile(uintptr(fd), "") - return file, nil -} - -func AbstractUnixReceiveFdData(sockFD int, buf []byte) (int, error) { - fd := C.int(-1) - sk_fd := C.int(sockFD) - ret := C.lxc_abstract_unix_recv_fds(sk_fd, &fd, C.int(1), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) - if ret < 0 { - return int(-C.EBADF), fmt.Errorf("Failed to receive file descriptor via abstract unix socket") - } - - if ret == 0 { - return int(-C.EBADF), io.EOF - } - - return int(fd), nil -} - func OpenPty(uid, gid int64) (master *os.File, slave *os.File, err error) { fd_master := C.int(-1) fd_slave := C.int(-1)
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel