2019-06-01 11:08:55 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2007-02-14 11:33:58 +03:00
/*
* Copyright ( C ) 2007
*
* Author : Eric Biederman < ebiederm @ xmision . com >
*/
2011-05-23 22:51:41 +04:00
# include <linux/export.h>
2007-02-14 11:33:58 +03:00
# include <linux/uts.h>
# include <linux/utsname.h>
2022-09-27 12:35:16 +03:00
# include <linux/random.h>
2007-02-14 11:33:58 +03:00
# include <linux/sysctl.h>
2011-11-03 00:39:22 +04:00
# include <linux/wait.h>
2017-02-08 20:51:58 +03:00
# include <linux/rwsem.h>
2007-02-14 11:33:58 +03:00
2013-02-28 05:05:22 +04:00
# ifdef CONFIG_PROC_SYSCTL
2018-06-25 19:34:10 +03:00
static void * get_uts ( struct ctl_table * table )
2007-02-14 11:33:58 +03:00
{
char * which = table - > data ;
2007-11-29 03:21:38 +03:00
struct uts_namespace * uts_ns ;
uts_ns = current - > nsproxy - > uts_ns ;
which = ( which - ( char * ) & init_uts_ns ) + ( char * ) uts_ns ;
2007-07-16 10:40:58 +04:00
2007-02-14 11:33:58 +03:00
return which ;
}
/*
* Special case of dostring for the UTS structure . This has locks
* to observe . Should this be in kernel / sys . c ? ? ? ?
*/
2014-06-07 01:38:08 +04:00
static int proc_do_uts_string ( struct ctl_table * table , int write ,
2020-04-24 09:43:38 +03:00
void * buffer , size_t * lenp , loff_t * ppos )
2007-02-14 11:33:58 +03:00
{
struct ctl_table uts_table ;
int r ;
2018-06-25 19:34:10 +03:00
char tmp_data [ __NEW_UTS_LEN + 1 ] ;
2007-02-14 11:33:58 +03:00
memcpy ( & uts_table , table , sizeof ( uts_table ) ) ;
2018-06-25 19:34:10 +03:00
uts_table . data = tmp_data ;
/*
* Buffer the value in tmp_data so that proc_dostring ( ) can be called
* without holding any locks .
* We also need to read the original value in the write = = 1 case to
* support partial writes .
*/
down_read ( & uts_sem ) ;
memcpy ( tmp_data , get_uts ( table ) , sizeof ( tmp_data ) ) ;
up_read ( & uts_sem ) ;
2014-06-05 03:11:26 +04:00
r = proc_dostring ( & uts_table , write , buffer , lenp , ppos ) ;
2011-11-03 00:39:22 +04:00
2018-06-25 19:34:10 +03:00
if ( write ) {
/*
* Write back the new value .
* Note that , since we dropped uts_sem , the result can
* theoretically be incorrect if there are two parallel writes
* at non - zero offsets to the same sysctl .
*/
2022-09-27 12:35:16 +03:00
add_device_randomness ( tmp_data , sizeof ( tmp_data ) ) ;
2018-06-25 19:34:10 +03:00
down_write ( & uts_sem ) ;
memcpy ( get_uts ( table ) , tmp_data , sizeof ( tmp_data ) ) ;
up_write ( & uts_sem ) ;
2011-11-03 00:39:22 +04:00
proc_sys_poll_notify ( table - > poll ) ;
2018-06-25 19:34:10 +03:00
}
2011-11-03 00:39:22 +04:00
2007-02-14 11:33:58 +03:00
return r ;
}
# else
# define proc_do_uts_string NULL
# endif
2011-11-03 00:39:22 +04:00
static DEFINE_CTL_TABLE_POLL ( hostname_poll ) ;
static DEFINE_CTL_TABLE_POLL ( domainname_poll ) ;
2022-10-23 22:01:01 +03:00
// Note: update 'enum uts_proc' to match any changes to this table
2007-02-14 11:33:58 +03:00
static struct ctl_table uts_kern_table [ ] = {
2022-09-01 22:44:03 +03:00
{
. procname = " arch " ,
. data = init_uts_ns . name . machine ,
. maxlen = sizeof ( init_uts_ns . name . machine ) ,
. mode = 0444 ,
. proc_handler = proc_do_uts_string ,
} ,
2007-02-14 11:33:58 +03:00
{
. procname = " ostype " ,
. data = init_uts_ns . name . sysname ,
. maxlen = sizeof ( init_uts_ns . name . sysname ) ,
. mode = 0444 ,
. proc_handler = proc_do_uts_string ,
} ,
{
. procname = " osrelease " ,
. data = init_uts_ns . name . release ,
. maxlen = sizeof ( init_uts_ns . name . release ) ,
. mode = 0444 ,
. proc_handler = proc_do_uts_string ,
} ,
{
. procname = " version " ,
. data = init_uts_ns . name . version ,
. maxlen = sizeof ( init_uts_ns . name . version ) ,
. mode = 0444 ,
. proc_handler = proc_do_uts_string ,
} ,
{
. procname = " hostname " ,
. data = init_uts_ns . name . nodename ,
. maxlen = sizeof ( init_uts_ns . name . nodename ) ,
. mode = 0644 ,
. proc_handler = proc_do_uts_string ,
2011-11-03 00:39:22 +04:00
. poll = & hostname_poll ,
2007-02-14 11:33:58 +03:00
} ,
{
. procname = " domainname " ,
. data = init_uts_ns . name . domainname ,
. maxlen = sizeof ( init_uts_ns . name . domainname ) ,
. mode = 0644 ,
. proc_handler = proc_do_uts_string ,
2011-11-03 00:39:22 +04:00
. poll = & domainname_poll ,
2007-02-14 11:33:58 +03:00
} ,
{ }
} ;
static struct ctl_table uts_root_table [ ] = {
{
. procname = " kernel " ,
. mode = 0555 ,
. child = uts_kern_table ,
} ,
{ }
} ;
2011-11-03 00:39:22 +04:00
# ifdef CONFIG_PROC_SYSCTL
/*
* Notify userspace about a change in a certain entry of uts_kern_table ,
* identified by the parameter proc .
*/
void uts_proc_notify ( enum uts_proc proc )
{
struct ctl_table * table = & uts_kern_table [ proc ] ;
proc_sys_poll_notify ( table - > poll ) ;
}
# endif
2007-02-14 11:33:58 +03:00
static int __init utsname_sysctl_init ( void )
{
2007-02-14 11:34:09 +03:00
register_sysctl_table ( uts_root_table ) ;
2007-02-14 11:33:58 +03:00
return 0 ;
}
2014-06-05 03:11:26 +04:00
device_initcall ( utsname_sysctl_init ) ;