summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2006-08-01 16:32:20 +0000
committerjhb <jhb@FreeBSD.org>2006-08-01 16:32:20 +0000
commit023ecadf48622b9accaf88dd47b13cd8a99ae035 (patch)
treeb9ddf54c00e1c5c2b880e5c041c164917b3311e2 /sys
parent4dc640e56e164af7bfa43acfe36b6a8037512f66 (diff)
downloadFreeBSD-src-023ecadf48622b9accaf88dd47b13cd8a99ae035.zip
FreeBSD-src-023ecadf48622b9accaf88dd47b13cd8a99ae035.tar.gz
Make system call modules a bit more robust:
- If we fail to register the system call during MOD_LOAD, then note that so that we don't try to deregister it or invoke the chained event handler during the subsequent MOD_UNLOAD event. Doing the deregister when the register failed could result in trashing system call entries. - Add a SI_SUB_SYSCALLS just before starting up init and use that to register syscall modules instead of SI_SUB_DRIVERS. Registering system calls as late as possible increases the chances that any other module event handlers or SYSINITs in a module are executed to initialize the data in a kld before a syscall dependent on that data is able to be invoked. MFC after: 3 days
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_syscalls.c12
-rw-r--r--sys/sys/kernel.h1
-rw-r--r--sys/sys/sysent.h2
3 files changed, 13 insertions, 2 deletions
diff --git a/sys/kern/kern_syscalls.c b/sys/kern/kern_syscalls.c
index a437fb3..6452d96 100644
--- a/sys/kern/kern_syscalls.c
+++ b/sys/kern/kern_syscalls.c
@@ -97,8 +97,11 @@ syscall_module_handler(struct module *mod, int what, void *arg)
case MOD_LOAD :
error = syscall_register(data->offset, data->new_sysent,
&data->old_sysent);
- if (error)
+ if (error) {
+ /* Leave a mark so we know to safely unload below. */
+ data->offset = NULL;
return error;
+ }
ms.intval = *data->offset;
MOD_XLOCK;
module_setspecific(mod, &ms);
@@ -108,6 +111,13 @@ syscall_module_handler(struct module *mod, int what, void *arg)
return error;
case MOD_UNLOAD :
+ /*
+ * MOD_LOAD failed, so just return without calling the
+ * chained handler since we didn't pass along the MOD_LOAD
+ * event.
+ */
+ if (data->offset == NULL)
+ return (0);
if (data->chainevh) {
error = data->chainevh(mod, what, data->chainarg);
if (error)
diff --git a/sys/sys/kernel.h b/sys/sys/kernel.h
index 7cb3d80..cc36ede 100644
--- a/sys/sys/kernel.h
+++ b/sys/sys/kernel.h
@@ -157,6 +157,7 @@ enum sysinit_sub_id {
SI_SUB_MOUNT_ROOT = 0xb400000, /* root mount*/
SI_SUB_SWAP = 0xc000000, /* swap */
SI_SUB_INTRINSIC_POST = 0xd000000, /* proc 0 cleanup*/
+ SI_SUB_SYSCALLS = 0xd800000, /* register system calls */
SI_SUB_KTHREAD_INIT = 0xe000000, /* init process*/
SI_SUB_KTHREAD_PAGE = 0xe400000, /* pageout daemon*/
SI_SUB_KTHREAD_VM = 0xe800000, /* vm daemon*/
diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h
index 0566794..4e4f25e 100644
--- a/sys/sys/sysent.h
+++ b/sys/sys/sysent.h
@@ -113,7 +113,7 @@ static moduledata_t name##_mod = { \
syscall_module_handler, \
&name##_syscall_mod \
}; \
-DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE)
+DECLARE_MODULE(name, name##_mod, SI_SUB_SYSCALLS, SI_ORDER_MIDDLE)
#define SYSCALL_MODULE_HELPER(syscallname) \
static int syscallname##_syscall = SYS_##syscallname; \
OpenPOWER on IntegriCloud