1/*- 2 * Copyright (c) 2003 David Xu <davidxu@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD$"); 29 30#include "namespace.h" 31#include <errno.h> 32#include <signal.h> 33#include "un-namespace.h" 34#include "thr_private.h" 35 36int _sigaltstack(stack_t *_ss, stack_t *_oss); 37 38__weak_reference(_sigaltstack, sigaltstack); 39 40int 41_sigaltstack(stack_t *_ss, stack_t *_oss) 42{ 43 struct pthread *curthread = _get_curthread(); 44 stack_t ss, oss; 45 int oonstack, errsave, ret; 46 kse_critical_t crit; 47 48 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) { 49 crit = _kse_critical_enter(); 50 ret = __sys_sigaltstack(_ss, _oss); 51 errsave = errno; 52 /* Get a copy */ 53 if (ret == 0 && _ss != NULL) 54 curthread->sigstk = *_ss; 55 _kse_critical_leave(crit); 56 errno = errsave; 57 return (ret); 58 } 59 60 if (_ss) 61 ss = *_ss; 62 if (_oss) 63 oss = *_oss; 64 65 /* Should get and set stack in atomic way */ 66 crit = _kse_critical_enter(); 67 oonstack = _thr_sigonstack(&ss); 68 if (_oss != NULL) { 69 oss = curthread->sigstk; 70 oss.ss_flags = (curthread->sigstk.ss_flags & SS_DISABLE) 71 ? SS_DISABLE : ((oonstack) ? SS_ONSTACK : 0); 72 } 73 74 if (_ss != NULL) { 75 if (oonstack) { 76 _kse_critical_leave(crit); 77 errno = EPERM; 78 return (-1); 79 } 80 if ((ss.ss_flags & ~SS_DISABLE) != 0) { 81 _kse_critical_leave(crit); 82 errno = EINVAL; 83 return (-1); 84 } 85 if (!(ss.ss_flags & SS_DISABLE)) { 86 if (ss.ss_size < MINSIGSTKSZ) { 87 _kse_critical_leave(crit); 88 errno = ENOMEM; 89 return (-1); 90 } 91 curthread->sigstk = ss; 92 } else { 93 curthread->sigstk.ss_flags |= SS_DISABLE; 94 } 95 } 96 _kse_critical_leave(crit); 97 if (_oss != NULL) 98 *_oss = oss; 99 return (0); 100} 101 102int 103_thr_sigonstack(void *sp) 104{ 105 struct pthread *curthread = _get_curthread(); 106 107 return ((curthread->sigstk.ss_flags & SS_DISABLE) == 0 ? 108 (((size_t)sp - (size_t)curthread->sigstk.ss_sp) < curthread->sigstk.ss_size) 109 : 0); 110} 111 112