Blame view

net/sysctl_net.c 4.37 KB
457c89965   Thomas Gleixner   treewide: Add SPD...
1
  // SPDX-License-Identifier: GPL-2.0-only
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
  /* -*- linux-c -*-
   * sysctl_net.c: sysctl interface to net subsystem.
   *
   * Begun April 1, 1996, Mike Shaver.
   * Added /proc/sys/net directories for each protocol family. [MS]
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
11
12
13
   * Revision 1.2  1996/05/08  20:24:40  shaver
   * Added bits for NET_BRIDGE and the NET_IPV4_ARP stuff and
   * NET_IPV4_IP_FORWARD.
   *
   *
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
  #include <linux/mm.h>
bc3b2d7fb   Paul Gortmaker   net: Add export.h...
15
  #include <linux/export.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
  #include <linux/sysctl.h>
95bdfccb2   Eric W. Biederman   [NET]: Implement ...
17
  #include <linux/nsproxy.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18

496a22b08   Russell King   [NET]: Fix "sysct...
19
  #include <net/sock.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
  #ifdef CONFIG_INET
20380731b   Arnaldo Carvalho de Melo   [NET]: Fix sparse...
21
  #include <net/ip.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
  #ifdef CONFIG_NET
20380731b   Arnaldo Carvalho de Melo   [NET]: Fix sparse...
24
  #include <linux/if_ether.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
  #endif
734550921   Al Viro   [PATCH] beginning...
26
  static struct ctl_table_set *
13bcc6a28   Eric W. Biederman   sysctl: Stop impl...
27
  net_ctl_header_lookup(struct ctl_table_root *root)
95bdfccb2   Eric W. Biederman   [NET]: Implement ...
28
  {
13bcc6a28   Eric W. Biederman   sysctl: Stop impl...
29
  	return &current->nsproxy->net_ns->sysctls;
734550921   Al Viro   [PATCH] beginning...
30
31
32
33
34
  }
  
  static int is_seen(struct ctl_table_set *set)
  {
  	return &current->nsproxy->net_ns->sysctls == set;
95bdfccb2   Eric W. Biederman   [NET]: Implement ...
35
  }
4ecb90090   Stephen Hemminger   sysctl: allow ove...
36
  /* Return standard mode bits for table entry. */
73f7ef435   Eric W. Biederman   sysctl: Pass usef...
37
  static int net_ctl_permissions(struct ctl_table_header *head,
4ecb90090   Stephen Hemminger   sysctl: allow ove...
38
39
  			       struct ctl_table *table)
  {
cff109768   Eric W. Biederman   net: Update the p...
40
  	struct net *net = container_of(head->set, struct net, sysctls);
cff109768   Eric W. Biederman   net: Update the p...
41

4ecb90090   Stephen Hemminger   sysctl: allow ove...
42
  	/* Allow network administrator to have same access as root. */
d6169b020   Tyler Hicks   net: Use ns_capab...
43
  	if (ns_capable_noaudit(net->user_ns, CAP_NET_ADMIN)) {
4ecb90090   Stephen Hemminger   sysctl: allow ove...
44
45
46
  		int mode = (table->mode >> 6) & 7;
  		return (mode << 6) | (mode << 3) | mode;
  	}
e79c6a4fc   Dmitry Torokhov   net: make net nam...
47

4ecb90090   Stephen Hemminger   sysctl: allow ove...
48
49
  	return table->mode;
  }
e79c6a4fc   Dmitry Torokhov   net: make net nam...
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
  static void net_ctl_set_ownership(struct ctl_table_header *head,
  				  struct ctl_table *table,
  				  kuid_t *uid, kgid_t *gid)
  {
  	struct net *net = container_of(head->set, struct net, sysctls);
  	kuid_t ns_root_uid;
  	kgid_t ns_root_gid;
  
  	ns_root_uid = make_kuid(net->user_ns, 0);
  	if (uid_valid(ns_root_uid))
  		*uid = ns_root_uid;
  
  	ns_root_gid = make_kgid(net->user_ns, 0);
  	if (gid_valid(ns_root_gid))
  		*gid = ns_root_gid;
  }
95bdfccb2   Eric W. Biederman   [NET]: Implement ...
66
67
  static struct ctl_table_root net_sysctl_root = {
  	.lookup = net_ctl_header_lookup,
4ecb90090   Stephen Hemminger   sysctl: allow ove...
68
  	.permissions = net_ctl_permissions,
e79c6a4fc   Dmitry Torokhov   net: make net nam...
69
  	.set_ownership = net_ctl_set_ownership,
95bdfccb2   Eric W. Biederman   [NET]: Implement ...
70
  };
2c8c1e729   Alexey Dobriyan   net: spread __net...
71
  static int __net_init sysctl_net_init(struct net *net)
95bdfccb2   Eric W. Biederman   [NET]: Implement ...
72
  {
9eb47c26f   Eric W. Biederman   sysctl: Add a roo...
73
  	setup_sysctl_set(&net->sysctls, &net_sysctl_root, is_seen);
95bdfccb2   Eric W. Biederman   [NET]: Implement ...
74
75
  	return 0;
  }
