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> 1137608ba3SJason 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 */ 6137608ba3SJason 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 77*52826d3bSLinus Torvalds // Note: update 'enum uts_proc' to match any changes to this table 7839732acdSEric W. Biederman static struct ctl_table uts_kern_table[] = { 7939732acdSEric W. Biederman { 80bfca3dd3SPetr Vorel .procname = "arch", 81bfca3dd3SPetr Vorel .data = init_uts_ns.name.machine, 82bfca3dd3SPetr Vorel .maxlen = sizeof(init_uts_ns.name.machine), 83bfca3dd3SPetr Vorel .mode = 0444, 84bfca3dd3SPetr Vorel .proc_handler = proc_do_uts_string, 85bfca3dd3SPetr Vorel }, 86bfca3dd3SPetr Vorel { 8739732acdSEric W. Biederman .procname = "ostype", 8839732acdSEric W. Biederman .data = init_uts_ns.name.sysname, 8939732acdSEric W. Biederman .maxlen = sizeof(init_uts_ns.name.sysname), 9039732acdSEric W. Biederman .mode = 0444, 9139732acdSEric W. Biederman .proc_handler = proc_do_uts_string, 9239732acdSEric W. Biederman }, 9339732acdSEric W. Biederman { 9439732acdSEric W. Biederman .procname = "osrelease", 9539732acdSEric W. Biederman .data = init_uts_ns.name.release, 9639732acdSEric W. Biederman .maxlen = sizeof(init_uts_ns.name.release), 9739732acdSEric W. Biederman .mode = 0444, 9839732acdSEric W. Biederman .proc_handler = proc_do_uts_string, 9939732acdSEric W. Biederman }, 10039732acdSEric W. Biederman { 10139732acdSEric W. Biederman .procname = "version", 10239732acdSEric W. Biederman .data = init_uts_ns.name.version, 10339732acdSEric W. Biederman .maxlen = sizeof(init_uts_ns.name.version), 10439732acdSEric W. Biederman .mode = 0444, 10539732acdSEric W. Biederman .proc_handler = proc_do_uts_string, 10639732acdSEric W. Biederman }, 10739732acdSEric W. Biederman { 10839732acdSEric W. Biederman .procname = "hostname", 10939732acdSEric W. Biederman .data = init_uts_ns.name.nodename, 11039732acdSEric W. Biederman .maxlen = sizeof(init_uts_ns.name.nodename), 11139732acdSEric W. Biederman .mode = 0644, 11239732acdSEric W. Biederman .proc_handler = proc_do_uts_string, 113f1ecf068SLucas De Marchi .poll = &hostname_poll, 11439732acdSEric W. Biederman }, 11539732acdSEric W. Biederman { 11639732acdSEric W. Biederman .procname = "domainname", 11739732acdSEric W. Biederman .data = init_uts_ns.name.domainname, 11839732acdSEric W. Biederman .maxlen = sizeof(init_uts_ns.name.domainname), 11939732acdSEric W. Biederman .mode = 0644, 12039732acdSEric W. Biederman .proc_handler = proc_do_uts_string, 121f1ecf068SLucas De Marchi .poll = &domainname_poll, 12239732acdSEric W. Biederman }, 12339732acdSEric W. Biederman {} 12439732acdSEric W. Biederman }; 12539732acdSEric W. Biederman 12639732acdSEric W. Biederman static struct ctl_table uts_root_table[] = { 12739732acdSEric W. Biederman { 12839732acdSEric W. Biederman .procname = "kernel", 12939732acdSEric W. Biederman .mode = 0555, 13039732acdSEric W. Biederman .child = uts_kern_table, 13139732acdSEric W. Biederman }, 13239732acdSEric W. Biederman {} 13339732acdSEric W. Biederman }; 13439732acdSEric W. Biederman 135f1ecf068SLucas De Marchi #ifdef CONFIG_PROC_SYSCTL 136f1ecf068SLucas De Marchi /* 137f1ecf068SLucas De Marchi * Notify userspace about a change in a certain entry of uts_kern_table, 138f1ecf068SLucas De Marchi * identified by the parameter proc. 139f1ecf068SLucas De Marchi */ 140f1ecf068SLucas De Marchi void uts_proc_notify(enum uts_proc proc) 141f1ecf068SLucas De Marchi { 142f1ecf068SLucas De Marchi struct ctl_table *table = &uts_kern_table[proc]; 143f1ecf068SLucas De Marchi 144f1ecf068SLucas De Marchi proc_sys_poll_notify(table->poll); 145f1ecf068SLucas De Marchi } 146f1ecf068SLucas De Marchi #endif 147f1ecf068SLucas De Marchi 14839732acdSEric W. Biederman static int __init utsname_sysctl_init(void) 14939732acdSEric W. Biederman { 1500b4d4147SEric W. Biederman register_sysctl_table(uts_root_table); 15139732acdSEric W. Biederman return 0; 15239732acdSEric W. Biederman } 15339732acdSEric W. Biederman 15495583e4aSFabian Frederick device_initcall(utsname_sysctl_init); 155