[v2,21/30] files: Add new master to file_desc if owners of existing fles have no permissions

Submitted by Kirill Tkhai on June 7, 2017, 11:29 a.m.

Details

Message ID 149683495737.4663.2975081317054178099.stgit@localhost.localdomain
State Accepted
Series "Support sockets leaked to child user_ns task"
Headers show

Commit Message

Kirill Tkhai June 7, 2017, 11:29 a.m.
Iterate over fake_master_head and add a fake fake fle of root_item,
which becomes new master and have permissions to restore file_desc.

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 criu/cr-restore.c    |    5 +++++
 criu/files.c         |   31 +++++++++++++++++++++++++++++++
 criu/include/files.h |    1 +
 3 files changed, 37 insertions(+)

Patch hide | download patch | download mbox

diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index 220450b43..6c6484e67 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -348,6 +348,11 @@  static int root_prepare_shared(void)
 	if (ret)
 		goto err;
 
+	/* This func may add new files, so it must be called before post prepare */
+	ret = add_fake_fds_masters();
+	if (ret)
+		goto err;
+
 	ret = run_post_prepare();
 	if (ret)
 		goto err;
diff --git a/criu/files.c b/criu/files.c
index d0a7a0dcf..1ddfcbd99 100644
--- a/criu/files.c
+++ b/criu/files.c
@@ -1747,3 +1747,34 @@  int open_transport_socket(void)
 out:
 	return ret;
 }
+
+int add_fake_fds_masters(void)
+{
+	struct fdinfo_list_entry *fle;
+	struct file_desc *fdesc, *tmp;
+	FdinfoEntry *fe;
+	int fd;
+
+	list_for_each_entry_safe(fdesc, tmp, &fake_master_head, fake_master_list) {
+		fle = list_first_entry(&fdesc->fd_info_head,
+				       struct fdinfo_list_entry, desc_list);
+		/*
+		 * All masters are created in root_item for now.
+		 * Distribute them over pstree if someone reports,
+		 * their number is too big, or you want support
+		 * file->user_ns.
+		 */
+		fd = find_unused_fd(root_item, -1);
+		fe = dup_fdinfo(fle->fe, fd, fle->fe->flags);
+		if (!fe)
+			goto err;
+
+		if (collect_fd(vpid(root_item), fe, rsti(root_item), true))
+			goto err;
+	}
+	BUG_ON(!list_empty(&fake_master_head));
+	return 0;
+err:
+	pr_err("Can't prepare fds masters\n");
+	return -1;
+}
diff --git a/criu/include/files.h b/criu/include/files.h
index 812ef8947..6f651827b 100644
--- a/criu/include/files.h
+++ b/criu/include/files.h
@@ -151,6 +151,7 @@  extern int rst_file_params(int fd, FownEntry *fown, int flags);
 
 extern void show_saved_files(void);
 
+extern int add_fake_fds_masters(void);
 extern int prepare_fds(struct pstree_item *me);
 extern int prepare_fd_pid(struct pstree_item *me);
 extern int prepare_ctl_tty(int pid, struct rst_info *rst_info, u32 ctl_tty_id);