[CRIU] [PATCH 09/11] net: set a proper network namespace to create a socket
Pavel Emelyanov
xemul at virtuozzo.com
Wed Feb 8 01:58:46 PST 2017
On 02/02/2017 03:04 AM, Andrei Vagin wrote:
> From: Andrei Vagin <avagin at virtuozzo.com>
>
> Each socket has to be restored from a proper network namespaces
> where it was created.
>
> We set a specified network namespace before restoring a socket.
Should we restore it back after the socket is created?
> A task network namespace is set after restoring all files.
>
> Signed-off-by: Andrei Vagin <avagin at virtuozzo.com>
> ---
> criu/files.c | 3 +++
> criu/include/sockets.h | 2 ++
> criu/sk-inet.c | 3 +++
> criu/sk-netlink.c | 3 +++
> criu/sk-packet.c | 3 +++
> criu/sk-unix.c | 7 ++++++-
> criu/sockets.c | 37 +++++++++++++++++++++++++++++++++++++
> 7 files changed, 57 insertions(+), 1 deletion(-)
>
> diff --git a/criu/files.c b/criu/files.c
> index 8e4ed1b..b394947 100644
> --- a/criu/files.c
> +++ b/criu/files.c
> @@ -1686,6 +1686,9 @@ int open_transport_socket(void)
> if (!task_alive(current) || (fdt && fdt->pid != pid))
> return 0;
>
> + if (root_item->ids && set_netns(root_item->ids->net_ns_id))
> + return -1;
Tasks all live in one netns, why do we need to change it here?
> +
> sock = socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
> if (sock < 0) {
> pr_perror("Can't create socket");
> diff --git a/criu/include/sockets.h b/criu/include/sockets.h
> index 7685eeb..28bf91e 100644
> --- a/criu/include/sockets.h
> +++ b/criu/include/sockets.h
> @@ -82,4 +82,6 @@ static inline int sk_decode_shutdown(int val)
> #define NETLINK_SOCK_DIAG NETLINK_INET_DIAG
> #endif
>
> +extern int set_netns(uint32_t ns_id);
> +
> #endif /* __CR_SOCKETS_H__ */
> diff --git a/criu/sk-inet.c b/criu/sk-inet.c
> index bb898d5..ee6ce60 100644
> --- a/criu/sk-inet.c
> +++ b/criu/sk-inet.c
> @@ -643,6 +643,9 @@ static int open_inet_sk(struct file_desc *d, int *new_fd)
> if (inet_validate_address(ie))
> return -1;
>
> + if (set_netns(ie->ns_id))
> + return -1;
> +
> sk = socket(ie->family, ie->type, ie->proto);
> if (sk < 0) {
> pr_perror("Can't create inet socket");
> diff --git a/criu/sk-netlink.c b/criu/sk-netlink.c
> index 4ef934a..1101ee8 100644
> --- a/criu/sk-netlink.c
> +++ b/criu/sk-netlink.c
> @@ -179,6 +179,9 @@ static int open_netlink_sk(struct file_desc *d, int *new_fd)
>
> pr_info("Opening netlink socket id %#x\n", nse->id);
>
> + if (set_netns(nse->ns_id))
> + return -1;
> +
> sk = socket(PF_NETLINK, SOCK_RAW, nse->protocol);
> if (sk < 0) {
> pr_perror("Can't create netlink sock");
> diff --git a/criu/sk-packet.c b/criu/sk-packet.c
> index f1cf117..297877a 100644
> --- a/criu/sk-packet.c
> +++ b/criu/sk-packet.c
> @@ -470,6 +470,9 @@ static int open_packet_sk(struct file_desc *d, int *new_fd)
>
> pr_info("Opening packet socket id %#x\n", pse->id);
>
> + if (set_netns(pse->ns_id))
> + return -1;
> +
> if (pse->type == SOCK_PACKET)
> return open_packet_sk_spkt(pse, new_fd);
>
> diff --git a/criu/sk-unix.c b/criu/sk-unix.c
> index 35c4d32..fe6ff1b 100644
> --- a/criu/sk-unix.c
> +++ b/criu/sk-unix.c
> @@ -1092,6 +1092,9 @@ static int open_unixsk_pair_master(struct unix_sk_info *ui, int *new_fd)
> pr_info("Opening pair master (id %#x ino %#x peer %#x)\n",
> ui->ue->id, ui->ue->ino, ui->ue->peer);
>
> + if (set_netns(ui->ue->ns_id))
> + return -1;
> +
> if (socketpair(PF_UNIX, ui->ue->type, 0, sk) < 0) {
> pr_perror("Can't make socketpair");
> return -1;
> @@ -1167,6 +1170,9 @@ static int open_unixsk_standalone(struct unix_sk_info *ui, int *new_fd)
> pr_info("Opening standalone socket (id %#x ino %#x peer %#x)\n",
> ui->ue->id, ui->ue->ino, ui->ue->peer);
>
> + if (set_netns(ui->ue->ns_id))
> + return -1;
> +
> /*
> * Check if this socket was connected to criu service.
> * If so, put response, that dumping and restoring
> @@ -1270,7 +1276,6 @@ static int open_unixsk_standalone(struct unix_sk_info *ui, int *new_fd)
> return -1;
> }
>
> -
> sk = socket(PF_UNIX, ui->ue->type, 0);
> if (sk < 0) {
> pr_perror("Can't make unix socket");
> diff --git a/criu/sockets.c b/criu/sockets.c
> index 86a6b21..95da999 100644
> --- a/criu/sockets.c
> +++ b/criu/sockets.c
> @@ -1,3 +1,4 @@
> +#include <sched.h>
> #include <unistd.h>
> #include <sys/socket.h>
> #include <linux/netlink.h>
> @@ -24,6 +25,8 @@
> #include "net.h"
> #include "xmalloc.h"
> #include "fs-magic.h"
> +#include "pstree.h"
> +#include "util.h"
>
> #ifndef SOCK_DIAG_BY_FAMILY
> #define SOCK_DIAG_BY_FAMILY 20
> @@ -740,3 +743,37 @@ int collect_sockets(struct ns_id *ns)
>
> return err;
> }
> +
> +static uint32_t last_ns_id = 0;
> +
> +int set_netns(uint32_t ns_id)
> +{
> + struct ns_id *ns;
> + int nsfd;
> +
> + if (!(root_ns_mask & CLONE_NEWNET))
> + return 0;
> +
> + if (ns_id == last_ns_id)
> + return 0;
> +
> + ns = lookup_ns_by_id(ns_id, &net_ns_desc);
> + if (ns == NULL) {
> + pr_err("Unable to find a network namespace");
> + return -1;
> + }
> + nsfd = open_proc(root_item->pid->ns[0].virt, "fd/%d", ns->net.ns_fd);
> + if (nsfd < 0)
> + return -1;
> + if (setns(nsfd, CLONE_NEWNET)) {
> + pr_perror("Unable to switch a network namespace");
> + close(nsfd);
> + return -1;
> + }
> + last_ns_id = ns_id;
> + close(nsfd);
> +
> + close_pid_proc();
Why this?
> +
> + return 0;
> +}
>
More information about the CRIU
mailing list