diff options
author | Ian Moffett <ian@osmora.org> | 2024-11-12 00:19:12 -0500 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2024-11-12 00:19:12 -0500 |
commit | fcb9fd7c83420e6ddcd8f29af6f4e61b0601a529 (patch) | |
tree | 4f81f43538731831ca853c6372505a20624a9f2b | |
parent | 24c1598929ac4cfd2c0a1e3c34b46a35ed1775bd (diff) |
kernel: syscall: Add SYS_sysctl syscall
Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r-- | sys/include/sys/syscall.h | 1 | ||||
-rw-r--r-- | sys/include/sys/sysctl.h | 5 | ||||
-rw-r--r-- | sys/kern/kern_syscall.c | 2 | ||||
-rw-r--r-- | sys/kern/kern_sysctl.c | 86 |
4 files changed, 94 insertions, 0 deletions
diff --git a/sys/include/sys/syscall.h b/sys/include/sys/syscall.h index b9e1d09..e93c0ce 100644 --- a/sys/include/sys/syscall.h +++ b/sys/include/sys/syscall.h @@ -41,6 +41,7 @@ #define SYS_read 3 #define SYS_close 4 #define SYS_stat 5 +#define SYS_sysctl 6 #if defined(_KERNEL) /* Syscall return value and arg type */ diff --git a/sys/include/sys/sysctl.h b/sys/include/sys/sysctl.h index 364d8e5..0f1df26 100644 --- a/sys/include/sys/sysctl.h +++ b/sys/include/sys/sysctl.h @@ -31,6 +31,9 @@ #define _SYS_SYSCTL_H_ #include <sys/types.h> +#if defined(_KERNEL) +#include <sys/syscall.h> +#endif #include <sys/param.h> #define KERN_OSTYPE 0 @@ -55,6 +58,8 @@ struct sysctl_entry { int optype; void *data; }; + +scret_t sys_sysctl(struct syscall_args *scargs); #endif /* _KERNEL */ /* diff --git a/sys/kern/kern_syscall.c b/sys/kern/kern_syscall.c index f4d9cb8..2d3d6ea 100644 --- a/sys/kern/kern_syscall.c +++ b/sys/kern/kern_syscall.c @@ -28,6 +28,7 @@ */ #include <sys/syscall.h> +#include <sys/sysctl.h> #include <sys/types.h> #include <sys/proc.h> #include <sys/vfs.h> @@ -39,6 +40,7 @@ scret_t(*g_sctab[])(struct syscall_args *) = { sys_read, /* SYS_read */ sys_close, /* SYS_close */ sys_stat, /* SYS_stat */ + sys_sysctl, /* SYS_sysctl */ }; const size_t MAX_SYSCALLS = NELEM(g_sctab); 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 <sys/sysctl.h> +#include <sys/syscall.h> #include <sys/errno.h> +#include <sys/systm.h> #include <vm/dynalloc.h> #include <string.h> @@ -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); +} |