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