@@ -1401,13 +1401,14 @@ static void unlink_stale(struct unix_sk_info *ui)
}
static int resolve_unix_peer(struct unix_sk_info *ui);
+static int fixup_unix_peer(struct unix_sk_info *ui);
static int post_prepare_unix_sk(struct pprep_head *ph)
{
struct unix_sk_info *ui;
ui = container_of(ph, struct unix_sk_info, peer_resolve);
- if (ui->ue->peer && resolve_unix_peer(ui))
+ if (ui->ue->peer && fixup_unix_peer(ui))
return -1;
if (ui->name)
unlink_stale(ui);
@@ -1468,6 +1469,9 @@ static int collect_one_unixsk(void *o, ProtobufCMessage *base, struct cr_img *i)
ui->name_dir ? ui->name_dir : "-");
if (ui->ue->peer || ui->name) {
+ if (ui->ue->peer && resolve_unix_peer(ui))
+ return -1;
+
ui->peer_resolve.actor = post_prepare_unix_sk;
add_post_prepare_cb(&ui->peer_resolve);
}
@@ -1512,6 +1516,27 @@ static void interconnected_pair(struct unix_sk_info *ui, struct unix_sk_info *pe
}
}
+static int fixup_unix_peer(struct unix_sk_info *ui)
+{
+ struct unix_sk_info *peer = ui->peer;
+
+ if (!peer) {
+ pr_err("FATAL: Peer %#x unresolved for %#x\n",
+ ui->ue->peer, ui->ue->ino);
+ return -1;
+ }
+
+ if (peer->peer == ui &&
+ !(ui->flags & (USK_PAIR_MASTER | USK_PAIR_SLAVE))) {
+ pr_info("Connected %#x -> %#x (%#x) flags %#x\n",
+ ui->ue->ino, ui->ue->peer, peer->ue->ino, ui->flags);
+ /* socketpair or interconnected sockets */
+ interconnected_pair(ui, peer);
+ }
+
+ return 0;
+}
+
static int resolve_unix_peer(struct unix_sk_info *ui)
{
struct unix_sk_info *peer;
@@ -1522,11 +1547,8 @@ static int resolve_unix_peer(struct unix_sk_info *ui)
BUG_ON(!ui->ue->peer);
peer = find_unix_sk_by_ino(ui->ue->peer);
- if (!peer) {
- pr_err("FATAL: Peer %#x unresolved for %#x\n",
- ui->ue->peer, ui->ue->ino);
- return -1;
- }
+ if (!peer)
+ goto out; /* Maybe later */
set_peer(ui, peer);
if (ui == peer)
@@ -1535,11 +1557,7 @@ static int resolve_unix_peer(struct unix_sk_info *ui)
if (peer->ue->peer != ui->ue->ino)
goto out;
- pr_info("Connected %#x -> %#x (%#x) flags %#x\n",
- ui->ue->ino, ui->ue->peer, peer->ue->ino, ui->flags);
set_peer(peer, ui);
- /* socketpair or interconnected sockets */
- interconnected_pair(ui, peer);
out:
return 0;
}
In order to make sender of a descriptor (unix socket) be restored _after_ the descriptor in question, we need to find out those sockets early (before post-prep calls). The problem is that current code gives us info about who's the queuer for who only in post-prep hooks, so the peer resolution should happen right in collect callback. At the same time we need to make sure that all peers configured in the image exist, as well as need to put master/slave flags for socketpairs. Both these actions can only happen in post-prep. Said that -- the current peer resolve routine should be split into two steps. Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com> --- criu/sk-unix.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-)