From c75c92db1d0a43f153aee229e0d6a69f3035f824 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Wed, 28 Aug 2013 23:57:46 +0400 Subject: [PATCH] pie: Move send_fds/recv_fds helpers into separate pie/util-fd.c We will need to reuse this code in criu library, where libc calls are present thus we will be compiling it in shared mode. Because internal syscalls library won't be needed we wrap them with __sys macro which would hide the details of invocation depending on CR_NOGLIBC preprocessor variable passed from command line. Original-patch-by: Ruslan Kuprieiev Signed-off-by: Cyrill Gorcunov Signed-off-by: Pavel Emelyanov --- Makefile | 1 + pie/Makefile | 1 + pie/util-fd.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++ pie/util.c | 139 -------------------------------------------- 4 files changed, 159 insertions(+), 139 deletions(-) create mode 100644 pie/util-fd.c diff --git a/Makefile b/Makefile index 352b74f1f..69a7f61d9 100644 --- a/Makefile +++ b/Makefile @@ -152,6 +152,7 @@ pie: arch/$(ARCH) built-in.o: $(VERSION_HEADER) pie $(Q) $(MAKE) $(build-crtools)=. $@ +PROGRAM-BUILTINS += pie/util-fd.o PROGRAM-BUILTINS += pie/util.o PROGRAM-BUILTINS += protobuf/built-in.o PROGRAM-BUILTINS += built-in.o diff --git a/pie/Makefile b/pie/Makefile index dc7130acb..c012b2526 100644 --- a/pie/Makefile +++ b/pie/Makefile @@ -3,6 +3,7 @@ targets += restorer obj-y += log-simple.o obj-y += util.o +obj-y += util-fd.o parasite-obj-y += parasite.o parasite-asm-e += $(ARCH_DIR)/parasite-head.o diff --git a/pie/util-fd.c b/pie/util-fd.c new file mode 100644 index 000000000..466a5f75a --- /dev/null +++ b/pie/util-fd.c @@ -0,0 +1,157 @@ +#include +#include +#include + +#include + +#include "compiler.h" +#include "asm/string.h" +#include "asm/types.h" + +#ifdef CR_NOGLIBC +# include "syscall.h" +# define __sys(foo) sys_##foo +#else +# define __sys(foo) foo +#endif + +#include "util-pie.h" + +static void scm_fdset_init_chunk(struct scm_fdset *fdset, int nr_fds) +{ + struct cmsghdr *cmsg; + + fdset->hdr.msg_controllen = CMSG_LEN(sizeof(int) * nr_fds); + + cmsg = CMSG_FIRSTHDR(&fdset->hdr); + cmsg->cmsg_len = fdset->hdr.msg_controllen; +} + +static int *scm_fdset_init(struct scm_fdset *fdset, struct sockaddr_un *saddr, + int saddr_len, bool with_flags) +{ + struct cmsghdr *cmsg; + + BUILD_BUG_ON(CR_SCM_MAX_FD > SCM_MAX_FD); + BUILD_BUG_ON(sizeof(fdset->msg_buf) < (CMSG_SPACE(sizeof(int) * CR_SCM_MAX_FD))); + + fdset->iov.iov_base = fdset->opts; + fdset->iov.iov_len = with_flags ? sizeof(fdset->opts) : 1; + + fdset->hdr.msg_iov = &fdset->iov; + fdset->hdr.msg_iovlen = 1; + fdset->hdr.msg_name = (struct sockaddr *)saddr; + fdset->hdr.msg_namelen = saddr_len; + + fdset->hdr.msg_control = &fdset->msg_buf; + fdset->hdr.msg_controllen = CMSG_LEN(sizeof(int) * CR_SCM_MAX_FD); + + cmsg = CMSG_FIRSTHDR(&fdset->hdr); + cmsg->cmsg_len = fdset->hdr.msg_controllen; + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + + return (int *)CMSG_DATA(cmsg); +} + +int send_fds(int sock, struct sockaddr_un *saddr, int len, + int *fds, int nr_fds, bool with_flags) +{ + struct scm_fdset fdset; + int *cmsg_data; + int i, min_fd, ret; + + cmsg_data = scm_fdset_init(&fdset, saddr, len, with_flags); + for (i = 0; i < nr_fds; i += min_fd) { + min_fd = min(CR_SCM_MAX_FD, nr_fds - i); + scm_fdset_init_chunk(&fdset, min_fd); + builtin_memcpy(cmsg_data, &fds[i], sizeof(int) * min_fd); + + if (with_flags) { + int j; + + for (j = 0; j < min_fd; j++) { + int flags, fd = fds[i + j]; + struct fd_opts *p = fdset.opts + j; + struct f_owner_ex owner_ex; + u32 v[2]; + + flags = __sys(fcntl)(fd, F_GETFD, 0); + if (flags < 0) + return -1; + + p->flags = (char)flags; + + if (__sys(fcntl)(fd, F_GETOWN_EX, (long)&owner_ex)) + return -1; + + /* + * Simple case -- nothing is changed. + */ + if (owner_ex.pid == 0) { + p->fown.pid = 0; + continue; + } + + if (__sys(fcntl)(fd, F_GETOWNER_UIDS, (long)&v)) + return -1; + + p->fown.uid = v[0]; + p->fown.euid = v[1]; + p->fown.pid_type = owner_ex.type; + p->fown.pid = owner_ex.pid; + } + } + + ret = __sys(sendmsg)(sock, &fdset.hdr, 0); + if (ret <= 0) + return ret ? : -1; + } + + return 0; +} + +int recv_fds(int sock, int *fds, int nr_fds, struct fd_opts *opts) +{ + struct scm_fdset fdset; + struct cmsghdr *cmsg; + int *cmsg_data; + int ret; + int i, min_fd; + + cmsg_data = scm_fdset_init(&fdset, NULL, 0, opts != NULL); + for (i = 0; i < nr_fds; i += min_fd) { + min_fd = min(CR_SCM_MAX_FD, nr_fds - i); + scm_fdset_init_chunk(&fdset, min_fd); + + ret = __sys(recvmsg)(sock, &fdset.hdr, 0); + if (ret <= 0) + return ret ? : -1; + + cmsg = CMSG_FIRSTHDR(&fdset.hdr); + if (!cmsg || cmsg->cmsg_type != SCM_RIGHTS) + return -EINVAL; + if (fdset.hdr.msg_flags & MSG_CTRUNC) + return -ENFILE; + + min_fd = (cmsg->cmsg_len - sizeof(struct cmsghdr)) / sizeof(int); + /* + * In case if kernel screwed the recepient, most probably + * the caller stack frame will be overwriten, just scream + * and exit. + * + * FIXME Need to sanitize util.h to be able to include it + * into files which do not have glibc and a couple of + * sys_write_ helpers. Meawhile opencoded BUG_ON here. + */ + if (unlikely(min_fd > CR_SCM_MAX_FD)) + *(volatile unsigned long *)NULL = 0xdead0000 + __LINE__; + if (unlikely(min_fd <= 0)) + return -1; + builtin_memcpy(&fds[i], cmsg_data, sizeof(int) * min_fd); + if (opts) + builtin_memcpy(opts + i, fdset.opts, sizeof(struct fd_opts) * min_fd); + } + + return 0; +} diff --git a/pie/util.c b/pie/util.c index fe3fe4f76..972f4da5e 100644 --- a/pie/util.c +++ b/pie/util.c @@ -11,145 +11,6 @@ #include "log.h" #include "util-pie.h" -static void scm_fdset_init_chunk(struct scm_fdset *fdset, int nr_fds) -{ - struct cmsghdr *cmsg; - - fdset->hdr.msg_controllen = CMSG_LEN(sizeof(int) * nr_fds); - - cmsg = CMSG_FIRSTHDR(&fdset->hdr); - cmsg->cmsg_len = fdset->hdr.msg_controllen; -} - -static int *scm_fdset_init(struct scm_fdset *fdset, struct sockaddr_un *saddr, - int saddr_len, bool with_flags) -{ - struct cmsghdr *cmsg; - - BUILD_BUG_ON(CR_SCM_MAX_FD > SCM_MAX_FD); - BUILD_BUG_ON(sizeof(fdset->msg_buf) < (CMSG_SPACE(sizeof(int) * CR_SCM_MAX_FD))); - - fdset->iov.iov_base = fdset->opts; - fdset->iov.iov_len = with_flags ? sizeof(fdset->opts) : 1; - - fdset->hdr.msg_iov = &fdset->iov; - fdset->hdr.msg_iovlen = 1; - fdset->hdr.msg_name = (struct sockaddr *)saddr; - fdset->hdr.msg_namelen = saddr_len; - - fdset->hdr.msg_control = &fdset->msg_buf; - fdset->hdr.msg_controllen = CMSG_LEN(sizeof(int) * CR_SCM_MAX_FD); - - cmsg = CMSG_FIRSTHDR(&fdset->hdr); - cmsg->cmsg_len = fdset->hdr.msg_controllen; - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - - return (int *)CMSG_DATA(cmsg); -} - -int send_fds(int sock, struct sockaddr_un *saddr, int len, - int *fds, int nr_fds, bool with_flags) -{ - struct scm_fdset fdset; - int *cmsg_data; - int i, min_fd, ret; - - cmsg_data = scm_fdset_init(&fdset, saddr, len, with_flags); - for (i = 0; i < nr_fds; i += min_fd) { - min_fd = min(CR_SCM_MAX_FD, nr_fds - i); - scm_fdset_init_chunk(&fdset, min_fd); - builtin_memcpy(cmsg_data, &fds[i], sizeof(int) * min_fd); - - if (with_flags) { - int j; - - for (j = 0; j < min_fd; j++) { - int flags, fd = fds[i + j]; - struct fd_opts *p = fdset.opts + j; - struct f_owner_ex owner_ex; - u32 v[2]; - - flags = sys_fcntl(fd, F_GETFD, 0); - if (flags < 0) - return -1; - - p->flags = (char)flags; - - if (sys_fcntl(fd, F_GETOWN_EX, (long)&owner_ex)) - return -1; - - /* - * Simple case -- nothing is changed. - */ - if (owner_ex.pid == 0) { - p->fown.pid = 0; - continue; - } - - if (sys_fcntl(fd, F_GETOWNER_UIDS, (long)&v)) - return -1; - - p->fown.uid = v[0]; - p->fown.euid = v[1]; - p->fown.pid_type = owner_ex.type; - p->fown.pid = owner_ex.pid; - } - } - - ret = sys_sendmsg(sock, &fdset.hdr, 0); - if (ret <= 0) - return ret ? : -1; - } - - return 0; -} - -int recv_fds(int sock, int *fds, int nr_fds, struct fd_opts *opts) -{ - struct scm_fdset fdset; - struct cmsghdr *cmsg; - int *cmsg_data; - int ret; - int i, min_fd; - - cmsg_data = scm_fdset_init(&fdset, NULL, 0, opts != NULL); - for (i = 0; i < nr_fds; i += min_fd) { - min_fd = min(CR_SCM_MAX_FD, nr_fds - i); - scm_fdset_init_chunk(&fdset, min_fd); - - ret = sys_recvmsg(sock, &fdset.hdr, 0); - if (ret <= 0) - return ret ? : -1; - - cmsg = CMSG_FIRSTHDR(&fdset.hdr); - if (!cmsg || cmsg->cmsg_type != SCM_RIGHTS) - return -EINVAL; - if (fdset.hdr.msg_flags & MSG_CTRUNC) - return -ENFILE; - - min_fd = (cmsg->cmsg_len - sizeof(struct cmsghdr)) / sizeof(int); - /* - * In case if kernel screwed the recepient, most probably - * the caller stack frame will be overwriten, just scream - * and exit. - * - * FIXME Need to sanitize util.h to be able to include it - * into files which do not have glibc and a couple of - * sys_write_ helpers. Meawhile opencoded BUG_ON here. - */ - if (unlikely(min_fd > CR_SCM_MAX_FD)) - *(volatile unsigned long *)NULL = 0xdead0000 + __LINE__; - if (unlikely(min_fd <= 0)) - return -1; - builtin_memcpy(&fds[i], cmsg_data, sizeof(int) * min_fd); - if (opts) - builtin_memcpy(opts + i, fdset.opts, sizeof(struct fd_opts) * min_fd); - } - - return 0; -} - int open_detach_mount(char *dir) { int fd;