1123974Sdavidxu/*- 2123974Sdavidxu * Copyright (c) 2003 David Xu <davidxu@freebsd.org> 3123974Sdavidxu * All rights reserved. 4123974Sdavidxu * 5123974Sdavidxu * Redistribution and use in source and binary forms, with or without 6123974Sdavidxu * modification, are permitted provided that the following conditions 7123974Sdavidxu * are met: 8123974Sdavidxu * 1. Redistributions of source code must retain the above copyright 9123974Sdavidxu * notice, this list of conditions and the following disclaimer. 10123974Sdavidxu * 2. Redistributions in binary form must reproduce the above copyright 11123974Sdavidxu * notice, this list of conditions and the following disclaimer in the 12123974Sdavidxu * documentation and/or other materials provided with the distribution. 13123974Sdavidxu * 14123974Sdavidxu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15123974Sdavidxu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16123974Sdavidxu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17123974Sdavidxu * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18123974Sdavidxu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19123974Sdavidxu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20123974Sdavidxu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21123974Sdavidxu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22123974Sdavidxu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23123974Sdavidxu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24123974Sdavidxu * SUCH DAMAGE. 25123974Sdavidxu */ 26123974Sdavidxu 27123974Sdavidxu#include <sys/cdefs.h> 28123974Sdavidxu__FBSDID("$FreeBSD$"); 29123974Sdavidxu 30174112Sdeischen#include "namespace.h" 31123974Sdavidxu#include <errno.h> 32123974Sdavidxu#include <signal.h> 33174112Sdeischen#include "un-namespace.h" 34123974Sdavidxu#include "thr_private.h" 35123974Sdavidxu 36174112Sdeischenint _sigaltstack(stack_t *_ss, stack_t *_oss); 37174112Sdeischen 38123974Sdavidxu__weak_reference(_sigaltstack, sigaltstack); 39123974Sdavidxu 40123974Sdavidxuint 41123974Sdavidxu_sigaltstack(stack_t *_ss, stack_t *_oss) 42123974Sdavidxu{ 43123974Sdavidxu struct pthread *curthread = _get_curthread(); 44123974Sdavidxu stack_t ss, oss; 45123974Sdavidxu int oonstack, errsave, ret; 46123974Sdavidxu kse_critical_t crit; 47123974Sdavidxu 48123974Sdavidxu if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) { 49123974Sdavidxu crit = _kse_critical_enter(); 50123974Sdavidxu ret = __sys_sigaltstack(_ss, _oss); 51123974Sdavidxu errsave = errno; 52123974Sdavidxu /* Get a copy */ 53123974Sdavidxu if (ret == 0 && _ss != NULL) 54123974Sdavidxu curthread->sigstk = *_ss; 55123974Sdavidxu _kse_critical_leave(crit); 56123974Sdavidxu errno = errsave; 57123974Sdavidxu return (ret); 58123974Sdavidxu } 59123974Sdavidxu 60123974Sdavidxu if (_ss) 61123974Sdavidxu ss = *_ss; 62123974Sdavidxu if (_oss) 63123974Sdavidxu oss = *_oss; 64123974Sdavidxu 65123974Sdavidxu /* Should get and set stack in atomic way */ 66123974Sdavidxu crit = _kse_critical_enter(); 67123974Sdavidxu oonstack = _thr_sigonstack(&ss); 68123974Sdavidxu if (_oss != NULL) { 69123974Sdavidxu oss = curthread->sigstk; 70123974Sdavidxu oss.ss_flags = (curthread->sigstk.ss_flags & SS_DISABLE) 71123974Sdavidxu ? SS_DISABLE : ((oonstack) ? SS_ONSTACK : 0); 72123974Sdavidxu } 73123974Sdavidxu 74123974Sdavidxu if (_ss != NULL) { 75123974Sdavidxu if (oonstack) { 76123974Sdavidxu _kse_critical_leave(crit); 77124056Sdavidxu errno = EPERM; 78124056Sdavidxu return (-1); 79123974Sdavidxu } 80123974Sdavidxu if ((ss.ss_flags & ~SS_DISABLE) != 0) { 81123974Sdavidxu _kse_critical_leave(crit); 82124056Sdavidxu errno = EINVAL; 83124056Sdavidxu return (-1); 84123974Sdavidxu } 85123974Sdavidxu if (!(ss.ss_flags & SS_DISABLE)) { 86123974Sdavidxu if (ss.ss_size < MINSIGSTKSZ) { 87123974Sdavidxu _kse_critical_leave(crit); 88124056Sdavidxu errno = ENOMEM; 89124056Sdavidxu return (-1); 90123974Sdavidxu } 91123974Sdavidxu curthread->sigstk = ss; 92123974Sdavidxu } else { 93123974Sdavidxu curthread->sigstk.ss_flags |= SS_DISABLE; 94123974Sdavidxu } 95123974Sdavidxu } 96123974Sdavidxu _kse_critical_leave(crit); 97123974Sdavidxu if (_oss != NULL) 98123974Sdavidxu *_oss = oss; 99123974Sdavidxu return (0); 100123974Sdavidxu} 101123974Sdavidxu 102123974Sdavidxuint 103123974Sdavidxu_thr_sigonstack(void *sp) 104123974Sdavidxu{ 105123974Sdavidxu struct pthread *curthread = _get_curthread(); 106123974Sdavidxu 107123974Sdavidxu return ((curthread->sigstk.ss_flags & SS_DISABLE) == 0 ? 108123974Sdavidxu (((size_t)sp - (size_t)curthread->sigstk.ss_sp) < curthread->sigstk.ss_size) 109123974Sdavidxu : 0); 110123974Sdavidxu} 111123974Sdavidxu 112