139732acdSEric W. Biederman /* 239732acdSEric W. Biederman * Copyright (C) 2007 339732acdSEric W. Biederman * 439732acdSEric W. Biederman * Author: Eric Biederman <ebiederm@xmision.com> 539732acdSEric W. Biederman * 639732acdSEric W. Biederman * This program is free software; you can redistribute it and/or 739732acdSEric W. Biederman * modify it under the terms of the GNU General Public License as 839732acdSEric W. Biederman * published by the Free Software Foundation, version 2 of the 939732acdSEric W. Biederman * License. 1039732acdSEric W. Biederman */ 1139732acdSEric W. Biederman 129984de1aSPaul Gortmaker #include <linux/export.h> 1339732acdSEric W. Biederman #include <linux/uts.h> 1439732acdSEric W. Biederman #include <linux/utsname.h> 1539732acdSEric W. Biederman #include <linux/sysctl.h> 16f1ecf068SLucas De Marchi #include <linux/wait.h> 17cd9c513bSIngo Molnar #include <linux/rwsem.h> 1839732acdSEric W. Biederman 19cd89f46bSYuanhan Liu #ifdef CONFIG_PROC_SYSCTL 20cd89f46bSYuanhan Liu 21*42a0cc34SJann Horn static void *get_uts(struct ctl_table *table) 2239732acdSEric W. Biederman { 2339732acdSEric W. Biederman char *which = table->data; 2432df81cbSPavel Emelyanov struct uts_namespace *uts_ns; 2532df81cbSPavel Emelyanov 2632df81cbSPavel Emelyanov uts_ns = current->nsproxy->uts_ns; 2732df81cbSPavel Emelyanov which = (which - (char *)&init_uts_ns) + (char *)uts_ns; 287d69a1f4SCedric Le Goater 2939732acdSEric W. Biederman return which; 3039732acdSEric W. Biederman } 3139732acdSEric W. Biederman 3239732acdSEric W. Biederman /* 3339732acdSEric W. Biederman * Special case of dostring for the UTS structure. This has locks 3439732acdSEric W. Biederman * to observe. Should this be in kernel/sys.c ???? 3539732acdSEric W. Biederman */ 366f8fd1d7SJoe Perches static int proc_do_uts_string(struct ctl_table *table, int write, 3739732acdSEric W. Biederman void __user *buffer, size_t *lenp, loff_t *ppos) 3839732acdSEric W. Biederman { 3939732acdSEric W. Biederman struct ctl_table uts_table; 4039732acdSEric W. Biederman int r; 41*42a0cc34SJann Horn char tmp_data[__NEW_UTS_LEN + 1]; 42f1ecf068SLucas De Marchi 43*42a0cc34SJann Horn memcpy(&uts_table, table, sizeof(uts_table)); 44*42a0cc34SJann Horn uts_table.data = tmp_data; 45*42a0cc34SJann Horn 46*42a0cc34SJann Horn /* 47*42a0cc34SJann Horn * Buffer the value in tmp_data so that proc_dostring() can be called 48*42a0cc34SJann Horn * without holding any locks. 49*42a0cc34SJann Horn * We also need to read the original value in the write==1 case to 50*42a0cc34SJann Horn * support partial writes. 51*42a0cc34SJann Horn */ 52*42a0cc34SJann Horn down_read(&uts_sem); 53*42a0cc34SJann Horn memcpy(tmp_data, get_uts(table), sizeof(tmp_data)); 54*42a0cc34SJann Horn up_read(&uts_sem); 55*42a0cc34SJann Horn r = proc_dostring(&uts_table, write, buffer, lenp, ppos); 56*42a0cc34SJann Horn 57*42a0cc34SJann Horn if (write) { 58*42a0cc34SJann Horn /* 59*42a0cc34SJann Horn * Write back the new value. 60*42a0cc34SJann Horn * Note that, since we dropped uts_sem, the result can 61*42a0cc34SJann Horn * theoretically be incorrect if there are two parallel writes 62*42a0cc34SJann Horn * at non-zero offsets to the same sysctl. 63*42a0cc34SJann Horn */ 64*42a0cc34SJann Horn down_write(&uts_sem); 65*42a0cc34SJann Horn memcpy(get_uts(table), tmp_data, sizeof(tmp_data)); 66*42a0cc34SJann Horn up_write(&uts_sem); 67f1ecf068SLucas De Marchi proc_sys_poll_notify(table->poll); 68*42a0cc34SJann Horn } 69f1ecf068SLucas De Marchi 7039732acdSEric W. Biederman return r; 7139732acdSEric W. Biederman } 7239732acdSEric W. Biederman #else 7339732acdSEric W. Biederman #define proc_do_uts_string NULL 7439732acdSEric W. Biederman #endif 7539732acdSEric W. Biederman 76f1ecf068SLucas De Marchi static DEFINE_CTL_TABLE_POLL(hostname_poll); 77f1ecf068SLucas De Marchi static DEFINE_CTL_TABLE_POLL(domainname_poll); 78f1ecf068SLucas De Marchi 7939732acdSEric W. Biederman static struct ctl_table uts_kern_table[] = { 8039732acdSEric W. Biederman { 8139732acdSEric W. Biederman .procname = "ostype", 8239732acdSEric W. Biederman .data = init_uts_ns.name.sysname, 8339732acdSEric W. Biederman .maxlen = sizeof(init_uts_ns.name.sysname), 8439732acdSEric W. Biederman .mode = 0444, 8539732acdSEric W. Biederman .proc_handler = proc_do_uts_string, 8639732acdSEric W. Biederman }, 8739732acdSEric W. Biederman { 8839732acdSEric W. Biederman .procname = "osrelease", 8939732acdSEric W. Biederman .data = init_uts_ns.name.release, 9039732acdSEric W. Biederman .maxlen = sizeof(init_uts_ns.name.release), 9139732acdSEric W. Biederman .mode = 0444, 9239732acdSEric W. Biederman .proc_handler = proc_do_uts_string, 9339732acdSEric W. Biederman }, 9439732acdSEric W. Biederman { 9539732acdSEric W. Biederman .procname = "version", 9639732acdSEric W. Biederman .data = init_uts_ns.name.version, 9739732acdSEric W. Biederman .maxlen = sizeof(init_uts_ns.name.version), 9839732acdSEric W. Biederman .mode = 0444, 9939732acdSEric W. Biederman .proc_handler = proc_do_uts_string, 10039732acdSEric W. Biederman }, 10139732acdSEric W. Biederman { 10239732acdSEric W. Biederman .procname = "hostname", 10339732acdSEric W. Biederman .data = init_uts_ns.name.nodename, 10439732acdSEric W. Biederman .maxlen = sizeof(init_uts_ns.name.nodename), 10539732acdSEric W. Biederman .mode = 0644, 10639732acdSEric W. Biederman .proc_handler = proc_do_uts_string, 107f1ecf068SLucas De Marchi .poll = &hostname_poll, 10839732acdSEric W. Biederman }, 10939732acdSEric W. Biederman { 11039732acdSEric W. Biederman .procname = "domainname", 11139732acdSEric W. Biederman .data = init_uts_ns.name.domainname, 11239732acdSEric W. Biederman .maxlen = sizeof(init_uts_ns.name.domainname), 11339732acdSEric W. Biederman .mode = 0644, 11439732acdSEric W. Biederman .proc_handler = proc_do_uts_string, 115f1ecf068SLucas De Marchi .poll = &domainname_poll, 11639732acdSEric W. Biederman }, 11739732acdSEric W. Biederman {} 11839732acdSEric W. Biederman }; 11939732acdSEric W. Biederman 12039732acdSEric W. Biederman static struct ctl_table uts_root_table[] = { 12139732acdSEric W. Biederman { 12239732acdSEric W. Biederman .procname = "kernel", 12339732acdSEric W. Biederman .mode = 0555, 12439732acdSEric W. Biederman .child = uts_kern_table, 12539732acdSEric W. Biederman }, 12639732acdSEric W. Biederman {} 12739732acdSEric W. Biederman }; 12839732acdSEric W. Biederman 129f1ecf068SLucas De Marchi #ifdef CONFIG_PROC_SYSCTL 130f1ecf068SLucas De Marchi /* 131f1ecf068SLucas De Marchi * Notify userspace about a change in a certain entry of uts_kern_table, 132f1ecf068SLucas De Marchi * identified by the parameter proc. 133f1ecf068SLucas De Marchi */ 134f1ecf068SLucas De Marchi void uts_proc_notify(enum uts_proc proc) 135f1ecf068SLucas De Marchi { 136f1ecf068SLucas De Marchi struct ctl_table *table = &uts_kern_table[proc]; 137f1ecf068SLucas De Marchi 138f1ecf068SLucas De Marchi proc_sys_poll_notify(table->poll); 139f1ecf068SLucas De Marchi } 140f1ecf068SLucas De Marchi #endif 141f1ecf068SLucas De Marchi 14239732acdSEric W. Biederman static int __init utsname_sysctl_init(void) 14339732acdSEric W. Biederman { 1440b4d4147SEric W. Biederman register_sysctl_table(uts_root_table); 14539732acdSEric W. Biederman return 0; 14639732acdSEric W. Biederman } 14739732acdSEric W. Biederman 14895583e4aSFabian Frederick device_initcall(utsname_sysctl_init); 149