18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* -*- linux-c -*- 38c2ecf20Sopenharmony_ci * sysctl_net.c: sysctl interface to net subsystem. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Begun April 1, 1996, Mike Shaver. 68c2ecf20Sopenharmony_ci * Added /proc/sys/net directories for each protocol family. [MS] 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Revision 1.2 1996/05/08 20:24:40 shaver 98c2ecf20Sopenharmony_ci * Added bits for NET_BRIDGE and the NET_IPV4_ARP stuff and 108c2ecf20Sopenharmony_ci * NET_IPV4_IP_FORWARD. 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <linux/mm.h> 168c2ecf20Sopenharmony_ci#include <linux/export.h> 178c2ecf20Sopenharmony_ci#include <linux/sysctl.h> 188c2ecf20Sopenharmony_ci#include <linux/nsproxy.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include <net/sock.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#ifdef CONFIG_INET 238c2ecf20Sopenharmony_ci#include <net/ip.h> 248c2ecf20Sopenharmony_ci#endif 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#ifdef CONFIG_NET 278c2ecf20Sopenharmony_ci#include <linux/if_ether.h> 288c2ecf20Sopenharmony_ci#endif 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistatic struct ctl_table_set * 318c2ecf20Sopenharmony_cinet_ctl_header_lookup(struct ctl_table_root *root) 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci return ¤t->nsproxy->net_ns->sysctls; 348c2ecf20Sopenharmony_ci} 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic int is_seen(struct ctl_table_set *set) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci return ¤t->nsproxy->net_ns->sysctls == set; 398c2ecf20Sopenharmony_ci} 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci/* Return standard mode bits for table entry. */ 428c2ecf20Sopenharmony_cistatic int net_ctl_permissions(struct ctl_table_header *head, 438c2ecf20Sopenharmony_ci struct ctl_table *table) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci struct net *net = container_of(head->set, struct net, sysctls); 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci /* Allow network administrator to have same access as root. */ 488c2ecf20Sopenharmony_ci if (ns_capable_noaudit(net->user_ns, CAP_NET_ADMIN)) { 498c2ecf20Sopenharmony_ci int mode = (table->mode >> 6) & 7; 508c2ecf20Sopenharmony_ci return (mode << 6) | (mode << 3) | mode; 518c2ecf20Sopenharmony_ci } 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci return table->mode; 548c2ecf20Sopenharmony_ci} 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cistatic void net_ctl_set_ownership(struct ctl_table_header *head, 578c2ecf20Sopenharmony_ci struct ctl_table *table, 588c2ecf20Sopenharmony_ci kuid_t *uid, kgid_t *gid) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci struct net *net = container_of(head->set, struct net, sysctls); 618c2ecf20Sopenharmony_ci kuid_t ns_root_uid; 628c2ecf20Sopenharmony_ci kgid_t ns_root_gid; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci ns_root_uid = make_kuid(net->user_ns, 0); 658c2ecf20Sopenharmony_ci if (uid_valid(ns_root_uid)) 668c2ecf20Sopenharmony_ci *uid = ns_root_uid; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci ns_root_gid = make_kgid(net->user_ns, 0); 698c2ecf20Sopenharmony_ci if (gid_valid(ns_root_gid)) 708c2ecf20Sopenharmony_ci *gid = ns_root_gid; 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistatic struct ctl_table_root net_sysctl_root = { 748c2ecf20Sopenharmony_ci .lookup = net_ctl_header_lookup, 758c2ecf20Sopenharmony_ci .permissions = net_ctl_permissions, 768c2ecf20Sopenharmony_ci .set_ownership = net_ctl_set_ownership, 778c2ecf20Sopenharmony_ci}; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistatic int __net_init sysctl_net_init(struct net *net) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci setup_sysctl_set(&net->sysctls, &net_sysctl_root, is_seen); 828c2ecf20Sopenharmony_ci return 0; 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistatic void __net_exit sysctl_net_exit(struct net *net) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci retire_sysctl_set(&net->sysctls); 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic struct pernet_operations sysctl_pernet_ops = { 918c2ecf20Sopenharmony_ci .init = sysctl_net_init, 928c2ecf20Sopenharmony_ci .exit = sysctl_net_exit, 938c2ecf20Sopenharmony_ci}; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic struct ctl_table_header *net_header; 968c2ecf20Sopenharmony_ci__init int net_sysctl_init(void) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci static struct ctl_table empty[1]; 998c2ecf20Sopenharmony_ci int ret = -ENOMEM; 1008c2ecf20Sopenharmony_ci /* Avoid limitations in the sysctl implementation by 1018c2ecf20Sopenharmony_ci * registering "/proc/sys/net" as an empty directory not in a 1028c2ecf20Sopenharmony_ci * network namespace. 1038c2ecf20Sopenharmony_ci */ 1048c2ecf20Sopenharmony_ci net_header = register_sysctl("net", empty); 1058c2ecf20Sopenharmony_ci if (!net_header) 1068c2ecf20Sopenharmony_ci goto out; 1078c2ecf20Sopenharmony_ci ret = register_pernet_subsys(&sysctl_pernet_ops); 1088c2ecf20Sopenharmony_ci if (ret) 1098c2ecf20Sopenharmony_ci goto out1; 1108c2ecf20Sopenharmony_ciout: 1118c2ecf20Sopenharmony_ci return ret; 1128c2ecf20Sopenharmony_ciout1: 1138c2ecf20Sopenharmony_ci unregister_sysctl_table(net_header); 1148c2ecf20Sopenharmony_ci net_header = NULL; 1158c2ecf20Sopenharmony_ci goto out; 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_cistruct ctl_table_header *register_net_sysctl(struct net *net, 1198c2ecf20Sopenharmony_ci const char *path, struct ctl_table *table) 1208c2ecf20Sopenharmony_ci{ 1218c2ecf20Sopenharmony_ci return __register_sysctl_table(&net->sysctls, path, table); 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(register_net_sysctl); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_civoid unregister_net_sysctl_table(struct ctl_table_header *header) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci unregister_sysctl_table(header); 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(unregister_net_sysctl_table); 130