net: add an ioctl to get a socket network namespace

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>
This commit is contained in:
Andrey Vagin 2016-10-24 18:29:13 -07:00 committed by David S. Miller
parent 2a43ca0aa9
commit c62cce2cae
4 changed files with 19 additions and 1 deletions

View File

@ -118,7 +118,7 @@ again:
return ret; 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 ns_common *(*get_ns)(struct ns_common *ns))
{ {
struct path path = {}; struct path path = {};

View File

@ -82,4 +82,8 @@ static inline struct proc_dir_entry *proc_net_mkdir(
return proc_mkdir_data(name, 0, parent, net); 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 */ #endif /* _LINUX_PROC_FS_H */

View File

@ -84,6 +84,7 @@
#define SIOCWANDEV 0x894A /* get/set netdev parameters */ #define SIOCWANDEV 0x894A /* get/set netdev parameters */
#define SIOCOUTQNSD 0x894B /* output queue size (not sent only) */ #define SIOCOUTQNSD 0x894B /* output queue size (not sent only) */
#define SIOCGSKNS 0x894C /* get socket network namespace */
/* ARP cache control calls. */ /* ARP cache control calls. */
/* 0x8950 - 0x8952 * obsolete calls, don't re-use */ /* 0x8950 - 0x8952 * obsolete calls, don't re-use */

View 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. * 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) static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{ {
struct socket *sock; 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); err = dlci_ioctl_hook(cmd, argp);
mutex_unlock(&dlci_ioctl_mutex); mutex_unlock(&dlci_ioctl_mutex);
break; 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: default:
err = sock_do_ioctl(net, sock, cmd, arg); err = sock_do_ioctl(net, sock, cmd, arg);
break; break;
@ -3093,6 +3105,7 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
case SIOCSIFVLAN: case SIOCSIFVLAN:
case SIOCADDDLCI: case SIOCADDDLCI:
case SIOCDELDLCI: case SIOCDELDLCI:
case SIOCGSKNS:
return sock_ioctl(file, cmd, arg); return sock_ioctl(file, cmd, arg);
case SIOCGIFFLAGS: case SIOCGIFFLAGS: