From f326061d985c32bb0e298b97d0804e897be9c6cf Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Fri, 12 Jan 2018 11:55:27 +0300 Subject: [PATCH] sfds: Protect service fds reuse This patch introduces sfds_protected, which allows to mask areas, where modifications of sfds are prohibited. That guarantees, that populated sfds won't be reused. v4: New v5: Add comment and print sfd type before BUG(). Signed-off-by: Kirill Tkhai Signed-off-by: Andrei Vagin --- criu/include/servicefd.h | 1 + criu/util.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/criu/include/servicefd.h b/criu/include/servicefd.h index 6266b5324..812396310 100644 --- a/criu/include/servicefd.h +++ b/criu/include/servicefd.h @@ -27,6 +27,7 @@ enum sfd_type { }; struct pstree_item; +extern bool sfds_protected; extern void set_proc_self_fd(int fd); extern int clone_service_fd(int id); diff --git a/criu/util.c b/criu/util.c index dea0a307d..cf2e04c9b 100644 --- a/criu/util.c +++ b/criu/util.c @@ -473,12 +473,27 @@ int service_fd_min_fd(struct pstree_item *item) } static DECLARE_BITMAP(sfd_map, SERVICE_FD_MAX); +/* + * Variable for marking areas of code, where service fds modifications + * are prohibited. It's used to safe them from reusing their numbers + * by ordinary files. See install_service_fd() and close_service_fd(). + */ +bool sfds_protected = false; + +static void sfds_protection_bug(enum sfd_type type) +{ + pr_err("Service fd %u is being modified in protected context\n", type); + print_stack_trace(current ? vpid(current) : 0); + BUG(); +} int install_service_fd(enum sfd_type type, int fd) { int sfd = __get_service_fd(type, service_fd_id); BUG_ON((int)type <= SERVICE_FD_MIN || (int)type >= SERVICE_FD_MAX); + if (sfds_protected && !test_bit(type, sfd_map)) + sfds_protection_bug(type); if (dup3(fd, sfd, O_CLOEXEC) != sfd) { pr_perror("Dup %d -> %d failed", fd, sfd); @@ -508,6 +523,9 @@ int close_service_fd(enum sfd_type type) { int fd; + if (sfds_protected) + sfds_protection_bug(type); + fd = get_service_fd(type); if (fd < 0) return 0;