[7/9] epoll: Use real file transferred for target fds check

Submitted by Cyrill Gorcunov on June 20, 2018, 12:01 p.m.

Details

Message ID 20180620120143.8604-8-gorcunov@gmail.com
State New
Series "epoll: Add support for duped targets"
Headers show

Commit Message

Cyrill Gorcunov June 20, 2018, 12:01 p.m.
When we are checkpoiting epoll targets we assuming that this target
file is belonging to the process we are on. This is of course not
true. Without kernel support the only thing we can do is compare
fd numbers with ones present in epoll fdinfo. When fd numer match
we assume that it indeed the file which has been added into epoll.

This won't cover the case when file has been moved to some other
number and new one is reopened instead of it. Such scenario will
trigger false positive and we can't do anything about.

In next patches with kernel help we will make precise check for
files identity.

Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
---
 criu/eventpoll.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 46 insertions(+), 5 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/eventpoll.c b/criu/eventpoll.c
index f0265ced2ceb..9ab1249dbc31 100644
--- a/criu/eventpoll.c
+++ b/criu/eventpoll.c
@@ -12,6 +12,7 @@ 
 #include <sys/ioctl.h>
 #include <sys/epoll.h>
 
+#include "types.h"
 #include "crtools.h"
 #include "common/compiler.h"
 #include "imgset.h"
@@ -22,6 +23,7 @@ 
 #include "util.h"
 #include "log.h"
 #include "pstree.h"
+#include "parasite.h"
 
 #include "protobuf.h"
 #include "images/eventpoll.pb-c.h"
@@ -55,7 +57,9 @@  static int dump_one_eventpoll(int lfd, u32 id, const struct fd_parms *p)
 {
 	FileEntry fe = FILE_ENTRY__INIT;
 	EventpollFileEntry e = EVENTPOLL_FILE_ENTRY__INIT;
-	int i, ret = -1;
+	EventpollTfdEntry **tfd_cpy = NULL;
+	size_t i, j, k, n_tfd_cpy;
+	int ret = -1;
 
 	e.id = id;
 	e.flags = p->flags;
@@ -68,14 +72,51 @@  static int dump_one_eventpoll(int lfd, u32 id, const struct fd_parms *p)
 	fe.id = e.id;
 	fe.epfd = &e;
 
+	n_tfd_cpy = e.n_tfd;
+	tfd_cpy = xmemdup(e.tfd, sizeof(e.tfd[0]) * e.n_tfd);
+	if (!tfd_cpy)
+		goto out;
+
+	/*
+	 * Handling dup'ed or transferred target
+	 * files is tricky: we need to use kcmp
+	 * to find out where file came from. Until
+	 * it's implemented lets use simplier approach
+	 * just check the targets are blonging to the
+	 * pid's file set.
+	 */
+	for (i = j = 0; p->dfds && i < e.n_tfd; i++) {
+		for (k = 0; k < p->dfds->nr_fds; k++) {
+			if (p->dfds->fds[k] == e.tfd[i]->tfd)
+				break;
+		}
+
+		if (k >= p->dfds->nr_fds) {
+			pr_warn("Escaped/closed fd descriptor %d on pid %d, ignoring\n",
+				e.tfd[i]->tfd, p->pid);
+			continue;
+		}
+
+		e.tfd[j++] = e.tfd[i];
+	}
+
+	e.n_tfd = j; /* New amount of "semi-valid" fds */
+
+
 	pr_info_eventpoll("Dumping ", &e);
 	ret = pb_write_one(img_from_set(glob_imgset, CR_FD_FILES), &fe, PB_FILE);
-out:
-	for (i = 0; i < e.n_tfd; i++) {
-		if (!ret)
+	if (!ret) {
+		for (i = 0; i < e.n_tfd; i++)
 			pr_info_eventpoll_tfd("Dumping: ", e.tfd[i]);
-		eventpoll_tfd_entry__free_unpacked(e.tfd[i], NULL);
 	}
+
+	/* Restore former values to free resources */
+	memcpy(e.tfd, tfd_cpy, sizeof(e.tfd[0]) * n_tfd_cpy);
+	e.n_tfd = n_tfd_cpy;
+out:
+	for (i = 0; i < e.n_tfd; i++)
+		eventpoll_tfd_entry__free_unpacked(e.tfd[i], NULL);
+	xfree(tfd_cpy);
 	xfree(e.tfd);
 
 	return ret;