[PATCH] SYS: refactor sethostname setdomainname by introducing shared helper

From: Laurijssen

Date: Thu Nov 12 2026 - 03:37:24 EST


Refactor sethostname/setdomainname to consolidate name setting logic
into a new helper, utsname_set_field. The existing implementation
duplicated validation, size checks, and uts namespace update steps that
are also needed by upcoming changes in related syscalls.

The helper centralizes:
- updates to utsname()->nodename/domainname with proper locking
- propagation rules for shared uts namespaces.

utsname_set_field could not be moved to utsname_sysctl.c as that file
is not compiled when CONFIG_SYSCTL is not defined.

This refactor does not change user behavior. All semantics of
the syscalls remain intact, including error codes and namespace
handling. The patch reduces code duplication, improves maintainability
and prepares for future extensions to utsname management.

Signed-off-by: Laurijssen <laurijssen@xxxxxxxxxxxxxx>
---
kernel/sys.c | 53 ++++++++++++++++++++++++++--------------------------
1 file changed, 27 insertions(+), 26 deletions(-)

diff --git a/kernel/sys.c b/kernel/sys.c
index 755bfa5ccd92..77fedd127a3f 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1419,7 +1419,7 @@ SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name)
}
#endif

-SYSCALL_DEFINE2(sethostname, char __user *, name, int, len)
+static int utsname_set_field(char __user *name, int len, enum uts_proc proc)
{
int errno;
char tmp[__NEW_UTS_LEN];
@@ -1432,19 +1432,41 @@ SYSCALL_DEFINE2(sethostname, char __user *, name, int, len)
errno = -EFAULT;
if (!copy_from_user(tmp, name, len)) {
struct new_utsname *u;
+ char *field;

add_device_randomness(tmp, len);
down_write(&uts_sem);
+
u = utsname();
- memcpy(u->nodename, tmp, len);
- memset(u->nodename + len, 0, sizeof(u->nodename) - len);
+
+ switch (proc) {
+ case UTS_PROC_HOSTNAME:
+ field = u->nodename;
+ break;
+ case UTS_PROC_DOMAINNAME:
+ field = u->domainname;
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ field = u->domainname;
+ break;
+ }
+
+ memcpy(field, tmp, len);
+ memset(field + len, 0, sizeof_field(struct new_utsname, nodename) - len);
+
errno = 0;
- uts_proc_notify(UTS_PROC_HOSTNAME);
+ uts_proc_notify(proc);
up_write(&uts_sem);
}
return errno;
}

+SYSCALL_DEFINE2(sethostname, char __user *, name, int, len)
+{
+ return utsname_set_field(name, len, UTS_PROC_HOSTNAME);
+}
+
#ifdef __ARCH_WANT_SYS_GETHOSTNAME

SYSCALL_DEFINE2(gethostname, char __user *, name, int, len)
@@ -1475,28 +1497,7 @@ SYSCALL_DEFINE2(gethostname, char __user *, name, int, len)
*/
SYSCALL_DEFINE2(setdomainname, char __user *, name, int, len)
{
- int errno;
- char tmp[__NEW_UTS_LEN];
-
- if (!ns_capable(current->nsproxy->uts_ns->user_ns, CAP_SYS_ADMIN))
- return -EPERM;
- if (len < 0 || len > __NEW_UTS_LEN)
- return -EINVAL;
-
- errno = -EFAULT;
- if (!copy_from_user(tmp, name, len)) {
- struct new_utsname *u;
-
- add_device_randomness(tmp, len);
- down_write(&uts_sem);
- u = utsname();
- memcpy(u->domainname, tmp, len);
- memset(u->domainname + len, 0, sizeof(u->domainname) - len);
- errno = 0;
- uts_proc_notify(UTS_PROC_DOMAINNAME);
- up_write(&uts_sem);
- }
- return errno;
+ return utsname_set_field(name, len, UTS_PROC_DOMAINNAME);
}

/* make sure you are allowed to change @tsk limits before calling this */
--
2.53.0