[CRIU] [PATCH 09/22] compel: plugins, fds -- Make it the same as criu internal instance

Cyrill Gorcunov gorcunov at openvz.org
Wed Oct 19 12:21:24 PDT 2016


Here we make fds to provide same helpers as CRIU's does. Since
we gonna use it in parasite engine lets make it identical and
then we will simply drop off CRIU's one but use the fds plugin
instead.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 compel/include/compel/bug.h                        |   1 +
 .../include/uapi/compel/plugins/plugin-fds.h       |  66 +++++++++--
 compel/src/shared/fds.c                            | 121 ++++++++++++++-------
 3 files changed, 143 insertions(+), 45 deletions(-)
 create mode 120000 compel/include/compel/bug.h

diff --git a/compel/include/compel/bug.h b/compel/include/compel/bug.h
new file mode 120000
index 000000000000..20a9713d8484
--- /dev/null
+++ b/compel/include/compel/bug.h
@@ -0,0 +1 @@
+../../../criu/include/bug.h
\ No newline at end of file
diff --git a/compel/plugins/include/uapi/compel/plugins/plugin-fds.h b/compel/plugins/include/uapi/compel/plugins/plugin-fds.h
index ae83caa87ad1..2900d7a3a088 100644
--- a/compel/plugins/include/uapi/compel/plugins/plugin-fds.h
+++ b/compel/plugins/include/uapi/compel/plugins/plugin-fds.h
@@ -4,21 +4,73 @@
 #ifndef UAPI_COMPEL_PLUGIN_FDS_H__
 #define UAPI_COMPEL_PLUGIN_FDS_H__
 
-extern int fds_send(int *fds, int nr_fds);
-extern int fds_recv(int *fds, int nr_fds);
+#include <stdbool.h>
+#include <stdint.h>
 
-static inline int fds_send_one(int fd)
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#ifndef F_SETOWN_EX
+# define F_SETOWN_EX		15
+# define F_GETOWN_EX		16
+
+struct f_owner_ex {
+	int	type;
+	pid_t	pid;
+};
+
+#endif
+
+#ifndef F_GETOWNER_UIDS
+# define F_GETOWNER_UIDS	17
+#endif
+
+
+/*
+ * Because of kernel doing kmalloc for user data passed
+ * in SCM messages, and there is kernel's SCM_MAX_FD as a limit
+ * for descriptors passed at once we're trying to reduce
+ * the pressue on kernel memory manager and use predefined
+ * known to work well size of the message buffer.
+ */
+#define COMPEL_SCM_MSG_SIZE		(1024)
+#define COMPEL_SCM_MAX_FD		(252)
+
+struct fd_opts {
+	char flags;
+	struct {
+		uint32_t uid;
+		uint32_t euid;
+		uint32_t signum;
+		uint32_t pid_type;
+		uint32_t pid;
+	} fown;
+};
+
+struct scm_fdset {
+	struct msghdr	hdr;
+	struct iovec	iov;
+	char		msg_buf[COMPEL_SCM_MSG_SIZE];
+	struct fd_opts	opts[COMPEL_SCM_MAX_FD];
+};
+
+extern int send_fds(int sock, struct sockaddr_un *saddr, int saddr_len,
+		    int *fds, int nr_fds, bool with_flags);
+extern int recv_fds(int sock, int *fds, int nr_fds, struct fd_opts *opts);
+
+static inline int send_fd(int sock, struct sockaddr_un *saddr, int saddr_len, int fd)
 {
-	return fds_send(&fd, 1);
+	return send_fds(sock, saddr, saddr_len, &fd, 1, false);
 }
 
-static inline int fds_recv_one(void)
+static inline int recv_fd(int sock)
 {
 	int fd, ret;
 
-	ret = fds_recv(&fd, 1);
+	ret = recv_fds(sock, &fd, 1, NULL);
 	if (ret)
-		fd = -1;
+		return -1;
 
 	return fd;
 }
diff --git a/compel/src/shared/fds.c b/compel/src/shared/fds.c
index 9bf49cbdd37f..8964b1ff09b0 100644
--- a/compel/src/shared/fds.c
+++ b/compel/src/shared/fds.c
@@ -1,22 +1,15 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
 #include <sys/socket.h>
 #include <sys/un.h>
 
-/*
- * Because of kernel doing kmalloc for user data passed
- * in SCM messages, and there is kernel's SCM_MAX_FD as a limit
- * for descriptors passed at once we're trying to reduce
- * the pressue on kernel memory manager and use predefined
- * known to work well size of the message buffer.
- */
-#define CR_SCM_MSG_SIZE		(1024)
-#define CR_SCM_MAX_FD		(252)
-
-struct scm_fdset {
-	struct msghdr	hdr;
-	struct iovec	iov;
-	char		msg_buf[CR_SCM_MSG_SIZE];
-	char		f;
-};
+#include "compiler.h"
+#include "bug.h"
+
+#include "uapi/compel/plugins/plugin-fds.h"
 
 static void scm_fdset_init_chunk(struct scm_fdset *fdset, int nr_fds)
 {
@@ -28,22 +21,23 @@ static void scm_fdset_init_chunk(struct scm_fdset *fdset, int nr_fds)
 	cmsg->cmsg_len	= fdset->hdr.msg_controllen;
 }
 
