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_node(len, GFP_KERNEL,
126 : : cpu_to_node(i));
127 [ # # ]: 0 : if (!cur) {
128 : : /* not unwinding previous changes */
129 : : ret = -ENOMEM;
130 : : goto write_unlock;
131 : : }
132 : 0 : cur->num_buckets = netdev_flow_limit_table_len;
133 : 0 : rcu_assign_pointer(sd->flow_limit, cur);
134 : : }
135 : : }
136 : : write_unlock:
137 : 0 : mutex_unlock(&flow_limit_update_mutex);
138 : : } else {
139 : : char kbuf[128];
140 : :
141 [ + + ][ - + ]: 2 : if (*ppos || !*lenp) {
142 : 1 : *lenp = 0;
143 : 1 : goto done;
144 : : }
145 : :
146 : : cpumask_clear(mask);
147 : : rcu_read_lock();
148 [ + + ]: 7 : for_each_possible_cpu(i) {
149 : 5 : sd = &per_cpu(softnet_data, i);
150 [ - + ]: 5 : if (rcu_dereference(sd->flow_limit))
151 : : cpumask_set_cpu(i, mask);
152 : : }
153 : : rcu_read_unlock();
154 : :
155 : 1 : len = min(sizeof(kbuf) - 1, *lenp);
156 : : len = cpumask_scnprintf(kbuf, len, mask);
157 [ - + ]: 1 : if (!len) {
158 : 0 : *lenp = 0;
159 : 0 : goto done;
160 : : }
161 [ + - ]: 1 : if (len < *lenp)
162 : 1 : kbuf[len++] = '\n';
163 [ + - ]: 3 : if (copy_to_user(buffer, kbuf, len)) {
164 : : ret = -EFAULT;
165 : : goto done;
166 : : }
167 : 1 : *lenp = len;
168 : 1 : *ppos += len;
169 : : }
170 : :
171 : : done:
172 : : free_cpumask_var(mask);
173 : : return ret;
174 : : }
175 : :
176 : 0 : static int flow_limit_table_len_sysctl(struct ctl_table *table, int write,
177 : : void __user *buffer, size_t *lenp,
178 : : loff_t *ppos)
179 : : {
180 : : unsigned int old, *ptr;
181 : : int ret;
182 : :
183 : 2 : mutex_lock(&flow_limit_update_mutex);
184 : :
185 : 2 : ptr = table->data;
186 : 2 : old = *ptr;
187 : 2 : ret = proc_dointvec(table, write, buffer, lenp, ppos);
188 [ - + ][ # # ]: 2 : if (!ret && write && !is_power_of_2(*ptr)) {
189 : 0 : *ptr = old;
190 : : ret = -EINVAL;
191 : : }
192 : :
193 : 2 : mutex_unlock(&flow_limit_update_mutex);
194 : 2 : return ret;
195 : : }
196 : : #endif /* CONFIG_NET_FLOW_LIMIT */
197 : :
198 : : #ifdef CONFIG_NET_SCHED
199 : : static int set_default_qdisc(struct ctl_table *table, int write,
200 : : void __user *buffer, size_t *lenp, loff_t *ppos)
201 : : {
202 : : char id[IFNAMSIZ];
203 : : struct ctl_table tbl = {
204 : : .data = id,
205 : : .maxlen = IFNAMSIZ,
206 : : };
207 : : int ret;
208 : :
209 : : qdisc_get_default(id, IFNAMSIZ);
210 : :
211 : : ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
212 : : if (write && ret == 0)
213 : : ret = qdisc_set_default(id);
214 : : return ret;
215 : : }
216 : : #endif
217 : :
218 : : static struct ctl_table net_core_table[] = {
219 : : #ifdef CONFIG_NET
220 : : {
221 : : .procname = "wmem_max",
222 : : .data = &sysctl_wmem_max,
223 : : .maxlen = sizeof(int),
224 : : .mode = 0644,
225 : : .proc_handler = proc_dointvec_minmax,
226 : : .extra1 = &one,
227 : : },
228 : : {
229 : : .procname = "rmem_max",
230 : : .data = &sysctl_rmem_max,
231 : : .maxlen = sizeof(int),
232 : : .mode = 0644,
233 : : .proc_handler = proc_dointvec_minmax,
234 : : .extra1 = &one,
235 : : },
236 : : {
237 : : .procname = "wmem_default",
238 : : .data = &sysctl_wmem_default,
239 : : .maxlen = sizeof(int),
240 : : .mode = 0644,
241 : : .proc_handler = proc_dointvec_minmax,
242 : : .extra1 = &one,
243 : : },
244 : : {
245 : : .procname = "rmem_default",
246 : : .data = &sysctl_rmem_default,
247 : : .maxlen = sizeof(int),
248 : : .mode = 0644,
249 : : .proc_handler = proc_dointvec_minmax,
250 : : .extra1 = &one,
251 : : },
252 : : {
253 : : .procname = "dev_weight",
254 : : .data = &weight_p,
255 : : .maxlen = sizeof(int),
256 : : .mode = 0644,
257 : : .proc_handler = proc_dointvec
258 : : },
259 : : {
260 : : .procname = "netdev_max_backlog",
261 : : .data = &netdev_max_backlog,
262 : : .maxlen = sizeof(int),
263 : : .mode = 0644,
264 : : .proc_handler = proc_dointvec
265 : : },
266 : : #ifdef CONFIG_BPF_JIT
267 : : {
268 : : .procname = "bpf_jit_enable",
269 : : .data = &bpf_jit_enable,
270 : : .maxlen = sizeof(int),
271 : : .mode = 0644,
272 : : .proc_handler = proc_dointvec
273 : : },
274 : : #endif
275 : : {
276 : : .procname = "netdev_tstamp_prequeue",
277 : : .data = &netdev_tstamp_prequeue,
278 : : .maxlen = sizeof(int),
279 : : .mode = 0644,
280 : : .proc_handler = proc_dointvec
281 : : },
282 : : {
283 : : .procname = "message_cost",
284 : : .data = &net_ratelimit_state.interval,
285 : : .maxlen = sizeof(int),
286 : : .mode = 0644,
287 : : .proc_handler = proc_dointvec_jiffies,
288 : : },
289 : : {
290 : : .procname = "message_burst",
291 : : .data = &net_ratelimit_state.burst,
292 : : .maxlen = sizeof(int),
293 : : .mode = 0644,
294 : : .proc_handler = proc_dointvec,
295 : : },
296 : : {
297 : : .procname = "optmem_max",
298 : : .data = &sysctl_optmem_max,
299 : : .maxlen = sizeof(int),
300 : : .mode = 0644,
301 : : .proc_handler = proc_dointvec
302 : : },
303 : : #ifdef CONFIG_RPS
304 : : {
305 : : .procname = "rps_sock_flow_entries",
306 : : .maxlen = sizeof(int),
307 : : .mode = 0644,
308 : : .proc_handler = rps_sock_flow_sysctl
309 : : },
310 : : #endif
311 : : #ifdef CONFIG_NET_FLOW_LIMIT
312 : : {
313 : : .procname = "flow_limit_cpu_bitmap",
314 : : .mode = 0644,
315 : : .proc_handler = flow_limit_cpu_sysctl
316 : : },
317 : : {
318 : : .procname = "flow_limit_table_len",
319 : : .data = &netdev_flow_limit_table_len,
320 : : .maxlen = sizeof(int),
321 : : .mode = 0644,
322 : : .proc_handler = flow_limit_table_len_sysctl
323 : : },
324 : : #endif /* CONFIG_NET_FLOW_LIMIT */
325 : : #ifdef CONFIG_NET_RX_BUSY_POLL
326 : : {
327 : : .procname = "busy_poll",
328 : : .data = &sysctl_net_busy_poll,
329 : : .maxlen = sizeof(unsigned int),
330 : : .mode = 0644,
331 : : .proc_handler = proc_dointvec
332 : : },
333 : : {
334 : : .procname = "busy_read",
335 : : .data = &sysctl_net_busy_read,
336 : : .maxlen = sizeof(unsigned int),
337 : : .mode = 0644,
338 : : .proc_handler = proc_dointvec
339 : : },
340 : : #endif
341 : : #ifdef CONFIG_NET_SCHED
342 : : {
343 : : .procname = "default_qdisc",
344 : : .mode = 0644,
345 : : .maxlen = IFNAMSIZ,
346 : : .proc_handler = set_default_qdisc
347 : : },
348 : : #endif
349 : : #endif /* CONFIG_NET */
350 : : {
351 : : .procname = "netdev_budget",
352 : : .data = &netdev_budget,
353 : : .maxlen = sizeof(int),
354 : : .mode = 0644,
355 : : .proc_handler = proc_dointvec
356 : : },
357 : : {
358 : : .procname = "warnings",
359 : : .data = &net_msg_warn,
360 : : .maxlen = sizeof(int),
361 : : .mode = 0644,
362 : : .proc_handler = proc_dointvec
363 : : },
364 : : { }
365 : : };
366 : :
367 : : static struct ctl_table netns_core_table[] = {
368 : : {
369 : : .procname = "somaxconn",
370 : : .data = &init_net.core.sysctl_somaxconn,
371 : : .maxlen = sizeof(int),
372 : : .mode = 0644,
373 : : .extra1 = &zero,
374 : : .extra2 = &ushort_max,
375 : : .proc_handler = proc_dointvec_minmax
376 : : },
377 : : { }
378 : : };
379 : :
380 : 0 : static __net_init int sysctl_core_net_init(struct net *net)
381 : : {
382 : : struct ctl_table *tbl;
383 : :
384 : 0 : net->core.sysctl_somaxconn = SOMAXCONN;
385 : :
386 : : tbl = netns_core_table;
387 : : if (!net_eq(net, &init_net)) {
388 : : tbl = kmemdup(tbl, sizeof(netns_core_table), GFP_KERNEL);
389 : : if (tbl == NULL)
390 : : goto err_dup;
391 : :
392 : : tbl[0].data = &net->core.sysctl_somaxconn;
393 : :
394 : : /* Don't export any sysctls to unprivileged users */
395 : : if (net->user_ns != &init_user_ns) {
396 : : tbl[0].procname = NULL;
397 : : }
398 : : }
399 : :
400 : 0 : net->core.sysctl_hdr = register_net_sysctl(net, "net/core", tbl);
401 [ # # ]: 0 : if (net->core.sysctl_hdr == NULL)
402 : : goto err_reg;
403 : :
404 : : return 0;
405 : :
406 : : err_reg:
407 : : if (tbl != netns_core_table)
408 : : kfree(tbl);
409 : : err_dup:
410 : : return -ENOMEM;
411 : : }
412 : :
413 : 0 : static __net_exit void sysctl_core_net_exit(struct net *net)
414 : : {
415 : : struct ctl_table *tbl;
416 : :
417 : 0 : tbl = net->core.sysctl_hdr->ctl_table_arg;
418 : 0 : unregister_net_sysctl_table(net->core.sysctl_hdr);
419 [ # # ]: 0 : BUG_ON(tbl == netns_core_table);
420 : 0 : kfree(tbl);
421 : 0 : }
422 : :
423 : : static __net_initdata struct pernet_operations sysctl_core_ops = {
424 : : .init = sysctl_core_net_init,
425 : : .exit = sysctl_core_net_exit,
426 : : };
427 : :
428 : 0 : static __init int sysctl_core_init(void)
429 : : {
430 : 0 : register_net_sysctl(&init_net, "net/core", net_core_table);
431 : 0 : return register_pernet_subsys(&sysctl_core_ops);
432 : : }
433 : :
434 : : fs_initcall(sysctl_core_init);
|