aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/netns/ipv4.h3
-rw-r--r--init/Kconfig1
-rw-r--r--net/ipv4/ping.c18
-rw-r--r--net/ipv4/sysctl_net_ipv4.c42
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
10struct tcpm_hash_bucket; 11struct 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
188static void inet_get_ping_group_range_net(struct net *net, gid_t *low, 188static 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,
203static int ping_init_sock(struct sock *sk) 203static 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
79static void inet_get_ping_group_range_table(struct ctl_table *table, gid_t *low, gid_t *high) 79static 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 */
92static void set_ping_group_range(struct ctl_table *table, gid_t range[2]) 92static 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