Commit 3122529f authored by Tycho Andersen's avatar Tycho Andersen Committed by Pavel Emelyanov

unix: wait for listen() as well as bind()

We need to wait for listen() as well as bind() for internal unix sockets, or we
can race like this:

(00.135950)      1: Opening standalone socket (id 0xb ino 0x9422f peer 0)
(00.135974)    353: Error (sk-unix.c:701): Can't connect 0x947c4 socket: Connection refused
(00.136390)      1: Error (cr-restore.c:1228): 353 exited, status=1
(00.136407)      1:  Putting 0x9422f into listen state

(where 0x9422f is the peer for 0x947c4)

This race was pretty rare for me, but I've run 1000 tests and it didn't
happen so hopefully this patch fixes it :)
Signed-off-by: 's avatarTycho Andersen <tycho.andersen@canonical.com>
Acked-by: 's avatarAndrew Vagin <avagin@odin.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 445dbd9d
......@@ -631,7 +631,13 @@ struct unix_sk_info {
unsigned flags;
struct unix_sk_info *peer;
struct file_desc d;
futex_t bound;
/*
* Futex to signal when the socket is prepared. In particular, we
* signal after bind()ing the socket if it is not in TCP_LISTEN, or
* after listen() if the socket is in TCP_LISTEN.
*/
futex_t prepared;
};
#define USK_PAIR_MASTER 0x1
......@@ -689,7 +695,7 @@ static int post_open_unix_sk(struct file_desc *d, int fd)
/* Skip external sockets */
if (!list_empty(&peer->d.fd_info_head))
futex_wait_while(&peer->bound, 0);
futex_wait_while(&peer->prepared, 0);
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
......@@ -764,7 +770,8 @@ static int bind_unix_sk(int sk, struct unix_sk_info *ui)
}
}
futex_set_and_wake(&ui->bound, 1);
if (ui->ue->state != TCP_LISTEN)
futex_set_and_wake(&ui->prepared, 1);
done:
return 0;
}
......@@ -957,6 +964,7 @@ static int open_unixsk_standalone(struct unix_sk_info *ui)
pr_perror("Can't make usk listen");
return -1;
}
futex_set_and_wake(&ui->prepared, 1);
}
out:
if (rst_file_params(sk, ui->ue->fown, ui->ue->flags))
......@@ -1012,7 +1020,7 @@ static int collect_one_unixsk(void *o, ProtobufCMessage *base)
} else
ui->name = NULL;
futex_init(&ui->bound);
futex_init(&ui->prepared);
ui->peer = NULL;
ui->flags = 0;
pr_info(" `- Got %#x peer %#x (name %s)\n",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment