diff options
author | John Baldwin <jhb@FreeBSD.org> | 2006-08-01 16:32:20 +0000 |
---|---|---|
committer | John Baldwin <jhb@FreeBSD.org> | 2006-08-01 16:32:20 +0000 |
commit | 03e161fdb10493d9baf7852127a9836715e080d3 (patch) | |
tree | b9ddf54c00e1c5c2b880e5c041c164917b3311e2 /sys/kern/kern_syscalls.c | |
parent | 6cba7f3609eb90e3240054473bb00f85e6756860 (diff) | |
download | src-03e161fdb10493d9baf7852127a9836715e080d3.tar.gz src-03e161fdb10493d9baf7852127a9836715e080d3.zip |
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
Notes
Notes:
svn path=/head/; revision=160882
Diffstat (limited to 'sys/kern/kern_syscalls.c')
-rw-r--r-- | sys/kern/kern_syscalls.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/sys/kern/kern_syscalls.c b/sys/kern/kern_syscalls.c index a437fb328cf8..6452d968696e 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) |