From fcb9fd7c83420e6ddcd8f29af6f4e61b0601a529 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Tue, 12 Nov 2024 00:19:12 -0500 Subject: kernel: syscall: Add SYS_sysctl syscall Signed-off-by: Ian Moffett --- sys/kern/kern_sysctl.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) (limited to 'sys/kern/kern_sysctl.c') diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index 970bc70..3d0b118 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -28,7 +28,9 @@ */ #include +#include #include +#include #include #include @@ -46,6 +48,76 @@ static struct sysctl_entry common_kerntab[] = { [KERN_VERSION] = { KERN_VERSION, SYSCTL_OPTYPE_STR, &hyra_version }, }; +/* + * Helper for sys_sysctl() + */ +static int +do_sysctl(struct sysctl_args *args) +{ + struct sysctl_args new_args; + size_t name_len, oldlenp; + int *name = NULL; + void *oldp = NULL, *newp = NULL; + int retval = 0; + + if (args->oldlenp == NULL) { + return -EINVAL; + } + + name_len = args->nlen; + retval = copyin(args->oldlenp, &oldlenp, sizeof(oldlenp)); + if (retval != 0) { + goto done; + } + + /* Copy in newp if it is set */ + if (args->newp == NULL) { + newp = NULL; + } else { + newp = dynalloc(args->newlen); + retval = copyin(args->newp, newp, args->newlen); + } + + if (retval != 0) { + goto done; + } + + name = dynalloc(name_len * sizeof(int)); + retval = copyin(args->name, name, name_len * sizeof(int)); + if (retval != 0) { + return retval; + } + + oldp = dynalloc(oldlenp); + retval = copyin(args->oldp, oldp, oldlenp); + if (retval != 0) { + return retval; + } + + /* Prepare the arguments for the sysctl call */ + new_args.name = name; + new_args.nlen = name_len; + new_args.oldp = oldp; + new_args.oldlenp = &oldlenp; + new_args.newp = newp; + + retval = sysctl(&new_args); + if (retval != 0) { + goto done; + } + + copyout(oldp, args->oldp, oldlenp); +done: + if (name != NULL) + dynfree(name); + if (newp != NULL) + dynfree(newp); + if (oldp != NULL) + dynfree(oldp); + + return retval; +} + int sysctl(struct sysctl_args *args) { @@ -96,3 +168,17 @@ sysctl(struct sysctl_args *args) memcpy(args->oldp, tmp_str, oldlen); return (len > oldlen) ? -ENOMEM : 0; } + +scret_t +sys_sysctl(struct syscall_args *scargs) +{ + struct sysctl_args args; + int error; + + error = copyin((void *)scargs->arg0, &args, sizeof(args)); + if (error != 0) { + return error; + } + + return do_sysctl(&args); +} -- cgit v1.2.3