net: add an ioctl to get a socket network namespace
authorAndrey Vagin <avagin@openvz.org>
Tue, 25 Oct 2016 01:29:13 +0000 (18:29 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 31 Oct 2016 14:56:36 +0000 (10:56 -0400)
Each socket operates in a network namespace where it has been created,
so if we want to dump and restore a socket, we have to know its network
namespace.

We have a socket_diag to get information about sockets, it doesn't
report sockets which are not bound or connected.

This patch introduces a new socket ioctl, which is called SIOCGSKNS
and used to get a file descriptor for a socket network namespace.

A task must have CAP_NET_ADMIN in a target network namespace to
use this ioctl.

Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Andrei Vagin <avagin@openvz.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
fs/nsfs.c
include/linux/proc_fs.h
include/uapi/linux/sockios.h
net/socket.c

index 8718af895eabf791451e1b607d7b0a2b2d33cef2..8c9fb29c667327549737a6a9b6440d2564c7c710 100644 (file)
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -118,7 +118,7 @@ again:
        return ret;
 }
 
-static int open_related_ns(struct ns_common *ns,
+int open_related_ns(struct ns_common *ns,
                   struct ns_common *(*get_ns)(struct ns_common *ns))
 {
        struct path path = {};
index b97bf2ef996ef3e9e0cf906280741f20365d1455..368c7ad06ae5b173d9cbe866de539d358e42b516 100644 (file)
@@ -82,4 +82,8 @@ static inline struct proc_dir_entry *proc_net_mkdir(
        return proc_mkdir_data(name, 0, parent, net);
 }
 
+struct ns_common;
+int open_related_ns(struct ns_common *ns,
+                  struct ns_common *(*get_ns)(struct ns_common *ns));
+
 #endif /* _LINUX_PROC_FS_H */
index 8e7890b26d9ab6b140ffe3bf13aea49ab27c7fef..83cc54ce6081e572984e7ba3c793c5adc7459a6f 100644 (file)
@@ -84,6 +84,7 @@
 #define SIOCWANDEV     0x894A          /* get/set netdev parameters    */
 
 #define SIOCOUTQNSD    0x894B          /* output queue size (not sent only) */
+#define SIOCGSKNS      0x894C          /* get socket network namespace */
 
 /* ARP cache control calls. */
                    /*  0x8950 - 0x8952  * obsolete calls, don't re-use */
index 5a9bf5ee2464da20fbb42ea6699b29318553e210..970a7ea3fc4ac89755ffef0d2af4e0153f79d26d 100644 (file)
@@ -877,6 +877,11 @@ static long sock_do_ioctl(struct net *net, struct socket *sock,
  *     what to do with it - that's up to the protocol still.
  */
 
+static struct ns_common *get_net_ns(struct ns_common *ns)
+{
+       return &get_net(container_of(ns, struct net, ns))->ns;
+}
+
 static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
 {
        struct socket *sock;
@@ -945,6 +950,13 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
                                err = dlci_ioctl_hook(cmd, argp);
                        mutex_unlock(&dlci_ioctl_mutex);
                        break;
+               case SIOCGSKNS:
+                       err = -EPERM;
+                       if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
+                               break;
+
+                       err = open_related_ns(&net->ns, get_net_ns);
+                       break;
                default:
                        err = sock_do_ioctl(net, sock, cmd, arg);
                        break;
@@ -3093,6 +3105,7 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
        case SIOCSIFVLAN:
        case SIOCADDDLCI:
        case SIOCDELDLCI:
+       case SIOCGSKNS:
                return sock_ioctl(file, cmd, arg);
 
        case SIOCGIFFLAGS: