[RH7,24/32] net: add an ioctl to get a socket network namespace

Submitted by Pavel Tikhomirov on June 8, 2020, 5:05 p.m.

Details

Message ID 20200608170602.308872-25-ptikhomirov@virtuozzo.com
State New
Series "port nsfs from vz8"
Headers show

Commit Message

Pavel Tikhomirov June 8, 2020, 5:05 p.m.
From: Andrey Vagin <avagin@openvz.org>

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>

(cherry picked from VZ8 commit c62cce2caee558e18aa05c01c2fd3b40f07174f2)

https://jira.sw.ru/browse/PSBM-102357

Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
---
 fs/nsfs.c                    |  2 +-
 include/linux/proc_fs.h      |  4 ++++
 include/uapi/linux/sockios.h |  1 +
 net/socket.c                 | 13 +++++++++++++
 4 files changed, 19 insertions(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/fs/nsfs.c b/fs/nsfs.c
index 20ae4f7d92e6..fb5215552a8d 100644
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -126,7 +126,7 @@  void *ns_get_path(struct path *path, struct task_struct *task,
 	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 = {};
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 1b516bccb5e2..91d2eab45808 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -120,4 +120,8 @@  static inline struct proc_dir_entry *proc_net_mkdir(
 	return proc_mkdir_data(name, S_ISVTX|S_IRUGO|S_IXUGO, 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 */
diff --git a/include/uapi/linux/sockios.h b/include/uapi/linux/sockios.h
index e888b1aed69f..cf0a25ebc74c 100644
--- a/include/uapi/linux/sockios.h
+++ b/include/uapi/linux/sockios.h
@@ -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 */
diff --git a/net/socket.c b/net/socket.c
index 5cb4ccef937c..728c7ec9fca4 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1091,6 +1091,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;
@@ -1158,6 +1163,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;
@@ -3316,6 +3328,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: