Back to home page

LXR

 
 

    


0001 /*
0002  *  Copyright (C) 2007
0003  *
0004  *  Author: Eric Biederman <ebiederm@xmision.com>
0005  *
0006  *  This program is free software; you can redistribute it and/or
0007  *  modify it under the terms of the GNU General Public License as
0008  *  published by the Free Software Foundation, version 2 of the
0009  *  License.
0010  */
0011 
0012 #include <linux/export.h>
0013 #include <linux/uts.h>
0014 #include <linux/utsname.h>
0015 #include <linux/sysctl.h>
0016 #include <linux/wait.h>
0017 
0018 #ifdef CONFIG_PROC_SYSCTL
0019 
0020 static void *get_uts(struct ctl_table *table, int write)
0021 {
0022     char *which = table->data;
0023     struct uts_namespace *uts_ns;
0024 
0025     uts_ns = current->nsproxy->uts_ns;
0026     which = (which - (char *)&init_uts_ns) + (char *)uts_ns;
0027 
0028     if (!write)
0029         down_read(&uts_sem);
0030     else
0031         down_write(&uts_sem);
0032     return which;
0033 }
0034 
0035 static void put_uts(struct ctl_table *table, int write, void *which)
0036 {
0037     if (!write)
0038         up_read(&uts_sem);
0039     else
0040         up_write(&uts_sem);
0041 }
0042 
0043 /*
0044  *  Special case of dostring for the UTS structure. This has locks
0045  *  to observe. Should this be in kernel/sys.c ????
0046  */
0047 static int proc_do_uts_string(struct ctl_table *table, int write,
0048           void __user *buffer, size_t *lenp, loff_t *ppos)
0049 {
0050     struct ctl_table uts_table;
0051     int r;
0052     memcpy(&uts_table, table, sizeof(uts_table));
0053     uts_table.data = get_uts(table, write);
0054     r = proc_dostring(&uts_table, write, buffer, lenp, ppos);
0055     put_uts(table, write, uts_table.data);
0056 
0057     if (write)
0058         proc_sys_poll_notify(table->poll);
0059 
0060     return r;
0061 }
0062 #else
0063 #define proc_do_uts_string NULL
0064 #endif
0065 
0066 static DEFINE_CTL_TABLE_POLL(hostname_poll);
0067 static DEFINE_CTL_TABLE_POLL(domainname_poll);
0068 
0069 static struct ctl_table uts_kern_table[] = {
0070     {
0071         .procname   = "ostype",
0072         .data       = init_uts_ns.name.sysname,
0073         .maxlen     = sizeof(init_uts_ns.name.sysname),
0074         .mode       = 0444,
0075         .proc_handler   = proc_do_uts_string,
0076     },
0077     {
0078         .procname   = "osrelease",
0079         .data       = init_uts_ns.name.release,
0080         .maxlen     = sizeof(init_uts_ns.name.release),
0081         .mode       = 0444,
0082         .proc_handler   = proc_do_uts_string,
0083     },
0084     {
0085         .procname   = "version",
0086         .data       = init_uts_ns.name.version,
0087         .maxlen     = sizeof(init_uts_ns.name.version),
0088         .mode       = 0444,
0089         .proc_handler   = proc_do_uts_string,
0090     },
0091     {
0092         .procname   = "hostname",
0093         .data       = init_uts_ns.name.nodename,
0094         .maxlen     = sizeof(init_uts_ns.name.nodename),
0095         .mode       = 0644,
0096         .proc_handler   = proc_do_uts_string,
0097         .poll       = &hostname_poll,
0098     },
0099     {
0100         .procname   = "domainname",
0101         .data       = init_uts_ns.name.domainname,
0102         .maxlen     = sizeof(init_uts_ns.name.domainname),
0103         .mode       = 0644,
0104         .proc_handler   = proc_do_uts_string,
0105         .poll       = &domainname_poll,
0106     },
0107     {}
0108 };
0109 
0110 static struct ctl_table uts_root_table[] = {
0111     {
0112         .procname   = "kernel",
0113         .mode       = 0555,
0114         .child      = uts_kern_table,
0115     },
0116     {}
0117 };
0118 
0119 #ifdef CONFIG_PROC_SYSCTL
0120 /*
0121  * Notify userspace about a change in a certain entry of uts_kern_table,
0122  * identified by the parameter proc.
0123  */
0124 void uts_proc_notify(enum uts_proc proc)
0125 {
0126     struct ctl_table *table = &uts_kern_table[proc];
0127 
0128     proc_sys_poll_notify(table->poll);
0129 }
0130 #endif
0131 
0132 static int __init utsname_sysctl_init(void)
0133 {
0134     register_sysctl_table(uts_root_table);
0135     return 0;
0136 }
0137 
0138 device_initcall(utsname_sysctl_init);