diff options
Diffstat (limited to 'net/ipv4/sysctl_net_ipv4.c')
-rw-r--r-- | net/ipv4/sysctl_net_ipv4.c | 42 |
1 files changed, 27 insertions, 15 deletions
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 | ||