[CRIU] [PATCH RESEND] files: Fix crossing unused and service fds of shared fd tables

Kirill Tkhai ktkhai at virtuozzo.com
Wed Jun 28 13:45:42 MSK 2017


service_fd_id is id of a specific task, while other tasks
in shared fd table group may have bigger id numbers.
In this case given unused fd intersects with service fds
of such tasks. This leads to undefined behaviour. Fix that.

Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
 criu/files.c             |    4 ++--
 criu/include/servicefd.h |    4 +++-
 criu/util.c              |    9 +++++++--
 3 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/criu/files.c b/criu/files.c
index a36eb366e..1b0e02626 100644
--- a/criu/files.c
+++ b/criu/files.c
@@ -153,7 +153,7 @@ unsigned int find_unused_fd(struct pstree_item *task, int hint_fd)
 		goto out;
 	}
 
-	prev_fd = service_fd_min_fd() - 1;
+	prev_fd = service_fd_min_fd(task) - 1;
 	head = &rsti(task)->fds;
 
 	list_for_each_entry_reverse(fle, head, ps_list) {
@@ -877,7 +877,7 @@ int prepare_fd_pid(struct pstree_item *item)
 		if (ret <= 0)
 			break;
 
-		if (e->fd >= service_fd_min_fd()) {
+		if (e->fd >= service_fd_min_fd(item)) {
 			ret = -1;
 			pr_err("Too big FD number to restore %d\n", e->fd);
 			break;
diff --git a/criu/include/servicefd.h b/criu/include/servicefd.h
index b77922394..29e5b0bdb 100644
--- a/criu/include/servicefd.h
+++ b/criu/include/servicefd.h
@@ -28,6 +28,8 @@ enum sfd_type {
 	SERVICE_FD_MAX
 };
 
+struct pstree_item;
+
 extern int clone_service_fd(int id);
 extern int init_service_fd(void);
 extern int get_service_fd(enum sfd_type type);
@@ -36,6 +38,6 @@ extern int install_service_fd(enum sfd_type type, int fd);
 extern int close_service_fd(enum sfd_type type);
 extern bool is_service_fd(int fd, enum sfd_type type);
 extern bool is_any_service_fd(int fd);
-extern int service_fd_min_fd(void);
+extern int service_fd_min_fd(struct pstree_item *);
 
 #endif /* __CR_SERVICE_FD_H__ */
diff --git a/criu/util.c b/criu/util.c
index db484f2f8..6c55b13c1 100644
--- a/criu/util.c
+++ b/criu/util.c
@@ -417,9 +417,14 @@ static int __get_service_fd(enum sfd_type type, int service_fd_id)
 	return service_fd_rlim_cur - type - SERVICE_FD_MAX * service_fd_id;
 }
 
-int service_fd_min_fd(void)
+int service_fd_min_fd(struct pstree_item *item)
 {
-	return service_fd_rlim_cur - (SERVICE_FD_MAX - 1) - SERVICE_FD_MAX * service_fd_id;
+	struct fdt *fdt = rsti(item)->fdt;
+	int id = 0;
+
+	if (fdt)
+		id = fdt->nr - 1;
+	return service_fd_rlim_cur - (SERVICE_FD_MAX - 1) - SERVICE_FD_MAX * id;
 }
 
 static DECLARE_BITMAP(sfd_map, SERVICE_FD_MAX);



More information about the CRIU mailing list