/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include <sys/param.h> #include <sys/types.h> #include <sys/sysmacros.h> #include <sys/systm.h> #include <sys/user.h> #include <sys/errno.h> #include <sys/proc.h> #include <sys/fault.h> #include <sys/signal.h> #include <sys/siginfo.h> #include <sys/debug.h> int sigaction(int sig, struct sigaction *actp, struct sigaction *oactp) { struct sigaction act; struct sigaction oact; k_sigset_t set; proc_t *p; user_t *ua; int sigcld_look = 0; if (sig <= 0 || sig >= NSIG || (actp != NULL && sigismember(&cantmask, sig))) return (set_errno(EINVAL)); /* * act and oact might be the same address, so copyin act first. */ if (actp) { #if defined(__sparc) void (*handler)(); #endif if (copyin(actp, &act, sizeof (act))) return (set_errno(EFAULT)); #if defined(__sparc) /* * Check alignment of handler */ handler = act.sa_handler; if (handler != SIG_IGN && handler != SIG_DFL && ((uintptr_t)handler & 0x3) != 0) return (set_errno(EINVAL)); #endif } p = curproc; ua = PTOU(p); mutex_enter(&p->p_lock); if (oactp) { int flags; void (*disp)(); disp = ua->u_signal[sig - 1]; flags = 0; if (disp != SIG_DFL && disp != SIG_IGN) { set = ua->u_sigmask[sig-1]; if (sigismember(&p->p_siginfo, sig)) flags |= SA_SIGINFO; if (sigismember(&ua->u_sigrestart, sig)) flags |= SA_RESTART; if (sigismember(&ua->u_sigonstack, sig)) flags |= SA_ONSTACK; if (sigismember(&ua->u_sigresethand, sig)) flags |= SA_RESETHAND; if (sigismember(&ua->u_signodefer, sig)) flags |= SA_NODEFER; } else sigemptyset(&set); if (sig == SIGCLD) { if (p->p_flag & SNOWAIT) flags |= SA_NOCLDWAIT; if (!(p->p_flag & SJCTL)) flags |= SA_NOCLDSTOP; } oact.sa_handler = disp; oact.sa_flags = flags; sigktou(&set, &oact.sa_mask); } if (actp) { if (sig == SIGCLD) sigcld_look = 1; sigutok(&act.sa_mask, &set); setsigact(sig, act.sa_handler, set, act.sa_flags); } mutex_exit(&p->p_lock); if (sigcld_look) sigcld_repost(); if (oactp && copyout(&oact, oactp, sizeof (oact))) return (set_errno(EFAULT)); return (0); } #ifdef _SYSCALL32_IMPL int sigaction32(int sig, struct sigaction32 *actp, struct sigaction32 *oactp) { struct sigaction32 act32; struct sigaction32 oact32; k_sigset_t set; proc_t *p; user_t *ua; int sigcld_look = 0; if (sig <= 0 || sig >= NSIG || (actp != NULL && sigismember(&cantmask, sig))) return (set_errno(EINVAL)); /* * act and oact might be the same address, so copyin act first. */ if (actp) { #if defined(__sparc) void (*handler)(); #endif if (copyin(actp, &act32, sizeof (act32))) return (set_errno(EFAULT)); #if defined(__sparc) /* * Check alignment of handler */ handler = (void (*)())(uintptr_t)act32.sa_handler; if (handler != SIG_IGN && handler != SIG_DFL && ((uintptr_t)handler & 0x3) != 0) return (set_errno(EINVAL)); #endif } p = curproc; ua = PTOU(p); mutex_enter(&p->p_lock); if (oactp) { int flags; void (*disp)(); disp = ua->u_signal[sig - 1]; flags = 0; if (disp != SIG_DFL && disp != SIG_IGN) { set = ua->u_sigmask[sig-1]; if (sigismember(&p->p_siginfo, sig)) flags |= SA_SIGINFO; if (sigismember(&ua->u_sigrestart, sig)) flags |= SA_RESTART; if (sigismember(&ua->u_sigonstack, sig)) flags |= SA_ONSTACK; if (sigismember(&ua->u_sigresethand, sig)) flags |= SA_RESETHAND; if (sigismember(&ua->u_signodefer, sig)) flags |= SA_NODEFER; } else sigemptyset(&set); if (sig == SIGCLD) { if (p->p_flag & SNOWAIT) flags |= SA_NOCLDWAIT; if (!(p->p_flag & SJCTL)) flags |= SA_NOCLDSTOP; } oact32.sa_handler = (caddr32_t)(uintptr_t)disp; oact32.sa_flags = flags; sigktou(&set, &oact32.sa_mask); } if (actp) { if (sig == SIGCLD) sigcld_look = 1; sigutok(&act32.sa_mask, &set); setsigact(sig, (void (*)())(uintptr_t)act32.sa_handler, set, act32.sa_flags); } mutex_exit(&p->p_lock); if (sigcld_look) sigcld_repost(); if (oactp && copyout(&oact32, oactp, sizeof (oact32))) return (set_errno(EFAULT)); return (0); } #endif /* _SYSCALL32_IMPL */