[CRIU]
[PATCH 2/3] files, pipes: Add dump and restore of file owners
Cyrill Gorcunov
gorcunov at openvz.org
Fri Mar 23 14:09:19 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 | 44 +++++++++++++++++++++++++++++++++++++++++---
cr-restore.c | 6 ++++++
cr-show.c | 9 +++++++++
files.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
include/files.h | 1 +
include/image.h | 10 ++++++++++
6 files changed, 113 insertions(+), 3 deletions(-)
diff --git a/cr-dump.c b/cr-dump.c
index b5c9a3c..e76938d 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;
u64 id;
pid_t pid;
@@ -158,6 +159,7 @@ static int dump_one_reg_file(const struct fd_parms *p, int lfd,
e.pos = p->pos;
e.addr = p->fd_name;
e.id = FD_ID_INVALID;
+ e.fown = p->fown;
if (likely(!fd_is_special(&e))) {
struct fd_id_entry *entry;
@@ -300,6 +302,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;
@@ -317,8 +320,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);
@@ -327,6 +335,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,
@@ -337,8 +374,6 @@ static int dump_one_fd(pid_t pid, int fd, int lfd,
struct fd_parms p;
int err;
- fill_fd_params(pid, fd, lfd, &p);
-
err = open_proc_nocheck(pid, "fd/%d", fd);
if (err < 0) {
err = try_dump_socket(pid, fd, cr_fdset, sk_queue);
@@ -368,6 +403,9 @@ static int dump_one_fd(pid_t pid, int fd, int lfd,
goto err;
}
+ if (fill_fd_params(pid, fd, lfd, &p))
+ return -1;
+
if (S_ISREG(fd_stat.st_mode) ||
S_ISDIR(fd_stat.st_mode) ||
(S_ISCHR(fd_stat.st_mode) && major(fd_stat.st_rdev) == MEM_MAJOR)) {
diff --git a/cr-restore.c b/cr-restore.c
index b750b9e..30dcdf7 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -759,6 +759,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;
@@ -815,6 +818,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 7eafdbd..1fc2adb 100644
--- a/cr-show.c
+++ b/cr-show.c
@@ -82,6 +82,11 @@ static void show_files(int fd_files)
}
pr_msg("\n");
+
+ 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);
}
out:
@@ -103,6 +108,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 773193f..86e5a3e 100644
--- a/files.c
+++ b/files.c
@@ -127,6 +127,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;
@@ -178,6 +221,9 @@ static int open_fe_fd(struct fdinfo_entry *fe, int fd)
lseek(tmp, fe->pos, SEEK_SET);
+ if (restore_fown(getpid(), tmp, &fe->fown))
+ return -1;
+
return tmp;
}
diff --git a/include/files.h b/include/files.h
index eb6a219..8496fc2 100644
--- a/include/files.h
+++ b/include/files.h
@@ -41,5 +41,6 @@ extern int prepare_fds(int pid);
extern int prepare_fd_pid(int pid);
extern int prepare_shared_fdinfo(void);
extern int try_fixup_file_map(int pid, struct vma_entry *vma_entry, int fd);
+extern int restore_fown(pid_t pid, int fd, fown_t *fown);
#endif /* FILES_H_ */
diff --git a/include/image.h b/include/image.h
index cdc4af8..78c2460 100644
--- a/include/image.h
+++ b/include/image.h
@@ -39,6 +39,14 @@
#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 fdinfo_entry {
u8 type;
u8 len;
@@ -46,6 +54,7 @@ struct fdinfo_entry {
u32 pos;
u64 addr;
u64 id;
+ fown_t fown;
u8 name[0];
} __packed;
@@ -65,6 +74,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