Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  Copyright (C) 2007
0004  *
0005  *  Author: Eric Biederman <ebiederm@xmision.com>
0006  */
0007 
0008 #include <linux/export.h>
0009 #include <linux/uts.h>
0010 #include <linux/utsname.h>
0011 #include <linux/sysctl.h>
0012 #include <linux/wait.h>
0013 #include <linux/rwsem.h>
0014 
0015 #ifdef CONFIG_PROC_SYSCTL
0016 
0017 static void *get_uts(struct ctl_table *table)
0018 {
0019     char *which = table->data;
0020     struct uts_namespace *uts_ns;
0021 
0022     uts_ns = current->nsproxy->uts_ns;
0023     which = (which - (char *)&init_uts_ns) + (char *)uts_ns;
0024 
0025     return which;
0026 }
0027 
0028 /*
0029  *  Special case of dostring for the UTS structure. This has locks
0030  *  to observe. Should this be in kernel/sys.c ????
0031  */
0032 static int proc_do_uts_string(struct ctl_table *table, int write,
0033           void *buffer, size_t *lenp, loff_t *ppos)
0034 {
0035     struct ctl_table uts_table;
0036     int r;
0037     char tmp_data[__NEW_UTS_LEN + 1];
0038 
0039     memcpy(&uts_table, table, sizeof(uts_table));
0040     uts_table.data = tmp_data;
0041 
0042     /*
0043      * Buffer the value in tmp_data so that proc_dostring() can be called
0044      * without holding any locks.
0045      * We also need to read the original value in the write==1 case to
0046      * support partial writes.
0047      */
0048     down_read(&uts_sem);
0049     memcpy(tmp_data, get_uts(table), sizeof(tmp_data));
0050     up_read(&uts_sem);
0051     r = proc_dostring(&uts_table, write, buffer, lenp, ppos);
0052 
0053     if (write) {
0054         /*
0055          * Write back the new value.
0056          * Note that, since we dropped uts_sem, the result can
0057          * theoretically be incorrect if there are two parallel writes
0058          * at non-zero offsets to the same sysctl.
0059          */
0060         down_write(&uts_sem);
0061         memcpy(get_uts(table), tmp_data, sizeof(tmp_data));
0062         up_write(&uts_sem);
0063         proc_sys_poll_notify(table->poll);
0064     }
0065 
0066     return r;
0067 }
0068 #else
0069 #define proc_do_uts_string NULL
0070 #endif
0071 
0072 static DEFINE_CTL_TABLE_POLL(hostname_poll);
0073 static DEFINE_CTL_TABLE_POLL(domainname_poll);
0074 
0075 static struct ctl_table uts_kern_table[] = {
0076     {
0077         .procname   = "ostype",
0078         .data       = init_uts_ns.name.sysname,
0079         .maxlen     = sizeof(init_uts_ns.name.sysname),
0080         .mode       = 0444,
0081         .proc_handler   = proc_do_uts_string,
0082     },
0083     {
0084         .procname   = "osrelease",
0085         .data       = init_uts_ns.name.release,
0086         .maxlen     = sizeof(init_uts_ns.name.release),
0087         .mode       = 0444,
0088         .proc_handler   = proc_do_uts_string,
0089     },
0090     {
0091         .procname   = "version",
0092         .data       = init_uts_ns.name.version,
0093         .maxlen     = sizeof(init_uts_ns.name.version),
0094         .mode       = 0444,
0095         .proc_handler   = proc_do_uts_string,
0096     },
0097     {
0098         .procname   = "hostname",
0099         .data       = init_uts_ns.name.nodename,
0100         .maxlen     = sizeof(init_uts_ns.name.nodename),
0101         .mode       = 0644,
0102         .proc_handler   = proc_do_uts_string,
0103         .poll       = &hostname_poll,
0104     },
0105     {
0106         .procname   = "domainname",
0107         .data       = init_uts_ns.name.domainname,
0108         .maxlen     = sizeof(init_uts_ns.name.domainname),
0109         .mode       = 0644,
0110         .proc_handler   = proc_do_uts_string,
0111         .poll       = &domainname_poll,
0112     },
0113     {}
0114 };
0115 
0116 static struct ctl_table uts_root_table[] = {
0117     {
0118         .procname   = "kernel",
0119         .mode       = 0555,
0120         .child      = uts_kern_table,
0121     },
0122     {}
0123 };
0124 
0125 #ifdef CONFIG_PROC_SYSCTL
0126 /*
0127  * Notify userspace about a change in a certain entry of uts_kern_table,
0128  * identified by the parameter proc.
0129  */
0130 void uts_proc_notify(enum uts_proc proc)
0131 {
0132     struct ctl_table *table = &uts_kern_table[proc];
0133 
0134     proc_sys_poll_notify(table->poll);
0135 }
0136 #endif
0137 
0138 static int __init utsname_sysctl_init(void)
0139 {
0140     register_sysctl_table(uts_root_table);
0141     return 0;
0142 }
0143 
0144 device_initcall(utsname_sysctl_init);