1b886d83cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 239732acdSEric W. Biederman /* 339732acdSEric W. Biederman * Copyright (C) 2007 439732acdSEric W. Biederman * 539732acdSEric W. Biederman * Author: Eric Biederman <ebiederm@xmision.com> 639732acdSEric W. Biederman */ 739732acdSEric W. Biederman 89984de1aSPaul Gortmaker #include <linux/export.h> 939732acdSEric W. Biederman #include <linux/uts.h> 1039732acdSEric W. Biederman #include <linux/utsname.h> 11*37608ba3SJason A. Donenfeld #include <linux/random.h> 1239732acdSEric W. Biederman #include <linux/sysctl.h> 13f1ecf068SLucas De Marchi #include <linux/wait.h> 14cd9c513bSIngo Molnar #include <linux/rwsem.h> 1539732acdSEric W. Biederman 16cd89f46bSYuanhan Liu #ifdef CONFIG_PROC_SYSCTL 17cd89f46bSYuanhan Liu 1842a0cc34SJann Horn static void *get_uts(struct ctl_table *table) 1939732acdSEric W. Biederman { 2039732acdSEric W. Biederman char *which = table->data; 2132df81cbSPavel Emelyanov struct uts_namespace *uts_ns; 2232df81cbSPavel Emelyanov 2332df81cbSPavel Emelyanov uts_ns = current->nsproxy->uts_ns; 2432df81cbSPavel Emelyanov which = (which - (char *)&init_uts_ns) + (char *)uts_ns; 257d69a1f4SCedric Le Goater 2639732acdSEric W. Biederman return which; 2739732acdSEric W. Biederman } 2839732acdSEric W. Biederman 2939732acdSEric W. Biederman /* 3039732acdSEric W. Biederman * Special case of dostring for the UTS structure. This has locks 3139732acdSEric W. Biederman * to observe. Should this be in kernel/sys.c ???? 3239732acdSEric W. Biederman */ 336f8fd1d7SJoe Perches static int proc_do_uts_string(struct ctl_table *table, int write, 3432927393SChristoph Hellwig void *buffer, size_t *lenp, loff_t *ppos) 3539732acdSEric W. Biederman { 3639732acdSEric W. Biederman struct ctl_table uts_table; 3739732acdSEric W. Biederman int r; 3842a0cc34SJann Horn char tmp_data[__NEW_UTS_LEN + 1]; 39f1ecf068SLucas De Marchi 4042a0cc34SJann Horn memcpy(&uts_table, table, sizeof(uts_table)); 4142a0cc34SJann Horn uts_table.data = tmp_data; 4242a0cc34SJann Horn 4342a0cc34SJann Horn /* 4442a0cc34SJann Horn * Buffer the value in tmp_data so that proc_dostring() can be called 4542a0cc34SJann Horn * without holding any locks. 4642a0cc34SJann Horn * We also need to read the original value in the write==1 case to 4742a0cc34SJann Horn * support partial writes. 4842a0cc34SJann Horn */ 4942a0cc34SJann Horn down_read(&uts_sem); 5042a0cc34SJann Horn memcpy(tmp_data, get_uts(table), sizeof(tmp_data)); 5142a0cc34SJann Horn up_read(&uts_sem); 5242a0cc34SJann Horn r = proc_dostring(&uts_table, write, buffer, lenp, ppos); 5342a0cc34SJann Horn 5442a0cc34SJann Horn if (write) { 5542a0cc34SJann Horn /* 5642a0cc34SJann Horn * Write back the new value. 5742a0cc34SJann Horn * Note that, since we dropped uts_sem, the result can 5842a0cc34SJann Horn * theoretically be incorrect if there are two parallel writes 5942a0cc34SJann Horn * at non-zero offsets to the same sysctl. 6042a0cc34SJann Horn */ 61*37608ba3SJason A. Donenfeld add_device_randomness(tmp_data, sizeof(tmp_data)); 6242a0cc34SJann Horn down_write(&uts_sem); 6342a0cc34SJann Horn memcpy(get_uts(table), tmp_data, sizeof(tmp_data)); 6442a0cc34SJann Horn up_write(&uts_sem); 65f1ecf068SLucas De Marchi proc_sys_poll_notify(table->poll); 6642a0cc34SJann Horn } 67f1ecf068SLucas De Marchi 6839732acdSEric W. Biederman return r; 6939732acdSEric W. Biederman } 7039732acdSEric W. Biederman #else 7139732acdSEric W. Biederman #define proc_do_uts_string NULL 7239732acdSEric W. Biederman #endif 7339732acdSEric W. Biederman 74f1ecf068SLucas De Marchi static DEFINE_CTL_TABLE_POLL(hostname_poll); 75f1ecf068SLucas De Marchi static DEFINE_CTL_TABLE_POLL(domainname_poll); 76f1ecf068SLucas De Marchi 7739732acdSEric W. Biederman static struct ctl_table uts_kern_table[] = { 7839732acdSEric W. Biederman { 7939732acdSEric W. Biederman .procname = "ostype", 8039732acdSEric W. Biederman .data = init_uts_ns.name.sysname, 8139732acdSEric W. Biederman .maxlen = sizeof(init_uts_ns.name.sysname), 8239732acdSEric W. Biederman .mode = 0444, 8339732acdSEric W. Biederman .proc_handler = proc_do_uts_string, 8439732acdSEric W. Biederman }, 8539732acdSEric W. Biederman { 8639732acdSEric W. Biederman .procname = "osrelease", 8739732acdSEric W. Biederman .data = init_uts_ns.name.release, 8839732acdSEric W. Biederman .maxlen = sizeof(init_uts_ns.name.release), 8939732acdSEric W. Biederman .mode = 0444, 9039732acdSEric W. Biederman .proc_handler = proc_do_uts_string, 9139732acdSEric W. Biederman }, 9239732acdSEric W. Biederman { 9339732acdSEric W. Biederman .procname = "version", 9439732acdSEric W. Biederman .data = init_uts_ns.name.version, 9539732acdSEric W. Biederman .maxlen = sizeof(init_uts_ns.name.version), 9639732acdSEric W. Biederman .mode = 0444, 9739732acdSEric W. Biederman .proc_handler = proc_do_uts_string, 9839732acdSEric W. Biederman }, 9939732acdSEric W. Biederman { 10039732acdSEric W. Biederman .procname = "hostname", 10139732acdSEric W. Biederman .data = init_uts_ns.name.nodename, 10239732acdSEric W. Biederman .maxlen = sizeof(init_uts_ns.name.nodename), 10339732acdSEric W. Biederman .mode = 0644, 10439732acdSEric W. Biederman .proc_handler = proc_do_uts_string, 105f1ecf068SLucas De Marchi .poll = &hostname_poll, 10639732acdSEric W. Biederman }, 10739732acdSEric W. Biederman { 10839732acdSEric W. Biederman .procname = "domainname", 10939732acdSEric W. Biederman .data = init_uts_ns.name.domainname, 11039732acdSEric W. Biederman .maxlen = sizeof(init_uts_ns.name.domainname), 11139732acdSEric W. Biederman .mode = 0644, 11239732acdSEric W. Biederman .proc_handler = proc_do_uts_string, 113f1ecf068SLucas De Marchi .poll = &domainname_poll, 11439732acdSEric W. Biederman }, 11539732acdSEric W. Biederman {} 11639732acdSEric W. Biederman }; 11739732acdSEric W. Biederman 11839732acdSEric W. Biederman static struct ctl_table uts_root_table[] = { 11939732acdSEric W. Biederman { 12039732acdSEric W. Biederman .procname = "kernel", 12139732acdSEric W. Biederman .mode = 0555, 12239732acdSEric W. Biederman .child = uts_kern_table, 12339732acdSEric W. Biederman }, 12439732acdSEric W. Biederman {} 12539732acdSEric W. Biederman }; 12639732acdSEric W. Biederman 127f1ecf068SLucas De Marchi #ifdef CONFIG_PROC_SYSCTL 128f1ecf068SLucas De Marchi /* 129f1ecf068SLucas De Marchi * Notify userspace about a change in a certain entry of uts_kern_table, 130f1ecf068SLucas De Marchi * identified by the parameter proc. 131f1ecf068SLucas De Marchi */ 132f1ecf068SLucas De Marchi void uts_proc_notify(enum uts_proc proc) 133f1ecf068SLucas De Marchi { 134f1ecf068SLucas De Marchi struct ctl_table *table = &uts_kern_table[proc]; 135f1ecf068SLucas De Marchi 136f1ecf068SLucas De Marchi proc_sys_poll_notify(table->poll); 137f1ecf068SLucas De Marchi } 138f1ecf068SLucas De Marchi #endif 139f1ecf068SLucas De Marchi 14039732acdSEric W. Biederman static int __init utsname_sysctl_init(void) 14139732acdSEric W. Biederman { 1420b4d4147SEric W. Biederman register_sysctl_table(uts_root_table); 14339732acdSEric W. Biederman return 0; 14439732acdSEric W. Biederman } 14539732acdSEric W. Biederman 14695583e4aSFabian Frederick device_initcall(utsname_sysctl_init); 147