xref: /freebsd/sys/kern/kern_context.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
12be05b70SDaniel Eischen /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
38a36da99SPedro F. Giffuni  *
42be05b70SDaniel Eischen  * Copyright (c) 2002 Daniel M. Eischen <deischen@freebsd.org>
52be05b70SDaniel Eischen  * All rights reserved.
62be05b70SDaniel Eischen  *
72be05b70SDaniel Eischen  * Redistribution and use in source and binary forms, with or without
82be05b70SDaniel Eischen  * modification, are permitted provided that the following conditions
92be05b70SDaniel Eischen  * are met:
102be05b70SDaniel Eischen  * 1. Redistributions of source code must retain the above copyright
112be05b70SDaniel Eischen  *    notice, this list of conditions and the following disclaimer.
122be05b70SDaniel Eischen  * 2. Redistributions in binary form must reproduce the above copyright
132be05b70SDaniel Eischen  *    notice, this list of conditions and the following disclaimer in the
142be05b70SDaniel Eischen  *    documentation and/or other materials provided with the distribution.
152be05b70SDaniel Eischen  *
162be05b70SDaniel Eischen  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
172be05b70SDaniel Eischen  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
182be05b70SDaniel Eischen  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
192be05b70SDaniel Eischen  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
202be05b70SDaniel Eischen  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
212be05b70SDaniel Eischen  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
222be05b70SDaniel Eischen  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
232be05b70SDaniel Eischen  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
242be05b70SDaniel Eischen  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
252be05b70SDaniel Eischen  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
262be05b70SDaniel Eischen  * SUCH DAMAGE.
272be05b70SDaniel Eischen  */
28677b542eSDavid E. O'Brien 
292be05b70SDaniel Eischen #include <sys/param.h>
302be05b70SDaniel Eischen #include <sys/kernel.h>
312be05b70SDaniel Eischen #include <sys/lock.h>
322be05b70SDaniel Eischen #include <sys/mutex.h>
332be05b70SDaniel Eischen #include <sys/proc.h>
34fc0de8f0SJohn Baldwin #include <sys/syscallsubr.h>
352be05b70SDaniel Eischen #include <sys/systm.h>
362be05b70SDaniel Eischen #include <sys/sysproto.h>
372be05b70SDaniel Eischen #include <sys/signalvar.h>
382be05b70SDaniel Eischen #include <sys/ucontext.h>
392be05b70SDaniel Eischen 
402be05b70SDaniel Eischen /*
41873fbcd7SRobert Watson  * The first two fields of a ucontext_t are the signal mask and the machine
42873fbcd7SRobert Watson  * context.  The next field is uc_link; we want to avoid destroying the link
43873fbcd7SRobert Watson  * when copying out contexts.
442be05b70SDaniel Eischen  */
45fc2fca74SJake Burkholder #define	UC_COPY_SIZE	offsetof(ucontext_t, uc_link)
462be05b70SDaniel Eischen 
472be05b70SDaniel Eischen #ifndef _SYS_SYSPROTO_H_
482be05b70SDaniel Eischen struct getcontext_args {
492be05b70SDaniel Eischen 	struct __ucontext *ucp;
502be05b70SDaniel Eischen }
512be05b70SDaniel Eischen struct setcontext_args {
522be05b70SDaniel Eischen 	const struct __ucontext_t *ucp;
532be05b70SDaniel Eischen }
542be05b70SDaniel Eischen struct swapcontext_args {
552be05b70SDaniel Eischen 	struct __ucontext *oucp;
562be05b70SDaniel Eischen 	const struct __ucontext_t *ucp;
572be05b70SDaniel Eischen }
582be05b70SDaniel Eischen #endif
592be05b70SDaniel Eischen 
602be05b70SDaniel Eischen int
sys_getcontext(struct thread * td,struct getcontext_args * uap)618451d0ddSKip Macy sys_getcontext(struct thread *td, struct getcontext_args *uap)
622be05b70SDaniel Eischen {
632be05b70SDaniel Eischen 	ucontext_t uc;
642be05b70SDaniel Eischen 	int ret;
652be05b70SDaniel Eischen 
662be05b70SDaniel Eischen 	if (uap->ucp == NULL)
672be05b70SDaniel Eischen 		ret = EINVAL;
682be05b70SDaniel Eischen 	else {
6989f652d1SGordon Tetlow 		bzero(&uc, sizeof(ucontext_t));
70fcaa2925SMarcel Moolenaar 		get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
7194df4b85SJohn Baldwin 		PROC_LOCK(td->td_proc);
724093529dSJeff Roberson 		uc.uc_sigmask = td->td_sigmask;
7394df4b85SJohn Baldwin 		PROC_UNLOCK(td->td_proc);
742be05b70SDaniel Eischen 		ret = copyout(&uc, uap->ucp, UC_COPY_SIZE);
752be05b70SDaniel Eischen 	}
762be05b70SDaniel Eischen 	return (ret);
772be05b70SDaniel Eischen }
782be05b70SDaniel Eischen 
792be05b70SDaniel Eischen int
sys_setcontext(struct thread * td,struct setcontext_args * uap)808451d0ddSKip Macy sys_setcontext(struct thread *td, struct setcontext_args *uap)
812be05b70SDaniel Eischen {
822be05b70SDaniel Eischen 	ucontext_t uc;
832be05b70SDaniel Eischen 	int ret;
842be05b70SDaniel Eischen 
852be05b70SDaniel Eischen 	if (uap->ucp == NULL)
862be05b70SDaniel Eischen 		ret = EINVAL;
872be05b70SDaniel Eischen 	else {
882be05b70SDaniel Eischen 		ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
892be05b70SDaniel Eischen 		if (ret == 0) {
902be05b70SDaniel Eischen 			ret = set_mcontext(td, &uc.uc_mcontext);
912be05b70SDaniel Eischen 			if (ret == 0) {
92d6e029adSKonstantin Belousov 				kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask,
93d6e029adSKonstantin Belousov 				    NULL, 0);
942be05b70SDaniel Eischen 			}
952be05b70SDaniel Eischen 		}
962be05b70SDaniel Eischen 	}
97fc2fca74SJake Burkholder 	return (ret == 0 ? EJUSTRETURN : ret);
982be05b70SDaniel Eischen }
992be05b70SDaniel Eischen 
1002be05b70SDaniel Eischen int
sys_swapcontext(struct thread * td,struct swapcontext_args * uap)1018451d0ddSKip Macy sys_swapcontext(struct thread *td, struct swapcontext_args *uap)
1022be05b70SDaniel Eischen {
1032be05b70SDaniel Eischen 	ucontext_t uc;
1042be05b70SDaniel Eischen 	int ret;
1052be05b70SDaniel Eischen 
1062be05b70SDaniel Eischen 	if (uap->oucp == NULL || uap->ucp == NULL)
1072be05b70SDaniel Eischen 		ret = EINVAL;
1082be05b70SDaniel Eischen 	else {
10989f652d1SGordon Tetlow 		bzero(&uc, sizeof(ucontext_t));
110fcaa2925SMarcel Moolenaar 		get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
11194df4b85SJohn Baldwin 		PROC_LOCK(td->td_proc);
1124093529dSJeff Roberson 		uc.uc_sigmask = td->td_sigmask;
11394df4b85SJohn Baldwin 		PROC_UNLOCK(td->td_proc);
1142be05b70SDaniel Eischen 		ret = copyout(&uc, uap->oucp, UC_COPY_SIZE);
1152be05b70SDaniel Eischen 		if (ret == 0) {
1162be05b70SDaniel Eischen 			ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
1172be05b70SDaniel Eischen 			if (ret == 0) {
1182be05b70SDaniel Eischen 				ret = set_mcontext(td, &uc.uc_mcontext);
1192be05b70SDaniel Eischen 				if (ret == 0) {
120d6e029adSKonstantin Belousov 					kern_sigprocmask(td, SIG_SETMASK,
121d6e029adSKonstantin Belousov 					    &uc.uc_sigmask, NULL, 0);
1222be05b70SDaniel Eischen 				}
1232be05b70SDaniel Eischen 			}
1242be05b70SDaniel Eischen 		}
1252be05b70SDaniel Eischen 	}
126fc2fca74SJake Burkholder 	return (ret == 0 ? EJUSTRETURN : ret);
1272be05b70SDaniel Eischen }
128