-static int *scm_fdset_init(struct scm_fdset *fdset)
+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(sizeof(fdset->msg_buf) < (CMSG_SPACE(sizeof(int) * CR_SCM_MAX_FD)));
+	BUILD_BUG_ON(sizeof(fdset->msg_buf) < (CMSG_SPACE(sizeof(int) * COMPEL_SCM_MAX_FD)));
 
-	fdset->iov.iov_base		= &fdset->f;
-	fdset->iov.iov_len		= 1;
+	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		= NULL;
-	fdset->hdr.msg_namelen		= 0;
+	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);
+	fdset->hdr.msg_controllen	= CMSG_LEN(sizeof(int) * COMPEL_SCM_MAX_FD);
 
 	cmsg				= CMSG_FIRSTHDR(&fdset->hdr);
 	cmsg->cmsg_len			= fdset->hdr.msg_controllen;
@@ -53,19 +47,64 @@ static int *scm_fdset_init(struct scm_fdset *fdset)
 	return (int *)CMSG_DATA(cmsg);
 }
 
-int fds_send_via(int sock, int *fds, int nr_fds)
+int send_fds(int sock, struct sockaddr_un *saddr, int len,
+	     int *fds, int nr_fds, bool with_flags)
 {
 	struct scm_fdset fdset;
-	int i, min_fd, ret;
 	int *cmsg_data;
+	int i, min_fd, ret;
 
-	cmsg_data = scm_fdset_init(&fdset);
-
+	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);
+		min_fd = min(COMPEL_SCM_MAX_FD, nr_fds - i);
 		scm_fdset_init_chunk(&fdset, min_fd);
 		__std(memcpy(cmsg_data, &fds[i], sizeof(int) * min_fd));
-		ret = __sys(sendmsg(sock, &fdset.hdr, 0));
+
+		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;
+				uint32_t v[2];
+
+				flags = __sys(fcntl)(fd, F_GETFD, 0);
+				if (flags < 0) {
+					pr_err("fcntl(%d, F_GETFD) -> %d\n", fd, flags);
+					return -1;
+				}
+
+				p->flags = (char)flags;
+
+				ret = __sys(fcntl)(fd, F_GETOWN_EX, (long)&owner_ex);
+				if (ret) {
+					pr_err("fcntl(%d, F_GETOWN_EX) -> %d\n", fd, ret);
+					return -1;
+				}
+
+				/*
+				 * Simple case -- nothing is changed.
+				 */
+				if (owner_ex.pid == 0) {
+					p->fown.pid = 0;
+					continue;
+				}
+
+				ret = __sys(fcntl)(fd, F_GETOWNER_UIDS, (long)&v);
+				if (ret) {
+					pr_err("fcntl(%d, F_GETOWNER_UIDS) -> %d\n", fd, ret);
+					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;
 	}
@@ -73,7 +112,7 @@ int fds_send_via(int sock, int *fds, int nr_fds)
 	return 0;
 }
 
-int fds_recv_via(int sock, int *fds, int nr_fds)
+int recv_fds(int sock, int *fds, int nr_fds, struct fd_opts *opts)
 {
 	struct scm_fdset fdset;
 	struct cmsghdr *cmsg;
@@ -81,32 +120,38 @@ int fds_recv_via(int sock, int *fds, int nr_fds)
 	int ret;
 	int i, min_fd;
 
-	cmsg_data = scm_fdset_init(&fdset);
+	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);
+		min_fd = min(COMPEL_SCM_MAX_FD, nr_fds - i);
 		scm_fdset_init_chunk(&fdset, min_fd);
 
-		ret = __sys(recvmsg(sock, &fdset.hdr, 0));
+		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 -1;
+			return -EINVAL;
 		if (fdset.hdr.msg_flags & MSG_CTRUNC)
-			return -2;
+			return -ENFILE;
 
 		min_fd = (cmsg->cmsg_len - sizeof(struct cmsghdr)) / sizeof(int);
 		/*
-		 * In case if kernel screwed the recepient, most probably
+		 * In case if kernel screwed the recipient, 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__;
+		BUG_ON(min_fd > COMPEL_SCM_MAX_FD);
+
 		if (unlikely(min_fd <= 0))
 			return -1;
 		__std(memcpy(&fds[i], cmsg_data, sizeof(int) * min_fd));
+		if (opts)
+			__std(memcpy(opts + i, fdset.opts, sizeof(struct fd_opts) * min_fd));
 	}
 
 	return 0;
-- 
2.7.4



More information about the CRIU mailing list