2c8c1e729   Alexey Dobriyan   net: spread __net...
76
  static void __net_exit sysctl_net_exit(struct net *net)
95bdfccb2   Eric W. Biederman   [NET]: Implement ...
77
  {
97324cd80   Eric W. Biederman   sysctl: Implement...
78
  	retire_sysctl_set(&net->sysctls);
95bdfccb2   Eric W. Biederman   [NET]: Implement ...
79
80
81
82
83
84
  }
  
  static struct pernet_operations sysctl_pernet_ops = {
  	.init = sysctl_net_init,
  	.exit = sysctl_net_exit,
  };
bc8a36942   Eric W. Biederman   net sysctl: Regis...
85
  static struct ctl_table_header *net_header;
2ca794e5e   Eric W. Biederman   net sysctl: Initi...
86
  __init int net_sysctl_init(void)
95bdfccb2   Eric W. Biederman   [NET]: Implement ...
87
  {
bc8a36942   Eric W. Biederman   net sysctl: Regis...
88
89
90
91
92
93
94
95
96
  	static struct ctl_table empty[1];
  	int ret = -ENOMEM;
  	/* Avoid limitations in the sysctl implementation by
  	 * registering "/proc/sys/net" as an empty directory not in a
  	 * network namespace.
  	 */
  	net_header = register_sysctl("net", empty);
  	if (!net_header)
  		goto out;
95bdfccb2   Eric W. Biederman   [NET]: Implement ...
97
98
  	ret = register_pernet_subsys(&sysctl_pernet_ops);
  	if (ret)
ce9d9b8e5   Li RongQing   net: sysctl: fix ...
99
  		goto out1;
95bdfccb2   Eric W. Biederman   [NET]: Implement ...
100
101
  out:
  	return ret;
ce9d9b8e5   Li RongQing   net: sysctl: fix ...
102
103
104
105
  out1:
  	unregister_sysctl_table(net_header);
  	net_header = NULL;
  	goto out;
95bdfccb2   Eric W. Biederman   [NET]: Implement ...
106
  }
95bdfccb2   Eric W. Biederman   [NET]: Implement ...
107

31c4d2f16   Jonathon Reinhart   net: Ensure net n...
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
  /* Verify that sysctls for non-init netns are safe by either:
   * 1) being read-only, or
   * 2) having a data pointer which points outside of the global kernel/module
   *    data segment, and rather into the heap where a per-net object was
   *    allocated.
   */
  static void ensure_safe_net_sysctl(struct net *net, const char *path,
  				   struct ctl_table *table)
  {
  	struct ctl_table *ent;
  
  	pr_debug("Registering net sysctl (net %p): %s
  ", net, path);
  	for (ent = table; ent->procname; ent++) {
  		unsigned long addr;
  		const char *where;
  
  		pr_debug("  procname=%s mode=%o proc_handler=%ps data=%p
  ",
  			 ent->procname, ent->mode, ent->proc_handler, ent->data);
  
  		/* If it's not writable inside the netns, then it can't hurt. */
  		if ((ent->mode & 0222) == 0) {
  			pr_debug("    Not writable by anyone
  ");
  			continue;
  		}
  
  		/* Where does data point? */
  		addr = (unsigned long)ent->data;
  		if (is_module_address(addr))
  			where = "module";
  		else if (core_kernel_data(addr))
  			where = "kernel";
  		else
  			continue;
  
  		/* If it is writable and points to kernel/module global
  		 * data, then it's probably a netns leak.
  		 */
  		WARN(1, "sysctl %s/%s: data points to %s global data: %ps
  ",
  		     path, ent->procname, where, ent->data);
  
  		/* Make it "safe" by dropping writable perms */
  		ent->mode &= ~0222;
  	}
  }
ab41a2ca5   Eric W. Biederman   net: Implement re...
156
157
158
  struct ctl_table_header *register_net_sysctl(struct net *net,
  	const char *path, struct ctl_table *table)
  {
31c4d2f16   Jonathon Reinhart   net: Ensure net n...
159
160
  	if (!net_eq(net, &init_net))
  		ensure_safe_net_sysctl(net, path, table);
ab41a2ca5   Eric W. Biederman   net: Implement re...
161
162
163
  	return __register_sysctl_table(&net->sysctls, path, table);
  }
  EXPORT_SYMBOL_GPL(register_net_sysctl);
95bdfccb2   Eric W. Biederman   [NET]: Implement ...
164
165
  void unregister_net_sysctl_table(struct ctl_table_header *header)
  {
ab59859de   Harvey Harrison   net: fix returnin...
166
  	unregister_sysctl_table(header);
95bdfccb2   Eric W. Biederman   [NET]: Implement ...
167
168
  }
  EXPORT_SYMBOL_GPL(unregister_net_sysctl_table);