Branch data Line data Source code
1 : : /* -*- linux-c -*-
2 : : * sysctl_net_core.c: sysctl interface to net core subsystem.
3 : : *
4 : : * Begun April 1, 1996, Mike Shaver.
5 : : * Added /proc/sys/net/core directory entry (empty =) ). [MS]
6 : : */
7 : :
8 : : #include <linux/mm.h>
9 : : #include <linux/sysctl.h>
10 : : #include <linux/module.h>
11 : : #include <linux/socket.h>
12 : : #include <linux/netdevice.h>
13 : : #include <linux/ratelimit.h>
14 : : #include <linux/vmalloc.h>
15 : : #include <linux/init.h>
16 : : #include <linux/slab.h>
17 : : #include <linux/kmemleak.h>
18 : :
19 : : #include <net/ip.h>
20 : : #include <net/sock.h>
21 : : #include <net/net_ratelimit.h>
22 : : #include <net/busy_poll.h>
23 : : #include <net/pkt_sched.h>
24 : :
25 : : static int zero = 0;
26 : : static int one = 1;
27 : : static int ushort_max = USHRT_MAX;
28 : :
29 : : #ifdef CONFIG_RPS
30 : 0 : static int rps_sock_flow_sysctl(struct ctl_table *table, int write,
31 : : void __user *buffer, size_t *lenp, loff_t *ppos)
32 : : {
33 : : unsigned int orig_size, size;
34 : : int ret, i;
35 : 4 : struct ctl_table tmp = {
36 : : .data = &size,
37 : : .maxlen = sizeof(size),
38 : 2 : .mode = table->mode
39 : : };
40 : : struct rps_sock_flow_table *orig_sock_table, *sock_table;
41 : : static DEFINE_MUTEX(sock_flow_mutex);
42 : :
43 : 2 : mutex_lock(&sock_flow_mutex);
44 : :
45 : 2 : orig_sock_table = rcu_dereference_protected(rps_sock_flow_table,
46 : : lockdep_is_held(&sock_flow_mutex));
47 [ - + ]: 2 : size = orig_size = orig_sock_table ? orig_sock_table->mask + 1 : 0;
48 : :
49 : 2 : ret = proc_dointvec(&tmp, write, buffer, lenp, ppos);
50 : :
51 [ - + ]: 2 : if (write) {
52 [ # # ]: 0 : if (size) {
53 [ - + ]: 2 : if (size > 1<<30) {
54 : : /* Enforce limit to prevent overflow */
55 : 0 : mutex_unlock(&sock_flow_mutex);
56 : 0 : return -EINVAL;
57 : : }
58 [ + - ][ + - ]: 2 : size = roundup_pow_of_two(size);
[ + - ][ - + ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - - ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
59 [ # # ]: 0 : if (size != orig_size) {
60 : 0 : sock_table =
61 : 0 : vmalloc(RPS_SOCK_FLOW_TABLE_SIZE(size));
62 [ # # ]: 0 : if (!sock_table) {
63 : 0 : mutex_unlock(&sock_flow_mutex);
64 : 0 : return -ENOMEM;
65 : : }
66 : :
67 : 0 : sock_table->mask = size - 1;
68 : : } else
69 : : sock_table = orig_sock_table;
70 : :
71 [ # # ]: 0 : for (i = 0; i < size; i++)
72 : 0 : sock_table->ents[i] = RPS_NO_CPU;
73 : : } else
74 : : sock_table = NULL;
75 : :
76 [ - ]: 0 : if (sock_table != orig_sock_table) {
77 : 0 : rcu_assign_pointer(rps_sock_flow_table, sock_table);
78 [ # # ]: 0 : if (sock_table)
79 : : static_key_slow_inc(&rps_needed);
80 [ # # ]: 0 : if (orig_sock_table) {
81 : : static_key_slow_dec(&rps_needed);
82 : : synchronize_rcu();
83 : 0 : vfree(orig_sock_table);
84 : : }
85 : : }
86 : : }
87 : :
88 : 0 : mutex_unlock(&sock_flow_mutex);
89 : :
90 : 2 : return ret;
91 : : }
92 : : #endif /* CONFIG_RPS */
93 : :
94 : : #ifdef CONFIG_NET_FLOW_LIMIT
95 : : static DEFINE_MUTEX(flow_limit_update_mutex);
96 : :
97 : 0 : static int flow_limit_cpu_sysctl(struct ctl_table *table, int write,
98 : : void __user *buffer, size_t *lenp,
99 : : loff_t *ppos)
100 : : {
101 : : struct sd_flow_limit *cur;
102 : : struct softnet_data *sd;
103 : : cpumask_var_t mask;
104 : : int i, len, ret = 0;
105 : :
106 : : if (!alloc_cpumask_var(&mask, GFP_KERNEL))
107 : : return -ENOMEM;
108 : :
109 [ - + ]: 2 : if (write) {
110 : 0 : ret = cpumask_parse_user(buffer, *lenp, mask);
111 [ # # ]: 0 : if (ret)
112 : : goto done;
113 : :
114 : 0 : mutex_lock(&flow_limit_update_mutex);
115 : 0 : len = sizeof(*cur) + netdev_flow_limit_table_len;
116 [ # # ]: 0 : for_each_possible_cpu(i) {
117 : 0 : sd = &per_cpu(softnet_data, i);
118 : 0 : cur = rcu_dereference_protected(sd->flow_limit,
119 : : lockdep_is_held(&flow_limit_update_mutex));
120 [ # # ][ # # ]: 0 : if (cur && !cpumask_test_cpu(i, mask)) {
121 : 0 : RCU_INIT_POINTER(sd->flow_limit, NULL);
122 : : synchronize_rcu();
123 : 0 : kfree(cur);
124 [ # # ][ # # ]: 0 : } else if (!cur && cpumask_test_cpu(i, mask)) {
125 : : cur = kzalloc(len, GFP_KERNEL);
126 [ # # ]: 0 : if (!cur) {
127 : : /* not unwinding previous changes */
128 : : ret = -ENOMEM;
129 : : goto write_unlock;
130 : : }
131 : 0 : cur->num_buckets = netdev_flow_limit_table_len;
132 : 0 : rcu_assign_pointer(sd->flow_limit, cur);
133 : : }
134 : : }
135 : : write_unlock:
136 : 0 : mutex_unlock(&flow_limit_update_mutex);
137 : : } else {
138 : : char kbuf[128];
139 : :
140 [ + + ][ - + ]: 2 : if (*ppos || !*lenp) {
141 : 1 : *lenp = 0;
142 : 1 : goto done;
143 : : }
144 : :
145 : : cpumask_clear(mask);
146 : : rcu_read_lock();
147 [ + + ]: 7 : for_each_possible_cpu(i) {
148 : 5 : sd = &per_cpu(softnet_data, i);
149 [ - + ]: 5 : if (rcu_dereference(sd->flow_limit))
150 : : cpumask_set_cpu(i, mask);
151 : : }
152 : : rcu_read_unlock();
153 : :
154 : 1 : len = min(sizeof(kbuf) - 1, *lenp);
155 : : len = cpumask_scnprintf(kbuf, len, mask);
156 [ - + ]: 1 : if (!len) {
157 : 0 : *lenp = 0;
158 : 0 : goto done;
159 : : }
160 [ + - ]: 1 : if (len < *lenp)
161 : 1 : kbuf[len++] = '\n';
162 [ + - ]: 1 : if (copy_to_user(buffer, kbuf, len)) {
163 : : ret = -EFAULT;
164 : : goto done;
165 : : }
166 : 1 : *lenp = len;
167 : 1 : *ppos += len;
168 : : }
169 : :
170 : : done:
171 : : free_cpumask_var(mask);
172 : : return ret;
173 : : }
174 : :
175 : 0 : static int flow_limit_table_len_sysctl(struct ctl_table *table, int write,
176 : : void __user *buffer, size_t *lenp,
177 : : loff_t *ppos)
178 : : {
179 : : unsigned int old, *ptr;
180 : : int ret;
181 : :
182 : 2 : mutex_lock(&flow_limit_update_mutex);
183 : :
184 : 2 : ptr = table->data;
185 : 2 : old = *ptr;
186 : 2 : ret = proc_dointvec(table, write, buffer, lenp, ppos);
187 [ - + ][ # # ]: 2 : if (!ret && write && !is_power_of_2(*ptr)) {
188 : 0 : *ptr = old;
189 : : ret = -EINVAL;
190 : : }
191 : :
192 : 2 : mutex_unlock(&flow_limit_update_mutex);
193 : 2 : return ret;
194 : : }
195 : : #endif /* CONFIG_NET_FLOW_LIMIT */
196 : :
197 : : #ifdef CONFIG_NET_SCHED
198 : : static int set_default_qdisc(struct ctl_table *table, int write,
199 : : void __user *buffer, size_t *lenp, loff_t *ppos)
200 : : {
201 : : char id[IFNAMSIZ];
202 : : struct ctl_table tbl = {
203 : : .data = id,
204 : : .maxlen = IFNAMSIZ,
205 : : };
206 : : int ret;
207 : :
208 : : qdisc_get_default(id, IFNAMSIZ);
209 : :
210 : : ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
211 : : if (write && ret == 0)
212 : : ret = qdisc_set_default(id);
213 : : return ret;
214 : : }
215 : : #endif
216 : :
217 : : static struct ctl_table net_core_table[] = {
218 : : #ifdef CONFIG_NET
219 : : {
220 : : .procname = "wmem_max",
221 : : .data = &sysctl_wmem_max,
222 : : .maxlen = sizeof(int),
223 : : .mode = 0644,
224 : : .proc_handler = proc_dointvec_minmax,
225 : : .extra1 = &one,
226 : : },
227 : : {
228 : : .procname = "rmem_max",
229 : : .data = &sysctl_rmem_max,
230 : : .maxlen = sizeof(int),
231 : : .mode = 0644,
232 : : .proc_handler = proc_dointvec_minmax,
233 : : .extra1 = &one,
234 : : },
235 : : {
236 : : .procname = "wmem_default",
237 : : .data = &sysctl_wmem_default,
238 : : .maxlen = sizeof(int),
239 : : .mode = 0644,
240 : : .proc_handler = proc_dointvec_minmax,
241 : : .extra1 = &one,
242 : : },
243 : : {
244 : : .procname = "rmem_default",
245 : : .data = &sysctl_rmem_default,
246 : : .maxlen = sizeof(int),
247 : : .mode = 0644,
248 : : .proc_handler = proc_dointvec_minmax,
249 : : .extra1 = &one,
250 : : },
251 : : {
252 : : .procname = "dev_weight",
253 : : .data = &weight_p,
254 : : .maxlen = sizeof(int),
255 : : .mode = 0644,
256 : : .proc_handler = proc_dointvec
257 : : },
258 : : {
259 : : .procname = "netdev_max_backlog",
260 : : .data = &netdev_max_backlog,
261 : : .maxlen = sizeof(int),
262 : : .mode = 0644,
263 : : .proc_handler = proc_dointvec
264 : : },
265 : : #ifdef CONFIG_BPF_JIT
266 : : {
267 : : .procname = "bpf_jit_enable",
268 : : .data = &bpf_jit_enable,
269 : : .maxlen = sizeof(int),
270 : : .mode = 0644,
271 : : .proc_handler = proc_dointvec
272 : : },
273 : : #endif
274 : : {
275 : : .procname = "netdev_tstamp_prequeue",
276 : : .data = &netdev_tstamp_prequeue,
277 : : .maxlen = sizeof(int),
278 : : .mode = 0644,
279 : : .proc_handler = proc_dointvec
280 : : },
281 : : {
282 : : .procname = "message_cost",
283 : : .data = &net_ratelimit_state.interval,
284 : : .maxlen = sizeof(int),
285 : : .mode = 0644,
286 : : .proc_handler = proc_dointvec_jiffies,
287 : : },
288 : : {
289 : : .procname = "message_burst",
290 : : .data = &net_ratelimit_state.burst,
291 : : .maxlen = sizeof(int),
292 : : .mode = 0644,
293 : : .proc_handler = proc_dointvec,
294 : : },
295 : : {
296 : : .procname = "optmem_max",
297 : : .data = &sysctl_optmem_max,
298 : : .maxlen = sizeof(int),
299 : : .mode = 0644,
300 : : .proc_handler = proc_dointvec
301 : : },
302 : : #ifdef CONFIG_RPS
303 : : {
304 : : .procname = "rps_sock_flow_entries",
305 : : .maxlen = sizeof(int),
306 : : .mode = 0644,
307 : : .proc_handler = rps_sock_flow_sysctl
308 : : },
309 : : #endif
310 : : #ifdef CONFIG_NET_FLOW_LIMIT
311 : : {
312 : : .procname = "flow_limit_cpu_bitmap",
313 : : .mode = 0644,
314 : : .proc_handler = flow_limit_cpu_sysctl
315 : : },
316 : : {
317 : : .procname = "flow_limit_table_len",
318 : : .data = &netdev_flow_limit_table_len,
319 : : .maxlen = sizeof(int),
320 : : .mode = 0644,
321 : : .proc_handler = flow_limit_table_len_sysctl
322 : : },
323 : : #endif /* CONFIG_NET_FLOW_LIMIT */
324 : : #ifdef CONFIG_NET_RX_BUSY_POLL
325 : : {
326 : : .procname = "busy_poll",
327 : : .data = &sysctl_net_busy_poll,
328 : : .maxlen = sizeof(unsigned int),
329 : : .mode = 0644,
330 : : .proc_handler = proc_dointvec
331 : : },
332 : : {
333 : : .procname = "busy_read",
334 : : .data = &sysctl_net_busy_read,
335 : : .maxlen = sizeof(unsigned int),
336 : : .mode = 0644,
337 : : .proc_handler = proc_dointvec
338 : : },
339 : : #endif
340 : : #ifdef CONFIG_NET_SCHED
341 : : {
342 : : .procname = "default_qdisc",
343 : : .mode = 0644,
344 : : .maxlen = IFNAMSIZ,
345 : : .proc_handler = set_default_qdisc
346 : : },
347 : : #endif
348 : : #endif /* CONFIG_NET */
349 : : {
350 : : .procname = "netdev_budget",
351 : : .data = &netdev_budget,
352 : : .maxlen = sizeof(int),
353 : : .mode = 0644,
354 : : .proc_handler = proc_dointvec
355 : : },
356 : : {
357 : : .procname = "warnings",
358 : : .data = &net_msg_warn,
359 : : .maxlen = sizeof(int),
360 : : .mode = 0644,
361 : : .proc_handler = proc_dointvec
362 : : },
363 : : { }
364 : : };
365 : :
366 : : static struct ctl_table netns_core_table[] = {
367 : : {
368 : : .procname = "somaxconn",
369 : : .data = &init_net.core.sysctl_somaxconn,
370 : : .maxlen = sizeof(int),
371 : : .mode = 0644,
372 : : .extra1 = &zero,
373 : : .extra2 = &ushort_max,
374 : : .proc_handler = proc_dointvec_minmax
375 : : },
376 : : { }
377 : : };
378 : :
379 : 0 : static __net_init int sysctl_core_net_init(struct net *net)
380 : : {
381 : : struct ctl_table *tbl;
382 : :
383 : 0 : net->core.sysctl_somaxconn = SOMAXCONN;
384 : :
385 : : tbl = netns_core_table;
386 : : if (!net_eq(net, &init_net)) {
387 : : tbl = kmemdup(tbl, sizeof(netns_core_table), GFP_KERNEL);
388 : : if (tbl == NULL)
389 : : goto err_dup;
390 : :
391 : : tbl[0].data = &net->core.sysctl_somaxconn;
392 : :
393 : : /* Don't export any sysctls to unprivileged users */
394 : : if (net->user_ns != &init_user_ns) {
395 : : tbl[0].procname = NULL;
396 : : }
397 : : }
398 : :
399 : 0 : net->core.sysctl_hdr = register_net_sysctl(net, "net/core", tbl);
400 [ # # ]: 0 : if (net->core.sysctl_hdr == NULL)
401 : : goto err_reg;
402 : :
403 : : return 0;
404 : :
405 : : err_reg:
406 : : if (tbl != netns_core_table)
407 : : kfree(tbl);
408 : : err_dup:
409 : : return -ENOMEM;
410 : : }
411 : :
412 : 0 : static __net_exit void sysctl_core_net_exit(struct net *net)
413 : : {
414 : : struct ctl_table *tbl;
415 : :
416 : 0 : tbl = net->core.sysctl_hdr->ctl_table_arg;
417 : 0 : unregister_net_sysctl_table(net->core.sysctl_hdr);
418 [ # # ]: 0 : BUG_ON(tbl == netns_core_table);
419 : 0 : kfree(tbl);
420 : 0 : }
421 : :
422 : : static __net_initdata struct pernet_operations sysctl_core_ops = {
423 : : .init = sysctl_core_net_init,
424 : : .exit = sysctl_core_net_exit,
425 : : };
426 : :
427 : 0 : static __init int sysctl_core_init(void)
428 : : {
429 : 0 : register_net_sysctl(&init_net, "net/core", net_core_table);
430 : 0 : return register_pernet_subsys(&sysctl_core_ops);
431 : : }
432 : :
433 : : fs_initcall(sysctl_core_init);
|