Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/checkpoint-restore/criu.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Clapinski <mclapinski@google.com>2022-04-06 19:35:26 +0300
committerAndrei Vagin <avagin@gmail.com>2022-08-23 03:05:34 +0300
commit6e35c5922e4dc689ff6f6ee5eba8e1013a875e8a (patch)
treedf706425744d14c6b352c6a3c23e860f4ca6168d
parentec49f42018dfb4beb6620bbaf6623e2c7cc4a5c7 (diff)
criu: fail migration if data was sent to an in-flight socket
Before this change, CRIU would just lose that data upon migration. So it's better to fail migration in this case. To reproduce the bug one can: 1. Create an AF_UNIX socket and call listen on it. 2. Create a second AF_UNIX socket and call connect to the first one. 3. Send the data to the second socket. 4. Migrate. 5. Call accept on the first socket and then read. There would be no data available. It should be even possible to close the second socket before migration. This would cause accept to hang because CRIU totally misses a closed in-flight socket. Signed-off-by: Michal Clapinski <mclapinski@google.com>
-rw-r--r--criu/sk-unix.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/criu/sk-unix.c b/criu/sk-unix.c
index 47e1b2962..873360bfa 100644
--- a/criu/sk-unix.c
+++ b/criu/sk-unix.c
@@ -497,9 +497,34 @@ static int dump_one_unix_fd(int lfd, uint32_t id, const struct fd_parms *p)
goto err;
}
+ if (sk->wqlen != 0) {
+ /*
+ * There's no known way to get data out of the write
+ * queue of an icon socket. The only good solution for
+ * now is to fail the migration.
+ */
+ pr_err("Non-empty write queue on an in-flight socket %#x\n", ue->ino);
+ goto err;
+ }
+
ue->peer = e->sk_desc->sd.ino;
pr_debug("\t\tFixed inflight socket %u peer %u)\n", ue->ino, ue->peer);
+ } else if (ue->state == TCP_LISTEN) {
+ int i;
+
+ for (i = 0; i < sk->nr_icons; i++)
+ if (sk->icons[i] == 0) {
+ /*
+ * Inode of an icon socket equal to 0 means
+ * it's already been closed. That means we have
+ * no simple way to check if it sent any data.
+ * The only good solution for now is to fail
+ * the migration.
+ */
+ pr_err("Found a closed in-flight socket to %#x\n", ue->ino);
+ goto err;
+ }
}
dump:
if (dump_socket_opts(lfd, skopts))