xref: /freebsd/sys/kern/kern_syscalls.c (revision b40ce4165d5eb3a5de1515245055350ae3dbab8e)
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  *
26c3aac50fSPeter Wemm  * $FreeBSD$
274c3df794SDoug Rabson  */
284c3df794SDoug Rabson 
294c3df794SDoug Rabson #include <sys/param.h>
304c3df794SDoug Rabson #include <sys/sysproto.h>
314c3df794SDoug Rabson #include <sys/sysent.h>
324c3df794SDoug Rabson #include <sys/syscall.h>
334c3df794SDoug Rabson #include <sys/module.h>
344c3df794SDoug Rabson 
3546db4836SPeter Wemm /*
3646db4836SPeter Wemm  * Acts like "nosys" but can be identified in sysent for dynamic call
3746db4836SPeter Wemm  * number assignment for a limited number of calls.
3846db4836SPeter Wemm  *
3946db4836SPeter Wemm  * Place holder for system call slots reserved for loadable modules.
4046db4836SPeter Wemm  */
4146db4836SPeter Wemm int
42b40ce416SJulian Elischer lkmnosys(struct thread *td, struct nosys_args *args)
4346db4836SPeter Wemm {
44b40ce416SJulian Elischer 	return(nosys(td, args));
4546db4836SPeter Wemm }
4646db4836SPeter Wemm 
474c3df794SDoug Rabson int
48b40ce416SJulian Elischer lkmressys(struct thread *td, struct nosys_args *args)
4978525ce3SAlfred Perlstein {
50b40ce416SJulian Elischer 	return(nosys(td, args));
5178525ce3SAlfred Perlstein }
5278525ce3SAlfred Perlstein 
5378525ce3SAlfred Perlstein int
544c3df794SDoug Rabson syscall_register(int *offset, struct sysent *new_sysent,
554c3df794SDoug Rabson 		 struct sysent *old_sysent)
564c3df794SDoug Rabson {
574c3df794SDoug Rabson        if (*offset == NO_SYSCALL) {
584c3df794SDoug Rabson                int i;
594c3df794SDoug Rabson 
604c3df794SDoug Rabson                for (i = 1; i < SYS_MAXSYSCALL; ++i)
614c3df794SDoug Rabson                        if (sysent[i].sy_call == (sy_call_t *)lkmnosys)
624c3df794SDoug Rabson                                break;
634c3df794SDoug Rabson                if (i == SYS_MAXSYSCALL)
644c3df794SDoug Rabson                        return ENFILE;
654c3df794SDoug Rabson                *offset = i;
664c3df794SDoug Rabson        } else if (*offset < 0 || *offset >= SYS_MAXSYSCALL)
674c3df794SDoug Rabson                return EINVAL;
6878525ce3SAlfred Perlstein        else if (sysent[*offset].sy_call != (sy_call_t *)lkmnosys &&
6978525ce3SAlfred Perlstein 				sysent[*offset].sy_call != (sy_call_t *)lkmressys)
704c3df794SDoug Rabson                return EEXIST;
714c3df794SDoug Rabson 
724c3df794SDoug Rabson        *old_sysent = sysent[*offset];
734c3df794SDoug Rabson        sysent[*offset] = *new_sysent;
744c3df794SDoug Rabson        return 0;
754c3df794SDoug Rabson }
764c3df794SDoug Rabson 
774c3df794SDoug Rabson int
784c3df794SDoug Rabson syscall_deregister(int *offset, struct sysent *old_sysent)
794c3df794SDoug Rabson {
804c3df794SDoug Rabson        if (*offset)
814c3df794SDoug Rabson                sysent[*offset] = *old_sysent;
824c3df794SDoug Rabson        return 0;
834c3df794SDoug Rabson }
844c3df794SDoug Rabson 
854c3df794SDoug Rabson int
864c3df794SDoug Rabson syscall_module_handler(struct module *mod, int what, void *arg)
874c3df794SDoug Rabson {
884c3df794SDoug Rabson        struct syscall_module_data *data = (struct syscall_module_data*)arg;
89a35261efSDoug Rabson        modspecific_t ms;
904c3df794SDoug Rabson        int error;
914c3df794SDoug Rabson 
924c3df794SDoug Rabson        switch (what) {
934c3df794SDoug Rabson        case MOD_LOAD :
944c3df794SDoug Rabson                error = syscall_register(data->offset, data->new_sysent,
954c3df794SDoug Rabson                                         &data->old_sysent);
964c3df794SDoug Rabson                if (error)
974c3df794SDoug Rabson                        return error;
98a35261efSDoug Rabson 	       ms.intval = *data->offset;
99a35261efSDoug Rabson 	       module_setspecific(mod, &ms);
100c049aba8SDoug Rabson                if (data->chainevh)
101c049aba8SDoug Rabson                        error = data->chainevh(mod, what, data->chainarg);
102c049aba8SDoug Rabson                return error;
103c049aba8SDoug Rabson 
1044c3df794SDoug Rabson        case MOD_UNLOAD :
105c049aba8SDoug Rabson                if (data->chainevh) {
106c049aba8SDoug Rabson                        error = data->chainevh(mod, what, data->chainarg);
1074c3df794SDoug Rabson                        if (error)
1084c3df794SDoug Rabson                                return error;
1094c3df794SDoug Rabson                }
110c049aba8SDoug Rabson                error = syscall_deregister(data->offset, &data->old_sysent);
111c049aba8SDoug Rabson                return error;
112c049aba8SDoug Rabson        }
113c049aba8SDoug Rabson 
1144c3df794SDoug Rabson        if (data->chainevh)
1154c3df794SDoug Rabson                return data->chainevh(mod, what, data->chainarg);
1164c3df794SDoug Rabson        else
1174c3df794SDoug Rabson                return 0;
1184c3df794SDoug Rabson }
119