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