From 0f6f224656d6eac998714833cef9828e801fd464 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Tue, 30 Jan 2018 18:41:56 +0300 Subject: [PATCH] unix: Add fake interconnected sockets We're going to split interconnected pair restore on two stages. Since we need the second end to restore message queue in (future) post open, we add it to the process, who is owner of the first end. Signed-off-by: Kirill Tkhai Signed-off-by: Andrei Vagin --- criu/sk-unix.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/criu/sk-unix.c b/criu/sk-unix.c index c8e61c844..cd53a8f74 100644 --- a/criu/sk-unix.c +++ b/criu/sk-unix.c @@ -1249,12 +1249,18 @@ done: static int open_unixsk_pair_master(struct unix_sk_info *ui, int *new_fd) { - int sk[2]; + struct fdinfo_list_entry *fle, *fle_peer; struct unix_sk_info *peer = ui->peer; + int sk[2]; pr_info("Opening pair master (id %#x ino %#x peer %#x)\n", ui->ue->id, ui->ue->ino, ui->ue->peer); + fle = file_master(&ui->d); + fle_peer = file_master(&peer->d); + + BUG_ON(fle->task != fle_peer->task); /* See interconnected_pair() */ + if (set_netns(ui->ue->ns_id)) return -1; @@ -1628,10 +1634,32 @@ static void set_peer(struct unix_sk_info *ui, struct unix_sk_info *peer) peer->queuer = ui->ue->id; } -static void interconnected_pair(struct unix_sk_info *ui, struct unix_sk_info *peer) +/* This function is called from post prepare only */ +static int interconnected_pair(struct unix_sk_info *ui, struct unix_sk_info *peer) { + struct fdinfo_list_entry *fle, *fle_peer; + ui->flags |= USK_PAIR_MASTER; peer->flags |= USK_PAIR_SLAVE; + + fle = file_master(&ui->d); + fle_peer = file_master(&peer->d); + + /* + * Since queue restore is delayed, every socket of the pair + * should have another end to send the queue packets. + * To fit that, we make the both file_master's to be owned + * by the only task. + * This function is called from run_post_prepare() and + * after add_fake_fds_masters(), so we must not add masters, + * which fle->task has no permissions to restore. But + * it has permissions on ui, so it has permissions on peer. + */ + if (fle->task != fle_peer->task && + !get_fle_for_task(&peer->d, fle->task, true)) + return -1; + + return 0; } static int fixup_unix_peer(struct unix_sk_info *ui) @@ -1649,7 +1677,8 @@ static int fixup_unix_peer(struct unix_sk_info *ui) 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); + if (interconnected_pair(ui, peer)) + return -1; } return 0;