diff options
-rw-r--r-- | include/net/netns/ipv4.h | 3 | ||||
-rw-r--r-- | init/Kconfig | 1 | ||||
-rw-r--r-- | net/ipv4/ping.c | 18 | ||||
-rw-r--r-- | net/ipv4/sysctl_net_ipv4.c | 42 |
4 files changed, 35 insertions, 29 deletions
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 1474dd65c66f..3516dc0cc615 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h | |||
@@ -5,6 +5,7 @@ | |||
5 | #ifndef __NETNS_IPV4_H__ | 5 | #ifndef __NETNS_IPV4_H__ |
6 | #define __NETNS_IPV4_H__ | 6 | #define __NETNS_IPV4_H__ |
7 | 7 | ||
8 | #include <linux/uidgid.h> | ||
8 | #include <net/inet_frag.h> | 9 | #include <net/inet_frag.h> |
9 | 10 | ||
10 | struct tcpm_hash_bucket; | 11 | struct tcpm_hash_bucket; |
@@ -62,7 +63,7 @@ struct netns_ipv4 { | |||
62 | int sysctl_icmp_ratemask; | 63 | int sysctl_icmp_ratemask; |
63 | int sysctl_icmp_errors_use_inbound_ifaddr; | 64 | int sysctl_icmp_errors_use_inbound_ifaddr; |
64 | 65 | ||
65 | unsigned int sysctl_ping_group_range[2]; | 66 | kgid_t sysctl_ping_group_range[2]; |
66 | long sysctl_tcp_mem[3]; | 67 | long sysctl_tcp_mem[3]; |
67 | 68 | ||
68 | atomic_t rt_genid; | 69 | atomic_t rt_genid; |
diff --git a/init/Kconfig b/init/Kconfig index 25a6ebb50c64..f857f97bcef3 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
@@ -948,7 +948,6 @@ config UIDGID_CONVERTED | |||
948 | depends on NETFILTER_XT_MATCH_RECENT = n | 948 | depends on NETFILTER_XT_MATCH_RECENT = n |
949 | depends on NETFILTER_XT_TARGET_LOG = n | 949 | depends on NETFILTER_XT_TARGET_LOG = n |
950 | depends on NETFILTER_NETLINK_LOG = n | 950 | depends on NETFILTER_NETLINK_LOG = n |
951 | depends on INET = n | ||
952 | depends on IPV6 = n | 951 | depends on IPV6 = n |
953 | depends on AF_RXRPC = n | 952 | depends on AF_RXRPC = n |
954 | depends on NET_KEY = n | 953 | depends on NET_KEY = n |
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index bee5eeb676f8..8f3d05424a3e 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c | |||
@@ -185,10 +185,10 @@ exit: | |||
185 | return sk; | 185 | return sk; |
186 | } | 186 | } |
187 | 187 | ||
188 | static void inet_get_ping_group_range_net(struct net *net, gid_t *low, | 188 | static void inet_get_ping_group_range_net(struct net *net, kgid_t *low, |
189 | gid_t *high) | 189 | kgid_t *high) |
190 | { | 190 | { |
191 | gid_t *data = net->ipv4.sysctl_ping_group_range; | 191 | kgid_t *data = net->ipv4.sysctl_ping_group_range; |
192 | unsigned int seq; | 192 | unsigned int seq; |
193 | 193 | ||
194 | do { | 194 | do { |
@@ -203,19 +203,13 @@ static void inet_get_ping_group_range_net(struct net *net, gid_t *low, | |||
203 | static int ping_init_sock(struct sock *sk) | 203 | static int ping_init_sock(struct sock *sk) |
204 | { | 204 | { |
205 | struct net *net = sock_net(sk); | 205 | struct net *net = sock_net(sk); |
206 | gid_t group = current_egid(); | 206 | kgid_t group = current_egid(); |
207 | gid_t range[2]; | ||
208 | struct group_info *group_info = get_current_groups(); | 207 | struct group_info *group_info = get_current_groups(); |
209 | int i, j, count = group_info->ngroups; | 208 | int i, j, count = group_info->ngroups; |
210 | kgid_t low, high; | 209 | kgid_t low, high; |
211 | 210 | ||
212 | inet_get_ping_group_range_net(net, range, range+1); | 211 | inet_get_ping_group_range_net(net, &low, &high); |
213 | low = make_kgid(&init_user_ns, range[0]); | 212 | if (gid_lte(low, group) && gid_lte(group, high)) |
214 | high = make_kgid(&init_user_ns, range[1]); | ||
215 | if (!gid_valid(low) || !gid_valid(high) || gid_lt(high, low)) | ||
216 | return -EACCES; | ||
217 | |||
218 | if (range[0] <= group && group <= range[1]) | ||
219 | return 0; | 213 | return 0; |
220 | 214 | ||
221 | for (i = 0; i < group_info->nblocks; i++) { | 215 | for (i = 0; i < group_info->nblocks; i++) { |
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 1b5ce96707a3..3e78c79b5586 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c | |||
@@ -76,9 +76,9 @@ static int ipv4_local_port_range(ctl_table *table, int write, | |||
76 | } | 76 | } |
77 | 77 | ||
78 | 78 | ||
79 | static void inet_get_ping_group_range_table(struct ctl_table *table, gid_t *low, gid_t *high) | 79 | static void inet_get_ping_group_range_table(struct ctl_table *table, kgid_t *low, kgid_t *high) |
80 | { | 80 | { |
81 | gid_t *data = table->data; | 81 | kgid_t *data = table->data; |
82 | unsigned int seq; | 82 | unsigned int seq; |
83 | do { | 83 | do { |
84 | seq = read_seqbegin(&sysctl_local_ports.lock); | 84 | seq = read_seqbegin(&sysctl_local_ports.lock); |
@@ -89,12 +89,12 @@ static void inet_get_ping_group_range_table(struct ctl_table *table, gid_t *low, | |||
89 | } | 89 | } |
90 | 90 | ||
91 | /* Update system visible IP port range */ | 91 | /* Update system visible IP port range */ |
92 | static void set_ping_group_range(struct ctl_table *table, gid_t range[2]) | 92 | static void set_ping_group_range(struct ctl_table *table, kgid_t low, kgid_t high) |
93 | { | 93 | { |
94 | gid_t *data = table->data; | 94 | kgid_t *data = table->data; |
95 | write_seqlock(&sysctl_local_ports.lock); | 95 | write_seqlock(&sysctl_local_ports.lock); |
96 | data[0] = range[0]; | 96 | data[0] = low; |
97 | data[1] = range[1]; | 97 | data[1] = high; |
98 | write_sequnlock(&sysctl_local_ports.lock); | 98 | write_sequnlock(&sysctl_local_ports.lock); |
99 | } | 99 | } |
100 | 100 | ||
@@ -103,21 +103,33 @@ static int ipv4_ping_group_range(ctl_table *table, int write, | |||
103 | void __user *buffer, | 103 | void __user *buffer, |
104 | size_t *lenp, loff_t *ppos) | 104 | size_t *lenp, loff_t *ppos) |
105 | { | 105 | { |
106 | struct user_namespace *user_ns = current_user_ns(); | ||
106 | int ret; | 107 | int ret; |
107 | gid_t range[2]; | 108 | gid_t urange[2]; |
109 | kgid_t low, high; | ||
108 | ctl_table tmp = { | 110 | ctl_table tmp = { |
109 | .data = &range, | 111 | .data = &urange, |
110 | .maxlen = sizeof(range), | 112 | .maxlen = sizeof(urange), |
111 | .mode = table->mode, | 113 | .mode = table->mode, |
112 | .extra1 = &ip_ping_group_range_min, | 114 | .extra1 = &ip_ping_group_range_min, |
113 | .extra2 = &ip_ping_group_range_max, | 115 | .extra2 = &ip_ping_group_range_max, |
114 | }; | 116 | }; |
115 | 117 | ||
116 | inet_get_ping_group_range_table(table, range, range + 1); | 118 | inet_get_ping_group_range_table(table, &low, &high); |
119 | urange[0] = from_kgid_munged(user_ns, low); | ||
120 | urange[1] = from_kgid_munged(user_ns, high); | ||
117 | ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); | 121 | ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); |
118 | 122 | ||
119 | if (write && ret == 0) | 123 | if (write && ret == 0) { |
120 | set_ping_group_range(table, range); | 124 | low = make_kgid(user_ns, urange[0]); |
125 | high = make_kgid(user_ns, urange[1]); | ||
126 | if (!gid_valid(low) || !gid_valid(high) || | ||
127 | (urange[1] < urange[0]) || gid_lt(high, low)) { | ||
128 | low = make_kgid(&init_user_ns, 1); | ||
129 | high = make_kgid(&init_user_ns, 0); | ||
130 | } | ||
131 | set_ping_group_range(table, low, high); | ||
132 | } | ||
121 | 133 | ||
122 | return ret; | 134 | return ret; |
123 | } | 135 | } |
@@ -786,7 +798,7 @@ static struct ctl_table ipv4_net_table[] = { | |||
786 | { | 798 | { |
787 | .procname = "ping_group_range", | 799 | .procname = "ping_group_range", |
788 | .data = &init_net.ipv4.sysctl_ping_group_range, | 800 | .data = &init_net.ipv4.sysctl_ping_group_range, |
789 | .maxlen = sizeof(init_net.ipv4.sysctl_ping_group_range), | 801 | .maxlen = sizeof(gid_t)*2, |
790 | .mode = 0644, | 802 | .mode = 0644, |
791 | .proc_handler = ipv4_ping_group_range, | 803 | .proc_handler = ipv4_ping_group_range, |
792 | }, | 804 | }, |
@@ -830,8 +842,8 @@ static __net_init int ipv4_sysctl_init_net(struct net *net) | |||
830 | * Sane defaults - nobody may create ping sockets. | 842 | * Sane defaults - nobody may create ping sockets. |
831 | * Boot scripts should set this to distro-specific group. | 843 | * Boot scripts should set this to distro-specific group. |
832 | */ | 844 | */ |
833 | net->ipv4.sysctl_ping_group_range[0] = 1; | 845 | net->ipv4.sysctl_ping_group_range[0] = make_kgid(&init_user_ns, 1); |
834 | net->ipv4.sysctl_ping_group_range[1] = 0; | 846 | net->ipv4.sysctl_ping_group_range[1] = make_kgid(&init_user_ns, 0); |
835 | 847 | ||
836 | tcp_init_mem(net); | 848 | tcp_init_mem(net); |
837 | 849 | ||