14c3df794SDoug Rabson /*- 24c3df794SDoug Rabson * Copyright (c) 1999 Assar Westerlund 34c3df794SDoug Rabson * All rights reserved. 44c3df794SDoug Rabson * 54c3df794SDoug Rabson * Redistribution and use in source and binary forms, with or without 64c3df794SDoug Rabson * modification, are permitted provided that the following conditions 74c3df794SDoug Rabson * are met: 84c3df794SDoug Rabson * 1. Redistributions of source code must retain the above copyright 94c3df794SDoug Rabson * notice, this list of conditions and the following disclaimer. 104c3df794SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright 114c3df794SDoug Rabson * notice, this list of conditions and the following disclaimer in the 124c3df794SDoug Rabson * documentation and/or other materials provided with the distribution. 134c3df794SDoug Rabson * 144c3df794SDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 154c3df794SDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 164c3df794SDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 174c3df794SDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 184c3df794SDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 194c3df794SDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 204c3df794SDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 214c3df794SDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 224c3df794SDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 234c3df794SDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 244c3df794SDoug Rabson * SUCH DAMAGE. 254c3df794SDoug Rabson */ 264c3df794SDoug Rabson 27677b542eSDavid E. O'Brien #include <sys/cdefs.h> 28677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 29677b542eSDavid E. O'Brien 304c3df794SDoug Rabson #include <sys/param.h> 314c3df794SDoug Rabson #include <sys/sysproto.h> 324c3df794SDoug Rabson #include <sys/sysent.h> 334c3df794SDoug Rabson #include <sys/syscall.h> 349b3851e9SAndrew R. Reiter #include <sys/lock.h> 359b3851e9SAndrew R. Reiter #include <sys/mutex.h> 369b3851e9SAndrew R. Reiter #include <sys/sx.h> 374c3df794SDoug Rabson #include <sys/module.h> 384c3df794SDoug Rabson 3946db4836SPeter Wemm /* 4046db4836SPeter Wemm * Acts like "nosys" but can be identified in sysent for dynamic call 4146db4836SPeter Wemm * number assignment for a limited number of calls. 4246db4836SPeter Wemm * 4346db4836SPeter Wemm * Place holder for system call slots reserved for loadable modules. 4446db4836SPeter Wemm */ 4546db4836SPeter Wemm int 46b40ce416SJulian Elischer lkmnosys(struct thread *td, struct nosys_args *args) 4746db4836SPeter Wemm { 48b40ce416SJulian Elischer return(nosys(td, args)); 4946db4836SPeter Wemm } 5046db4836SPeter Wemm 514c3df794SDoug Rabson int 52b40ce416SJulian Elischer lkmressys(struct thread *td, struct nosys_args *args) 5378525ce3SAlfred Perlstein { 54b40ce416SJulian Elischer return(nosys(td, args)); 5578525ce3SAlfred Perlstein } 5678525ce3SAlfred Perlstein 5778525ce3SAlfred Perlstein int 584c3df794SDoug Rabson syscall_register(int *offset, struct sysent *new_sysent, 594c3df794SDoug Rabson struct sysent *old_sysent) 604c3df794SDoug Rabson { 614c3df794SDoug Rabson if (*offset == NO_SYSCALL) { 624c3df794SDoug Rabson int i; 634c3df794SDoug Rabson 644c3df794SDoug Rabson for (i = 1; i < SYS_MAXSYSCALL; ++i) 654c3df794SDoug Rabson if (sysent[i].sy_call == (sy_call_t *)lkmnosys) 664c3df794SDoug Rabson break; 674c3df794SDoug Rabson if (i == SYS_MAXSYSCALL) 684c3df794SDoug Rabson return ENFILE; 694c3df794SDoug Rabson *offset = i; 704c3df794SDoug Rabson } else if (*offset < 0 || *offset >= SYS_MAXSYSCALL) 714c3df794SDoug Rabson return EINVAL; 7278525ce3SAlfred Perlstein else if (sysent[*offset].sy_call != (sy_call_t *)lkmnosys && 7378525ce3SAlfred Perlstein sysent[*offset].sy_call != (sy_call_t *)lkmressys) 744c3df794SDoug Rabson return EEXIST; 754c3df794SDoug Rabson 764c3df794SDoug Rabson *old_sysent = sysent[*offset]; 774c3df794SDoug Rabson sysent[*offset] = *new_sysent; 784c3df794SDoug Rabson return 0; 794c3df794SDoug Rabson } 804c3df794SDoug Rabson 814c3df794SDoug Rabson int 824c3df794SDoug Rabson syscall_deregister(int *offset, struct sysent *old_sysent) 834c3df794SDoug Rabson { 844c3df794SDoug Rabson if (*offset) 854c3df794SDoug Rabson sysent[*offset] = *old_sysent; 864c3df794SDoug Rabson return 0; 874c3df794SDoug Rabson } 884c3df794SDoug Rabson 894c3df794SDoug Rabson int 904c3df794SDoug Rabson syscall_module_handler(struct module *mod, int what, void *arg) 914c3df794SDoug Rabson { 924c3df794SDoug Rabson struct syscall_module_data *data = (struct syscall_module_data*)arg; 93a35261efSDoug Rabson modspecific_t ms; 944c3df794SDoug Rabson int error; 954c3df794SDoug Rabson 964c3df794SDoug Rabson switch (what) { 974c3df794SDoug Rabson case MOD_LOAD : 984c3df794SDoug Rabson error = syscall_register(data->offset, data->new_sysent, 994c3df794SDoug Rabson &data->old_sysent); 10003e161fdSJohn Baldwin if (error) { 10103e161fdSJohn Baldwin /* Leave a mark so we know to safely unload below. */ 10203e161fdSJohn Baldwin data->offset = NULL; 1034c3df794SDoug Rabson return error; 10403e161fdSJohn Baldwin } 105a35261efSDoug Rabson ms.intval = *data->offset; 1069b3851e9SAndrew R. Reiter MOD_XLOCK; 107a35261efSDoug Rabson module_setspecific(mod, &ms); 1089b3851e9SAndrew R. Reiter MOD_XUNLOCK; 109c049aba8SDoug Rabson if (data->chainevh) 110c049aba8SDoug Rabson error = data->chainevh(mod, what, data->chainarg); 111c049aba8SDoug Rabson return error; 112c049aba8SDoug Rabson 1134c3df794SDoug Rabson case MOD_UNLOAD : 11403e161fdSJohn Baldwin /* 11503e161fdSJohn Baldwin * MOD_LOAD failed, so just return without calling the 11603e161fdSJohn Baldwin * chained handler since we didn't pass along the MOD_LOAD 11703e161fdSJohn Baldwin * event. 11803e161fdSJohn Baldwin */ 11903e161fdSJohn Baldwin if (data->offset == NULL) 12003e161fdSJohn Baldwin return (0); 121c049aba8SDoug Rabson if (data->chainevh) { 122c049aba8SDoug Rabson error = data->chainevh(mod, what, data->chainarg); 1234c3df794SDoug Rabson if (error) 1244c3df794SDoug Rabson return error; 1254c3df794SDoug Rabson } 126c049aba8SDoug Rabson error = syscall_deregister(data->offset, &data->old_sysent); 127c049aba8SDoug Rabson return error; 1283e019deaSPoul-Henning Kamp default : 1293e019deaSPoul-Henning Kamp return EOPNOTSUPP; 1303e019deaSPoul-Henning Kamp 131c049aba8SDoug Rabson } 132c049aba8SDoug Rabson 1334c3df794SDoug Rabson if (data->chainevh) 1344c3df794SDoug Rabson return data->chainevh(mod, what, data->chainarg); 1354c3df794SDoug Rabson else 1364c3df794SDoug Rabson return 0; 1374c3df794SDoug Rabson } 138