diff options
author | Michal Clapinski <mclapinski@google.com> | 2022-04-06 19:35:26 +0300 |
---|---|---|
committer | Andrei Vagin <avagin@gmail.com> | 2022-08-23 03:05:34 +0300 |
commit | 6e35c5922e4dc689ff6f6ee5eba8e1013a875e8a (patch) | |
tree | df706425744d14c6b352c6a3c23e860f4ca6168d | |
parent | ec49f42018dfb4beb6620bbaf6623e2c7cc4a5c7 (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.c | 25 |
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)) |