/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2002 Daniel M. Eischen <[email protected]>4* All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND16* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE17* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE18* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE19* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL20* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS21* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)22* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT23* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY24* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF25* SUCH DAMAGE.26*/2728#include <sys/param.h>29#include <sys/kernel.h>30#include <sys/lock.h>31#include <sys/mutex.h>32#include <sys/proc.h>33#include <sys/syscallsubr.h>34#include <sys/systm.h>35#include <sys/sysproto.h>36#include <sys/signalvar.h>37#include <sys/ucontext.h>3839/*40* The first two fields of a ucontext_t are the signal mask and the machine41* context. The next field is uc_link; we want to avoid destroying the link42* when copying out contexts.43*/44#define UC_COPY_SIZE offsetof(ucontext_t, uc_link)4546#ifndef _SYS_SYSPROTO_H_47struct getcontext_args {48struct __ucontext *ucp;49}50struct setcontext_args {51const struct __ucontext_t *ucp;52}53struct swapcontext_args {54struct __ucontext *oucp;55const struct __ucontext_t *ucp;56}57#endif5859int60sys_getcontext(struct thread *td, struct getcontext_args *uap)61{62ucontext_t uc;63int ret;6465if (uap->ucp == NULL)66ret = EINVAL;67else {68bzero(&uc, sizeof(ucontext_t));69get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);70PROC_LOCK(td->td_proc);71uc.uc_sigmask = td->td_sigmask;72PROC_UNLOCK(td->td_proc);73ret = copyout(&uc, uap->ucp, UC_COPY_SIZE);74}75return (ret);76}7778int79sys_setcontext(struct thread *td, struct setcontext_args *uap)80{81ucontext_t uc;82int ret;8384if (uap->ucp == NULL)85ret = EINVAL;86else {87ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);88if (ret == 0) {89ret = set_mcontext(td, &uc.uc_mcontext);90if (ret == 0) {91kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask,92NULL, 0);93}94}95}96return (ret == 0 ? EJUSTRETURN : ret);97}9899int100sys_swapcontext(struct thread *td, struct swapcontext_args *uap)101{102ucontext_t uc;103int ret;104105if (uap->oucp == NULL || uap->ucp == NULL)106ret = EINVAL;107else {108bzero(&uc, sizeof(ucontext_t));109get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);110PROC_LOCK(td->td_proc);111uc.uc_sigmask = td->td_sigmask;112PROC_UNLOCK(td->td_proc);113ret = copyout(&uc, uap->oucp, UC_COPY_SIZE);114if (ret == 0) {115ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);116if (ret == 0) {117ret = set_mcontext(td, &uc.uc_mcontext);118if (ret == 0) {119kern_sigprocmask(td, SIG_SETMASK,120&uc.uc_sigmask, NULL, 0);121}122}123}124}125return (ret == 0 ? EJUSTRETURN : ret);126}127128129