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.
Unified · Split
| @@ -118,7 +118,7 @@ again: · 117 unmodified lines | ||
| 118 | 118 | return ret; |
| 119 | 119 | } |
| 120 | 120 | |
| 121 | −static int open_related_ns(struct ns_common *ns, | |
| 121 | +int open_related_ns(struct ns_common *ns, | |
| 122 | 122 | struct ns_common *(*get_ns)(struct ns_common *ns)) |
| 123 | 123 | { |
| 124 | 124 | struct path path = {}; |
| @@ -82,4 +82,8 @@ static inline struct proc_dir_entry *proc_net_mkdir( · 81 unmodified lines | ||
| 82 | 82 | return proc_mkdir_data(name, 0, parent, net); |
| 83 | 83 | } |
| 84 | 84 | |
| 85 | +struct ns_common; | |
| 86 | +int open_related_ns(struct ns_common *ns, | |
| 87 | + struct ns_common *(*get_ns)(struct ns_common *ns)); | |
| 88 | + | |
| 85 | 89 | #endif /* _LINUX_PROC_FS_H */ |
| @@ -84,6 +84,7 @@ · 83 unmodified lines | ||
| 84 | 84 | #define SIOCWANDEV 0x894A /* get/set netdev parameters */ |
| 85 | 85 | |
| 86 | 86 | #define SIOCOUTQNSD 0x894B /* output queue size (not sent only) */ |
| 87 | +#define SIOCGSKNS 0x894C /* get socket network namespace */ | |
| 87 | 88 | |
| 88 | 89 | /* ARP cache control calls. */ |
| 89 | 90 | /* 0x8950 - 0x8952 * obsolete calls, don't re-use */ |
| @@ -877,6 +877,11 @@ static long sock_do_ioctl(struct net *net, struct socket *sock, · 876 unmodified lines | ||
| 877 | 877 | * what to do with it - that's up to the protocol still. |
| 878 | 878 | */ |
| 879 | 879 | |
| 880 | +static struct ns_common *get_net_ns(struct ns_common *ns) | |
| 881 | +{ | |
| 882 | + return &get_net(container_of(ns, struct net, ns))->ns; | |
| 883 | +} | |
| 884 | + | |
| 880 | 885 | static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) |
| 881 | 886 | { |
| 882 | 887 | struct socket *sock; |
| @@ -945,6 +950,13 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) · 62 unmodified lines | ||
| 945 | 950 | err = dlci_ioctl_hook(cmd, argp); |
| 946 | 951 | mutex_unlock(&dlci_ioctl_mutex); |
| 947 | 952 | break; |
| 953 | + case SIOCGSKNS: | |
| 954 | + err = -EPERM; | |
| 955 | + if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) | |
| 956 | + break; | |
| 957 | + | |
| 958 | + err = open_related_ns(&net->ns, get_net_ns); | |
| 959 | + break; | |
| 948 | 960 | default: |
| 949 | 961 | err = sock_do_ioctl(net, sock, cmd, arg); |
| 950 | 962 | break; |
| @@ -3093,6 +3105,7 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, · 2142 unmodified lines | ||
| 3093 | 3105 | case SIOCSIFVLAN: |
| 3094 | 3106 | case SIOCADDDLCI: |
| 3095 | 3107 | case SIOCDELDLCI: |
| 3108 | + case SIOCGSKNS: | |
| 3096 | 3109 | return sock_ioctl(file, cmd, arg); |
| 3097 | 3110 | |
| 3098 | 3111 | case SIOCGIFFLAGS: |