xref: /freebsd/sys/kern/kern_syscalls.c (revision 03e161fdb10493d9baf7852127a9836715e080d3)
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