[CRIU] [PATCH 09/12] files, pipes: Add dump and restore of file owners

Cyrill Gorcunov gorcunov at openvz.org
Sun Mar 25 17:33:55 EDT 2012


While fcntl provides almost all data file
owner handler might have, a missing piece reminds
uid and euid of owner.

For this sake a kernel patch is needed, which means
the crtools will refuse to work on old kernels (before
crtools-v3.3).

This patch brings dump/show/restore procedure of
file owners. Noticable detail of the patch -- the
image format is extended, again ;)

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 cr-dump.c       |   39 ++++++++++++++++++++++++++++++++++++++-
 cr-restore.c    |    6 ++++++
 cr-show.c       |    9 +++++++++
 files.c         |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 include/files.h |    1 +
 include/image.h |   11 +++++++++++
 6 files changed, 111 insertions(+), 1 deletions(-)

diff --git a/cr-dump.c b/cr-dump.c
index 0374255..78e4c45 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -124,6 +124,7 @@ struct fd_parms {
 	unsigned long	pos;
 	unsigned int	flags;
 	unsigned int	type;
+	fown_t		fown;
 
 	u32		id;
 	pid_t		pid;
@@ -152,6 +153,7 @@ static int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p)
 	rfe.flags = p->flags;
 	rfe.pos = p->pos;
 	rfe.id = id;
+	rfe.fown = p->fown;
 
 	if (write_img(reg_files_fd, &rfe))
 		return -1;
@@ -304,6 +306,7 @@ static int dump_one_pipe(const struct fd_parms *p, unsigned int id, int lfd,
 	e.fd		= p->fd_name;
 	e.pipeid	= id;
 	e.flags		= p->flags;
+	e.fown		= p->fown;
 
 	if (p->flags & O_WRONLY) {
 		e.bytes = 0;
@@ -321,8 +324,13 @@ err:
 	return ret;
 }
 
-static void fill_fd_params(pid_t pid, int fd, int lfd, struct fd_parms *p)
+static int fill_fd_params(pid_t pid, int fd, int lfd, struct fd_parms *p)
 {
+	struct f_owner_ex owner_ex;
+	u32 v[2];
+
+	memzero(p, sizeof(*p));
+
 	p->fd_name	= fd;
 	p->pos		= lseek(lfd, 0, SEEK_CUR);
 	p->flags	= fcntl(lfd, F_GETFL);
@@ -331,6 +339,35 @@ static void fill_fd_params(pid_t pid, int fd, int lfd, struct fd_parms *p)
 
 	pr_info("%d fdinfo %d: pos: %16lx flags: %16o\n",
 		pid, fd, p->pos, p->flags);
+
+	p->fown.signum = fcntl(lfd, F_GETSIG, 0);
+	if (p->fown.signum < 0) {
+		pr_perror("Can't get owner signum on %d/%d\n", pid, fd);
+		return -1;
+	}
+
+	if (fcntl(lfd, F_GETOWN_EX, (long)&owner_ex)) {
+		pr_perror("Can't get owners on %d/%d\n", pid, fd);
+		return -1;
+	}
+
+	/*
+	 * Simple case -- nothing is changed.
+	 */
+	if (owner_ex.pid == 0)
+		return 0;
+
+	if (fcntl(lfd, F_GETOWNER_UIDS, (long)&v)) {
+		pr_perror("Can't get owner uids on %d/%d\n", pid, fd);
+		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;
+
+	return 0;
 }
 
 static int dump_one_fd(pid_t pid, int fd, int lfd,
diff --git a/cr-restore.c b/cr-restore.c
index 3c29fcc..b34ba5c 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -704,6 +704,9 @@ static int create_pipe(int pid, struct pipe_entry *e, struct pipe_info *pi, int
 	if (tmp < 0)
 		return -1;
 
+	if (restore_fown(pid, e->fd, &e->fown))
+		return -1;
+
 	pr_info("\t%d: All is ok - reopening pipe for %d\n", pid, e->fd);
 
 	return 0;
@@ -760,6 +763,9 @@ out:
 	if (tmp < 0)
 		return -1;
 
+	if (restore_fown(pid, e->fd, &e->fown))
+		return -1;
+
 	return 0;
 
 }
diff --git a/cr-show.c b/cr-show.c
index 8b83599..d5054c8 100644
--- a/cr-show.c
+++ b/cr-show.c
@@ -119,6 +119,11 @@ static void show_reg_files(int fd_reg_files)
 		}
 
 		pr_msg("\n");
+
+		pr_msg("\touid: %4x oeuid: %4x osignum: %4x "
+		       "opid_type: %2x opid: %8x\n",
+		       rfe.fown.uid, rfe.fown.euid, rfe.fown.signum,
+		       rfe.fown.pid_type, rfe.fown.pid);
 	}
 
 out:
@@ -140,6 +145,10 @@ static void show_pipes(int fd_pipes)
 			goto out;
 		pr_msg("fd: %8x pipeid: %8x flags: %8x bytes: %8x\n",
 		       e.fd, e.pipeid, e.flags, e.bytes);
+		pr_msg("\touid: %4x oeuid: %4x osignum: %4x "
+		       "opid_type: %2x opid: %8x\n",
+		       e.fown.uid, e.fown.euid, e.fown.signum,
+		       e.fown.pid_type, e.fown.pid);
 		if (e.bytes)
 			lseek(fd_pipes, e.bytes, SEEK_CUR);
 	}
