Branch data Line data Source code
1 : : /* -*- linux-c -*-
2 : : * sysctl_net.c: sysctl interface to net subsystem.
3 : : *
4 : : * Begun April 1, 1996, Mike Shaver.
5 : : * Added /proc/sys/net directories for each protocol family. [MS]
6 : : *
7 : : * Revision 1.2 1996/05/08 20:24:40 shaver
8 : : * Added bits for NET_BRIDGE and the NET_IPV4_ARP stuff and
9 : : * NET_IPV4_IP_FORWARD.
10 : : *
11 : : *
12 : : */
13 : :
14 : : #include <linux/mm.h>
15 : : #include <linux/export.h>
16 : : #include <linux/sysctl.h>
17 : : #include <linux/nsproxy.h>
18 : :
19 : : #include <net/sock.h>
20 : :
21 : : #ifdef CONFIG_INET
22 : : #include <net/ip.h>
23 : : #endif
24 : :
25 : : #ifdef CONFIG_NET
26 : : #include <linux/if_ether.h>
27 : : #endif
28 : :
29 : : static struct ctl_table_set *
30 : 0 : net_ctl_header_lookup(struct ctl_table_root *root, struct nsproxy *namespaces)
31 : : {
32 : 5 : return &namespaces->net_ns->sysctls;
33 : : }
34 : :
35 : 0 : static int is_seen(struct ctl_table_set *set)
36 : : {
37 : 4147 : return ¤t->nsproxy->net_ns->sysctls == set;
38 : : }
39 : :
40 : : /* Return standard mode bits for table entry. */
41 : 0 : static int net_ctl_permissions(struct ctl_table_header *head,
42 : : struct ctl_table *table)
43 : : {
44 : 4667 : struct net *net = container_of(head->set, struct net, sysctls);
45 : : kuid_t root_uid = make_kuid(net->user_ns, 0);
46 : : kgid_t root_gid = make_kgid(net->user_ns, 0);
47 : :
48 : : /* Allow network administrator to have same access as root. */
49 [ - + ][ # # ]: 4667 : if (ns_capable(net->user_ns, CAP_NET_ADMIN) ||
50 : 0 : uid_eq(root_uid, current_euid())) {
51 : 4667 : int mode = (table->mode >> 6) & 7;
52 : 4667 : return (mode << 6) | (mode << 3) | mode;
53 : : }
54 : : /* Allow netns root group to have the same access as the root group */
55 [ # # ]: 0 : if (in_egroup_p(root_gid)) {
56 : 0 : int mode = (table->mode >> 3) & 7;
57 : 0 : return (mode << 3) | mode;
58 : : }
59 : 0 : return table->mode;
60 : : }
61 : :
62 : : static struct ctl_table_root net_sysctl_root = {
63 : : .lookup = net_ctl_header_lookup,
64 : : .permissions = net_ctl_permissions,
65 : : };
66 : :
67 : 0 : static int __net_init sysctl_net_init(struct net *net)
68 : : {
69 : 0 : setup_sysctl_set(&net->sysctls, &net_sysctl_root, is_seen);
70 : 0 : return 0;
71 : : }
72 : :
73 : 0 : static void __net_exit sysctl_net_exit(struct net *net)
74 : : {
75 : 0 : retire_sysctl_set(&net->sysctls);
76 : 0 : }
77 : :
78 : : static struct pernet_operations sysctl_pernet_ops = {
79 : : .init = sysctl_net_init,
80 : : .exit = sysctl_net_exit,
81 : : };
82 : :
83 : : static struct ctl_table_header *net_header;
84 : 0 : __init int net_sysctl_init(void)
85 : : {
86 : : static struct ctl_table empty[1];
87 : : int ret = -ENOMEM;
88 : : /* Avoid limitations in the sysctl implementation by
89 : : * registering "/proc/sys/net" as an empty directory not in a
90 : : * network namespace.
91 : : */
92 : 0 : net_header = register_sysctl("net", empty);
93 [ # # ]: 0 : if (!net_header)
94 : : goto out;
95 : 0 : ret = register_pernet_subsys(&sysctl_pernet_ops);
96 [ # # ]: 0 : if (ret)
97 : : goto out;
98 : 0 : register_sysctl_root(&net_sysctl_root);
99 : : out:
100 : 0 : return ret;
101 : : }
102 : :
103 : 0 : struct ctl_table_header *register_net_sysctl(struct net *net,
104 : : const char *path, struct ctl_table *table)
105 : : {
106 : 0 : return __register_sysctl_table(&net->sysctls, path, table);
107 : : }
108 : : EXPORT_SYMBOL_GPL(register_net_sysctl);
109 : :
110 : 0 : void unregister_net_sysctl_table(struct ctl_table_header *header)
111 : : {
112 : 0 : unregister_sysctl_table(header);
113 : 0 : }
114 : : EXPORT_SYMBOL_GPL(unregister_net_sysctl_table);
|