1106977Sdeischen/*-
2106977Sdeischen * Copyright (c) 2002 Daniel M. Eischen <deischen@freebsd.org>
3106977Sdeischen * All rights reserved.
4106977Sdeischen *
5106977Sdeischen * Redistribution and use in source and binary forms, with or without
6106977Sdeischen * modification, are permitted provided that the following conditions
7106977Sdeischen * are met:
8106977Sdeischen * 1. Redistributions of source code must retain the above copyright
9106977Sdeischen *    notice, this list of conditions and the following disclaimer.
10106977Sdeischen * 2. Redistributions in binary form must reproduce the above copyright
11106977Sdeischen *    notice, this list of conditions and the following disclaimer in the
12106977Sdeischen *    documentation and/or other materials provided with the distribution.
13106977Sdeischen *
14106977Sdeischen * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15106977Sdeischen * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16106977Sdeischen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17106977Sdeischen * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18106977Sdeischen * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19106977Sdeischen * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20106977Sdeischen * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21106977Sdeischen * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22106977Sdeischen * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23106977Sdeischen * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24106977Sdeischen * SUCH DAMAGE.
25106977Sdeischen */
26106977Sdeischen
27116182Sobrien#include <sys/cdefs.h>
28116182Sobrien__FBSDID("$FreeBSD: stable/11/sys/kern/kern_context.c 338983 2018-09-27 18:42:40Z gordon $");
29116182Sobrien
30106977Sdeischen#include <sys/param.h>
31106977Sdeischen#include <sys/kernel.h>
32106977Sdeischen#include <sys/lock.h>
33106977Sdeischen#include <sys/mutex.h>
34106977Sdeischen#include <sys/proc.h>
35209613Sjhb#include <sys/syscallsubr.h>
36106977Sdeischen#include <sys/sysent.h>
37106977Sdeischen#include <sys/systm.h>
38106977Sdeischen#include <sys/sysproto.h>
39106977Sdeischen#include <sys/signalvar.h>
40106977Sdeischen#include <sys/ucontext.h>
41106977Sdeischen
42106977Sdeischen/*
43167232Srwatson * The first two fields of a ucontext_t are the signal mask and the machine
44167232Srwatson * context.  The next field is uc_link; we want to avoid destroying the link
45167232Srwatson * when copying out contexts.
46106977Sdeischen */
47112962Sjake#define	UC_COPY_SIZE	offsetof(ucontext_t, uc_link)
48106977Sdeischen
49106977Sdeischen#ifndef _SYS_SYSPROTO_H_
50106977Sdeischenstruct getcontext_args {
51106977Sdeischen	struct __ucontext *ucp;
52106977Sdeischen}
53106977Sdeischenstruct setcontext_args {
54106977Sdeischen	const struct __ucontext_t *ucp;
55106977Sdeischen}
56106977Sdeischenstruct swapcontext_args {
57106977Sdeischen	struct __ucontext *oucp;
58106977Sdeischen	const struct __ucontext_t *ucp;
59106977Sdeischen}
60106977Sdeischen#endif
61106977Sdeischen
62106977Sdeischenint
63225617Skmacysys_getcontext(struct thread *td, struct getcontext_args *uap)
64106977Sdeischen{
65106977Sdeischen	ucontext_t uc;
66113626Sjhb	int ret;
67106977Sdeischen
68106977Sdeischen	if (uap->ucp == NULL)
69106977Sdeischen		ret = EINVAL;
70106977Sdeischen	else {
71338983Sgordon		bzero(&uc, sizeof(ucontext_t));
72122364Smarcel		get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
73113626Sjhb		PROC_LOCK(td->td_proc);
74112888Sjeff		uc.uc_sigmask = td->td_sigmask;
75113626Sjhb		PROC_UNLOCK(td->td_proc);
76218327Skib		bzero(uc.__spare__, sizeof(uc.__spare__));
77106977Sdeischen		ret = copyout(&uc, uap->ucp, UC_COPY_SIZE);
78106977Sdeischen	}
79106977Sdeischen	return (ret);
80106977Sdeischen}
81106977Sdeischen
82106977Sdeischenint
83225617Skmacysys_setcontext(struct thread *td, struct setcontext_args *uap)
84106977Sdeischen{
85106977Sdeischen	ucontext_t uc;
86106977Sdeischen	int ret;
87106977Sdeischen
88106977Sdeischen	if (uap->ucp == NULL)
89106977Sdeischen		ret = EINVAL;
90106977Sdeischen	else {
91106977Sdeischen		ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
92106977Sdeischen		if (ret == 0) {
93106977Sdeischen			ret = set_mcontext(td, &uc.uc_mcontext);
94106977Sdeischen			if (ret == 0) {
95198507Skib				kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask,
96198507Skib				    NULL, 0);
97106977Sdeischen			}
98106977Sdeischen		}
99106977Sdeischen	}
100112962Sjake	return (ret == 0 ? EJUSTRETURN : ret);
101106977Sdeischen}
102106977Sdeischen
103106977Sdeischenint
104225617Skmacysys_swapcontext(struct thread *td, struct swapcontext_args *uap)
105106977Sdeischen{
106106977Sdeischen	ucontext_t uc;
107106977Sdeischen	int ret;
108106977Sdeischen
109106977Sdeischen	if (uap->oucp == NULL || uap->ucp == NULL)
110106977Sdeischen		ret = EINVAL;
111106977Sdeischen	else {
112338983Sgordon		bzero(&uc, sizeof(ucontext_t));
113122364Smarcel		get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
114218327Skib		bzero(uc.__spare__, sizeof(uc.__spare__));
115113626Sjhb		PROC_LOCK(td->td_proc);
116112888Sjeff		uc.uc_sigmask = td->td_sigmask;
117113626Sjhb		PROC_UNLOCK(td->td_proc);
118106977Sdeischen		ret = copyout(&uc, uap->oucp, UC_COPY_SIZE);
119106977Sdeischen		if (ret == 0) {
120106977Sdeischen			ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
121106977Sdeischen			if (ret == 0) {
122106977Sdeischen				ret = set_mcontext(td, &uc.uc_mcontext);
123106977Sdeischen				if (ret == 0) {
124198507Skib					kern_sigprocmask(td, SIG_SETMASK,
125198507Skib					    &uc.uc_sigmask, NULL, 0);
126106977Sdeischen				}
127106977Sdeischen			}
128106977Sdeischen		}
129106977Sdeischen	}
130112962Sjake	return (ret == 0 ? EJUSTRETURN : ret);
131106977Sdeischen}
132