diff --git a/files.c b/files.c
index 7055771..c7ea23e 100644
--- a/files.c
+++ b/files.c
@@ -115,6 +115,49 @@ static int collect_fd(int pid, struct fdinfo_entry *e)
 	return 0;
 }
 
+int restore_fown(pid_t pid, int fd, fown_t *fown)
+{
+	struct f_owner_ex owner;
+	uid_t uids[3];
+
+	if (fown->signum) {
+		if (fcntl(fd, F_SETSIG, fown->signum)) {
+			pr_perror("%d: Can't set signal", pid);
+			return -1;
+		}
+	}
+
+	/* May be untouched */
+	if (!fown->pid)
+		return 0;
+
+	if (getresuid(&uids[0], &uids[1], &uids[2])) {
+		pr_perror("%d: Can't get UIDs", pid);
+		return -1;
+	}
+
+	if (setresuid(fown->uid, fown->euid, uids[2])) {
+		pr_perror("%d: Can't set UIDs", pid);
+		return -1;
+	}
+
+	owner.type	= fown->pid_type;
+	owner.pid	= fown->pid;
+
+	if (fcntl(fd, F_SETOWN_EX, &owner)) {
+		pr_perror("%d: Can't setup %d file owner pid",
+			  pid, fd);
+		return -1;
+	}
+
+	if (setresuid(uids[0], uids[1], uids[2])) {
+		pr_perror("%d: Can't set UIDs", pid);
+		return -1;
+	}
+
+	return 0;
+}
+
 int prepare_fd_pid(int pid)
 {
 	int fdinfo_fd, ret = 0;
@@ -193,6 +236,9 @@ static int open_fe_fd(struct fdinfo_entry *fe, int fd)
 
 	lseek(tmp, rfe.pos, SEEK_SET);
 
+	if (restore_fown(getpid(), tmp, &rfe.fown))
+		return -1;
+
 	return tmp;
 }
 
diff --git a/include/files.h b/include/files.h
index e040380..563f22a 100644
--- a/include/files.h
+++ b/include/files.h
@@ -41,6 +41,7 @@ extern int prepare_fds(int pid);
 extern int prepare_fd_pid(int pid);
 extern int prepare_shared_fdinfo(void);
 extern int get_filemap_fd(int pid, struct vma_entry *vma_entry);
+extern int restore_fown(pid_t pid, int fd, fown_t *fown);
 
 extern int self_exe_fd;
 
diff --git a/include/image.h b/include/image.h
index 3316078..75cd5eb 100644
--- a/include/image.h
+++ b/include/image.h
@@ -45,11 +45,20 @@ enum fd_types {
 #define PAGE_RSS	1
 #define PAGE_ANON	2
 
+typedef struct {
+	u32	uid;
+	u32	euid;
+	u32	signum;
+	u32	pid_type;
+	u32	pid;
+} __packed fown_t;
+
 struct reg_file_entry {
 	u32	id;
 	u16	flags;
 	u16	len;
 	u64	pos;
+	fown_t	fown;
 	u8	name[0];
 } __packed;
 
@@ -57,6 +66,7 @@ struct fdinfo_entry {
 	u64	addr;
 	u8	type;
 	u32	id;
+	struct reg_file_entry rfe;
 } __packed;
 
 #define fd_is_special(fe)		\
@@ -75,6 +85,7 @@ struct pipe_entry {
 	u32	pipeid;
 	u32	flags;
 	u32	bytes;
+	fown_t	fown;
 	u8	data[0];
 } __packed;
 
-- 
1.7.7.6



More information about the CRIU mailing list