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> 1139732acdSEric W. Biederman #include <linux/sysctl.h> 12f1ecf068SLucas De Marchi #include <linux/wait.h> 13cd9c513bSIngo Molnar #include <linux/rwsem.h> 1439732acdSEric W. Biederman 15cd89f46bSYuanhan Liu #ifdef CONFIG_PROC_SYSCTL 16cd89f46bSYuanhan Liu 1742a0cc34SJann Horn static void *get_uts(struct ctl_table *table) 1839732acdSEric W. Biederman { 1939732acdSEric W. Biederman char *which = table->data; 2032df81cbSPavel Emelyanov struct uts_namespace *uts_ns; 2132df81cbSPavel Emelyanov 2232df81cbSPavel Emelyanov uts_ns = current->nsproxy->uts_ns; 2332df81cbSPavel Emelyanov which = (which - (char *)&init_uts_ns) + (char *)uts_ns; 247d69a1f4SCedric Le Goater 2539732acdSEric W. Biederman return which; 2639732acdSEric W. Biederman } 2739732acdSEric W. Biederman 2839732acdSEric W. Biederman /* 2939732acdSEric W. Biederman * Special case of dostring for the UTS structure. This has locks 3039732acdSEric W. Biederman * to observe. Should this be in kernel/sys.c ???? 3139732acdSEric W. Biederman */ 326f8fd1d7SJoe Perches static int proc_do_uts_string(struct ctl_table *table, int write, 3332927393SChristoph Hellwig void *buffer, size_t *lenp, loff_t *ppos) 3439732acdSEric W. Biederman { 3539732acdSEric W. Biederman struct ctl_table uts_table; 3639732acdSEric W. Biederman int r; 3742a0cc34SJann Horn char tmp_data[__NEW_UTS_LEN + 1]; 38f1ecf068SLucas De Marchi 3942a0cc34SJann Horn memcpy(&uts_table, table, sizeof(uts_table)); 4042a0cc34SJann Horn uts_table.data = tmp_data; 4142a0cc34SJann Horn 4242a0cc34SJann Horn /* 4342a0cc34SJann Horn * Buffer the value in tmp_data so that proc_dostring() can be called 4442a0cc34SJann Horn * without holding any locks. 4542a0cc34SJann Horn * We also need to read the original value in the write==1 case to 4642a0cc34SJann Horn * support partial writes. 4742a0cc34SJann Horn */ 4842a0cc34SJann Horn down_read(&uts_sem); 4942a0cc34SJann Horn memcpy(tmp_data, get_uts(table), sizeof(tmp_data)); 5042a0cc34SJann Horn up_read(&uts_sem); 5142a0cc34SJann Horn r = proc_dostring(&uts_table, write, buffer, lenp, ppos); 5242a0cc34SJann Horn 5342a0cc34SJann Horn if (write) { 5442a0cc34SJann Horn /* 5542a0cc34SJann Horn * Write back the new value. 5642a0cc34SJann Horn * Note that, since we dropped uts_sem, the result can 5742a0cc34SJann Horn * theoretically be incorrect if there are two parallel writes 5842a0cc34SJann Horn * at non-zero offsets to the same sysctl. 5942a0cc34SJann Horn */ 6042a0cc34SJann Horn down_write(&uts_sem); 6142a0cc34SJann Horn memcpy(get_uts(table), tmp_data, sizeof(tmp_data)); 6242a0cc34SJann Horn up_write(&uts_sem); 63f1ecf068SLucas De Marchi proc_sys_poll_notify(table->poll); 6442a0cc34SJann Horn } 65f1ecf068SLucas De Marchi 6639732acdSEric W. Biederman return r; 6739732acdSEric W. Biederman } 6839732acdSEric W. Biederman #else 6939732acdSEric W. Biederman #define proc_do_uts_string NULL 7039732acdSEric W. Biederman #endif 7139732acdSEric W. Biederman 72f1ecf068SLucas De Marchi static DEFINE_CTL_TABLE_POLL(hostname_poll); 73f1ecf068SLucas De Marchi static DEFINE_CTL_TABLE_POLL(domainname_poll); 74f1ecf068SLucas De Marchi 7539732acdSEric W. Biederman static struct ctl_table uts_kern_table[] = { 7639732acdSEric W. Biederman { 77*bfca3dd3SPetr Vorel .procname = "arch", 78*bfca3dd3SPetr Vorel .data = init_uts_ns.name.machine, 79*bfca3dd3SPetr Vorel .maxlen = sizeof(init_uts_ns.name.machine), 80*bfca3dd3SPetr Vorel .mode = 0444, 81*bfca3dd3SPetr Vorel .proc_handler = proc_do_uts_string, 82*bfca3dd3SPetr Vorel }, 83*bfca3dd3SPetr Vorel { 8439732acdSEric W. Biederman .procname = "ostype", 8539732acdSEric W. Biederman .data = init_uts_ns.name.sysname, 8639732acdSEric W. Biederman .maxlen = sizeof(init_uts_ns.name.sysname), 8739732acdSEric W. Biederman .mode = 0444, 8839732acdSEric W. Biederman .proc_handler = proc_do_uts_string, 8939732acdSEric W. Biederman }, 9039732acdSEric W. Biederman { 9139732acdSEric W. Biederman .procname = "osrelease", 9239732acdSEric W. Biederman .data = init_uts_ns.name.release, 9339732acdSEric W. Biederman .maxlen = sizeof(init_uts_ns.name.release), 9439732acdSEric W. Biederman .mode = 0444, 9539732acdSEric W. Biederman .proc_handler = proc_do_uts_string, 9639732acdSEric W. Biederman }, 9739732acdSEric W. Biederman { 9839732acdSEric W. Biederman .procname = "version", 9939732acdSEric W. Biederman .data = init_uts_ns.name.version, 10039732acdSEric W. Biederman .maxlen = sizeof(init_uts_ns.name.version), 10139732acdSEric W. Biederman .mode = 0444, 10239732acdSEric W. Biederman .proc_handler = proc_do_uts_string, 10339732acdSEric W. Biederman }, 10439732acdSEric W. Biederman { 10539732acdSEric W. Biederman .procname = "hostname", 10639732acdSEric W. Biederman .data = init_uts_ns.name.nodename, 10739732acdSEric W. Biederman .maxlen = sizeof(init_uts_ns.name.nodename), 10839732acdSEric W. Biederman .mode = 0644, 10939732acdSEric W. Biederman .proc_handler = proc_do_uts_string, 110f1ecf068SLucas De Marchi .poll = &hostname_poll, 11139732acdSEric W. Biederman }, 11239732acdSEric W. Biederman { 11339732acdSEric W. Biederman .procname = "domainname", 11439732acdSEric W. Biederman .data = init_uts_ns.name.domainname, 11539732acdSEric W. Biederman .maxlen = sizeof(init_uts_ns.name.domainname), 11639732acdSEric W. Biederman .mode = 0644, 11739732acdSEric W. Biederman .proc_handler = proc_do_uts_string, 118f1ecf068SLucas De Marchi .poll = &domainname_poll, 11939732acdSEric W. Biederman }, 12039732acdSEric W. Biederman {} 12139732acdSEric W. Biederman }; 12239732acdSEric W. Biederman 12339732acdSEric W. Biederman static struct ctl_table uts_root_table[] = { 12439732acdSEric W. Biederman { 12539732acdSEric W. Biederman .procname = "kernel", 12639732acdSEric W. Biederman .mode = 0555, 12739732acdSEric W. Biederman .child = uts_kern_table, 12839732acdSEric W. Biederman }, 12939732acdSEric W. Biederman {} 13039732acdSEric W. Biederman }; 13139732acdSEric W. Biederman 132f1ecf068SLucas De Marchi #ifdef CONFIG_PROC_SYSCTL 133f1ecf068SLucas De Marchi /* 134f1ecf068SLucas De Marchi * Notify userspace about a change in a certain entry of uts_kern_table, 135f1ecf068SLucas De Marchi * identified by the parameter proc. 136f1ecf068SLucas De Marchi */ 137f1ecf068SLucas De Marchi void uts_proc_notify(enum uts_proc proc) 138f1ecf068SLucas De Marchi { 139f1ecf068SLucas De Marchi struct ctl_table *table = &uts_kern_table[proc]; 140f1ecf068SLucas De Marchi 141f1ecf068SLucas De Marchi proc_sys_poll_notify(table->poll); 142f1ecf068SLucas De Marchi } 143f1ecf068SLucas De Marchi #endif 144f1ecf068SLucas De Marchi 14539732acdSEric W. Biederman static int __init utsname_sysctl_init(void) 14639732acdSEric W. Biederman { 1470b4d4147SEric W. Biederman register_sysctl_table(uts_root_table); 14839732acdSEric W. Biederman return 0; 14939732acdSEric W. Biederman } 15039732acdSEric W. Biederman 15195583e4aSFabian Frederick device_initcall(utsname_sysctl_init); 152