Commit c75c92db authored by Cyrill Gorcunov's avatar Cyrill Gorcunov Committed by Pavel Emelyanov

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: 's avatarRuslan Kuprieiev <kupruser@gmail.com>
Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 5033068a
......@@ -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
......
......@@ -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
......
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/mount.h>
#include <errno.h>
#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;
}
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment