Index: head/sys/alpha/include/signal.h =================================================================== --- head/sys/alpha/include/signal.h (revision 68519) +++ head/sys/alpha/include/signal.h (revision 68520) @@ -1,93 +1,99 @@ /* $FreeBSD$ */ /* From: NetBSD: signal.h,v 1.3 1997/04/06 08:47:43 cgd Exp */ /* * Copyright (c) 1994, 1995 Carnegie-Mellon University. * All rights reserved. * * Author: Chris G. Demetriou * * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ #ifndef _ALPHA_SIGNAL_H_ #define _ALPHA_SIGNAL_H_ typedef long sig_atomic_t; #ifndef _ANSI_SOURCE /* + * Minimum signal stack size. The current signal frame + * for Alpha is 808 bytes large. + */ +#define MINSIGSTKSZ (1024 * 4) + +/* * Information pushed on stack when a signal is delivered. * This is used by the kernel to restore state following * execution of the signal handler. It is also made available * to the handler to allow it to restore state properly if * a non-standard exit is performed. * * Note that sc_regs[] and sc_fpregs[]+sc_fpcr are inline * representations of 'struct reg' and 'struct fpreg', respectively. */ typedef unsigned int osigset_t; struct osigcontext { long sc_onstack; /* sigstack state to restore */ long sc_mask; /* signal mask to restore */ long sc_pc; /* pc to restore */ long sc_ps; /* ps to restore */ unsigned long sc_regs[32]; /* integer register set (see above) */ long sc_ownedfp; /* fp has been used */ unsigned long sc_fpregs[32]; /* FP register set (see above) */ unsigned long sc_fpcr; /* FP control register (see above) */ unsigned long sc_fp_control; /* FP software control word */ long sc_reserved[2]; /* XXX */ long sc_xxx1[2]; /* sc_ssize, sc_sbase on DUX */ unsigned long sc_traparg_a0; /* a0 argument to trap at exception */ unsigned long sc_traparg_a1; /* a1 argument to trap at exception */ unsigned long sc_traparg_a2; /* a2 argument to trap at exception */ long sc_xxx2[3]; /* sc_fp_trap_pc, sc_fp_trigger_sum, sc_fp_trigger_inst */ }; /* * The sequence of the fields should match those in * mcontext_t. Keep them in sync! */ struct sigcontext { sigset_t sc_mask; /* signal mask to restore */ long sc_onstack; /* sigstack state to restore */ unsigned long sc_regs[32]; /* integer register set (see above) */ long sc_ps; /* ps to restore */ long sc_pc; /* pc to restore */ unsigned long sc_traparg_a0; /* a0 argument to trap at exception */ unsigned long sc_traparg_a1; /* a1 argument to trap at exception */ unsigned long sc_traparg_a2; /* a2 argument to trap at exception */ unsigned long sc_fpregs[32]; /* FP register set (see above) */ unsigned long sc_fpcr; /* FP control register (see above) */ unsigned long sc_fp_control; /* FP software control word */ long sc_ownedfp; /* fp has been used */ long sc_xxx1[2]; /* sc_ssize, sc_sbase on DUX */ long sc_xxx2[3]; /* sc_fp_trap_pc, sc_fp_trigger_sum, sc_fp_trigger_inst */ long sc_reserved[2]; /* XXX */ }; #define sc_sp sc_regs[R_SP] #endif /* !_ANSI_SOURCE */ #endif /* !_ALPHA_SIGNAL_H_*/ Index: head/sys/alpha/linux/linux.h =================================================================== --- head/sys/alpha/linux/linux.h (revision 68519) +++ head/sys/alpha/linux/linux.h (revision 68520) @@ -1,432 +1,434 @@ /*- * Copyright (c) 1994-1996 Søren Schmidt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _ALPHA_LINUX_LINUX_H_ #define _ALPHA_LINUX_LINUX_H_ #include #ifdef MALLOC_DECLARE MALLOC_DECLARE(M_LINUX); #endif /* * Miscellaneous */ #define LINUX_NAME_MAX 255 #define LINUX_MAX_UTSNAME 65 /* Scheduling policies */ #define LINUX_SCHED_OTHER 0 #define LINUX_SCHED_FIFO 1 #define LINUX_SCHED_RR 2 /* Resource limits */ #define LINUX_RLIMIT_CPU 0 #define LINUX_RLIMIT_FSIZE 1 #define LINUX_RLIMIT_DATA 2 #define LINUX_RLIMIT_STACK 3 #define LINUX_RLIMIT_CORE 4 #define LINUX_RLIMIT_RSS 5 #define LINUX_RLIMIT_AS 7 /* address space limit */ #define LINUX_RLIMIT_NPROC 8 #define LINUX_RLIMIT_NOFILE 6 #define LINUX_RLIMIT_MEMLOCK 9 #define LINUX_RLIM_NLIMITS 10 /* mmap options */ #define LINUX_MAP_SHARED 0x0001 #define LINUX_MAP_PRIVATE 0x0002 #define LINUX_MAP_ANON 0x0010 #define LINUX_MAP_FIXED 0x0100 #define LINUX_MAP_GROWSDOWN 0x1000 typedef char * linux_caddr_t; typedef long linux_clock_t; typedef u_short linux_dev_t; typedef u_short linux_gid_t; typedef u_long linux_ino_t; typedef int linux_key_t; /* XXX */ typedef u_short linux_mode_t; typedef u_short linux_nlink_t; typedef long linux_off_t; typedef int linux_pid_t; /*typedef u_int linux_size_t; */ typedef long linux_time_t; typedef u_short linux_uid_t; typedef struct { int val[2]; } linux_fsid_t; struct linux_new_utsname { char sysname[LINUX_MAX_UTSNAME]; char nodename[LINUX_MAX_UTSNAME]; char release[LINUX_MAX_UTSNAME]; char version[LINUX_MAX_UTSNAME]; char machine[LINUX_MAX_UTSNAME]; char domainname[LINUX_MAX_UTSNAME]; }; /* * Signalling */ #define LINUX_SIGHUP 1 #define LINUX_SIGINT 2 #define LINUX_SIGQUIT 3 #define LINUX_SIGILL 4 #define LINUX_SIGTRAP 5 #define LINUX_SIGABRT 6 #define LINUX_SIGIOT LINUX_SIGABRT #define LINUX_SIGBUS 7 #define LINUX_SIGFPE 8 #define LINUX_SIGKILL 9 #define LINUX_SIGUSR1 10 #define LINUX_SIGSEGV 11 #define LINUX_SIGUSR2 12 #define LINUX_SIGPIPE 13 #define LINUX_SIGALRM 14 #define LINUX_SIGTERM 15 #define LINUX_SIGSTKFLT 16 #define LINUX_SIGCHLD 17 #define LINUX_SIGCONT 18 #define LINUX_SIGSTOP 19 #define LINUX_SIGTSTP 20 #define LINUX_SIGTTIN 21 #define LINUX_SIGTTOU 22 #define LINUX_SIGURG 23 #define LINUX_SIGXCPU 24 #define LINUX_SIGXFSZ 25 #define LINUX_SIGVTALRM 26 #define LINUX_SIGPROF 27 #define LINUX_SIGWINCH 28 #define LINUX_SIGIO 29 #define LINUX_SIGPOLL LINUX_SIGIO #define LINUX_SIGPWR 30 #define LINUX_SIGTBLSZ 31 #define LINUX_SIGUNUSED LINUX_SIGTBLSZ #define LINUX_NSIG 64 /* sigaction flags */ #define LINUX_SA_ONSTACK 0x00000001 #define LINUX_SA_RESTART 0x00000002 #define LINUX_SA_NOCLDSTOP 0x00000004 #define LINUX_SA_NODEFER 0x00000008 #define LINUX_SA_RESETHAND 0x00000010 #define LINUX_SA_NOCLDWAIT 0x00000020 #define LINUX_SA_SIGINFO 0x00000040 #define LINUX_SA_RESTORER 0x04000000 #define LINUX_SA_INTERRUPT 0x20000000 #define LINUX_SA_NOMASK LINUX_SA_NODEFER #define LINUX_SA_ONESHOT LINUX_SA_RESETHAND /* sigprocmask actions */ #define LINUX_SIG_BLOCK 0 #define LINUX_SIG_UNBLOCK 1 #define LINUX_SIG_SETMASK 2 /* sigset_t macros */ #define LINUX_SIGEMPTYSET(set) (set).__bits[0] = (set).__bits[1] = 0 #define LINUX_SIGISMEMBER(set, sig) SIGISMEMBER(set, sig) #define LINUX_SIGADDSET(set, sig) SIGADDSET(set, sig) +#define LINUX_MINSIGSTKSZ 4096 + typedef void (*linux_handler_t)(int); typedef u_long linux_osigset_t; typedef struct { u_int __bits[2]; /* u_long __bits[1];*/ } linux_sigset_t; typedef struct { linux_handler_t lsa_handler; linux_osigset_t lsa_mask; u_long lsa_flags; void (*lsa_restorer)(void); } linux_osigaction_t; typedef struct { linux_handler_t lsa_handler; u_long lsa_flags; void (*lsa_restorer)(void); linux_sigset_t lsa_mask; } linux_sigaction_t; #if 0 typedef struct { void *ss_sp; int ss_flags; linux_size_t ss_size; } linux_stack_t; #endif /* * The Linux sigcontext */ struct linux_sigcontext { long sc_onstack; long sc_mask; long sc_pc; long sc_ps; long sc_regs[32]; long sc_ownedfp; long sc_fpregs[32]; u_long sc_fpcr; u_long sc_fp_control; u_long sc_reserved1, sc_reserved2; u_long sc_ssize; char * sc_sbase; u_long sc_traparg_a0; u_long sc_traparg_a1; u_long sc_traparg_a2; u_long sc_fp_trap_pc; u_long sc_fp_trigger_sum; u_long sc_fp_trigger_inst; }; /* * We make the stack look like Linux expects it when calling a signal * handler, but use the BSD way of calling the handler and sigreturn(). * This means that we need to pass the pointer to the handler too. * It is appended to the frame to not interfere with the rest of it. */ struct linux_sigframe { int sf_sig; struct linux_sigcontext sf_sc; linux_handler_t sf_handler; }; /* * Pluggable ioctl handlers */ struct linker_set; struct linux_ioctl_args; struct proc; typedef int linux_ioctl_function_t(struct proc *, struct linux_ioctl_args *); struct linux_ioctl_handler { linux_ioctl_function_t *func; int low, high; }; int linux_ioctl_register_handler(struct linux_ioctl_handler *h); int linux_ioctl_register_handlers(struct linker_set *s); int linux_ioctl_unregister_handler(struct linux_ioctl_handler *h); int linux_ioctl_unregister_handlers(struct linker_set *s); /* * open/fcntl flags */ #define LINUX_O_RDONLY 00 #define LINUX_O_WRONLY 01 #define LINUX_O_RDWR 02 #define LINUX_O_NONBLOCK 04 #define LINUX_O_APPEND 010 #define LINUX_O_CREAT 01000 #define LINUX_O_TRUNC 02000 #define LINUX_O_EXCL 04000 #define LINUX_O_NOCTTY 010000 #define LINUX_O_NDELAY LINUX_O_NONBLOCK #define LINUX_O_SYNC 040000 #define LINUX_FASYNC 020000 /* fcntl flags */ #define LINUX_F_DUPFD 0 #define LINUX_F_GETFD 1 #define LINUX_F_SETFD 2 #define LINUX_F_GETFL 3 #define LINUX_F_SETFL 4 #define LINUX_F_GETLK 5 #define LINUX_F_SETLK 6 #define LINUX_F_SETLKW 7 #define LINUX_F_SETOWN 8 #define LINUX_F_GETOWN 9 #define LINUX_F_RDLCK 0 #define LINUX_F_WRLCK 1 #define LINUX_F_UNLCK 2 /* * SystemV IPC defines */ #define LINUX_SEMOP 1 #define LINUX_SEMGET 2 #define LINUX_SEMCTL 3 #define LINUX_MSGSND 11 #define LINUX_MSGRCV 12 #define LINUX_MSGGET 13 #define LINUX_MSGCTL 14 #define LINUX_SHMAT 21 #define LINUX_SHMDT 22 #define LINUX_SHMGET 23 #define LINUX_SHMCTL 24 #define LINUX_IPC_RMID 0 #define LINUX_IPC_SET 1 #define LINUX_IPC_STAT 2 #define LINUX_IPC_INFO 3 #define LINUX_SHM_LOCK 11 #define LINUX_SHM_UNLOCK 12 #define LINUX_SHM_STAT 13 #define LINUX_SHM_INFO 14 #define LINUX_SHM_RDONLY 0x1000 #define LINUX_SHM_RND 0x2000 #define LINUX_SHM_REMAP 0x4000 /* semctl commands */ #define LINUX_GETPID 11 #define LINUX_GETVAL 12 #define LINUX_GETALL 13 #define LINUX_GETNCNT 14 #define LINUX_GETZCNT 15 #define LINUX_SETVAL 16 #define LINUX_SETALL 17 /* * Socket defines */ #define LINUX_SOCKET 1 #define LINUX_BIND 2 #define LINUX_CONNECT 3 #define LINUX_LISTEN 4 #define LINUX_ACCEPT 5 #define LINUX_GETSOCKNAME 6 #define LINUX_GETPEERNAME 7 #define LINUX_SOCKETPAIR 8 #define LINUX_SEND 9 #define LINUX_RECV 10 #define LINUX_SENDTO 11 #define LINUX_RECVFROM 12 #define LINUX_SHUTDOWN 13 #define LINUX_SETSOCKOPT 14 #define LINUX_GETSOCKOPT 15 #define LINUX_SENDMSG 16 #define LINUX_RECVMSG 17 #define LINUX_AF_UNSPEC 0 #define LINUX_AF_UNIX 1 #define LINUX_AF_INET 2 #define LINUX_AF_AX25 3 #define LINUX_AF_IPX 4 #define LINUX_AF_APPLETALK 5 #define LINUX_SOL_SOCKET 1 #define LINUX_SOL_IP 0 #define LINUX_SOL_TCP 6 #define LINUX_SOL_UDP 17 #define LINUX_SOL_IPX 256 #define LINUX_SOL_AX25 257 #define LINUX_SO_DEBUG 1 #define LINUX_SO_REUSEADDR 2 #define LINUX_SO_TYPE 3 #define LINUX_SO_ERROR 4 #define LINUX_SO_DONTROUTE 5 #define LINUX_SO_BROADCAST 6 #define LINUX_SO_SNDBUF 7 #define LINUX_SO_RCVBUF 8 #define LINUX_SO_KEEPALIVE 9 #define LINUX_SO_OOBINLINE 10 #define LINUX_SO_NO_CHECK 11 #define LINUX_SO_PRIORITY 12 #define LINUX_SO_LINGER 13 #define LINUX_IP_TOS 1 #define LINUX_IP_TTL 2 #define LINUX_IP_HDRINCL 3 #define LINUX_IP_OPTIONS 4 #define LINUX_IP_MULTICAST_IF 32 #define LINUX_IP_MULTICAST_TTL 33 #define LINUX_IP_MULTICAST_LOOP 34 #define LINUX_IP_ADD_MEMBERSHIP 35 #define LINUX_IP_DROP_MEMBERSHIP 36 struct linux_sockaddr { u_short sa_family; char sa_data[14]; }; struct linux_ifmap { u_long mem_start; u_long mem_end; u_short base_addr; u_char irq; u_char dma; u_char port; }; #define LINUX_IFHWADDRLEN 6 #define LINUX_IFNAMSIZ 16 struct linux_ifreq { union { char ifrn_name[LINUX_IFNAMSIZ]; /* if name, e.g. "en0" */ } ifr_ifrn; union { struct linux_sockaddr ifru_addr; struct linux_sockaddr ifru_dstaddr; struct linux_sockaddr ifru_broadaddr; struct linux_sockaddr ifru_netmask; struct linux_sockaddr ifru_hwaddr; short ifru_flags; int ifru_metric; int ifru_mtu; struct linux_ifmap ifru_map; char ifru_slave[LINUX_IFNAMSIZ]; /* Just fits the size */ /* linux_caddr_t ifru_data; */ caddr_t ifru_data; } ifr_ifru; }; #define ifr_name ifr_ifrn.ifrn_name /* interface name */ #define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ extern char linux_sigcode[]; extern int linux_szsigcode; /*extern const char linux_emul_path[];*/ extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL]; extern struct sysentvec linux_sysvec; extern struct sysentvec elf_linux_sysvec; /* dummy struct definitions */ struct image_params; struct trapframe; #endif /* !_ALPHA_LINUX_LINUX_H_ */ Index: head/sys/alpha/linux/linux_sysvec.c =================================================================== --- head/sys/alpha/linux/linux_sysvec.c (revision 68519) +++ head/sys/alpha/linux/linux_sysvec.c (revision 68520) @@ -1,265 +1,266 @@ /*- * Copyright (c) 1994-1996 Søren Schmidt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software withough specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ /* XXX we use functions that might not exist. */ #include "opt_compat.h" #ifndef COMPAT_43 #error "Unable to compile Linux-emulator due to missing COMPAT_43 option!" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #undef szsigcode MODULE_VERSION(linux, 1); MODULE_DEPEND(linux, osf1, 1, 1, 1); MALLOC_DEFINE(M_LINUX, "linux", "Linux mode structures"); #if BYTE_ORDER == LITTLE_ENDIAN #define SHELLMAGIC 0x2123 /* #! */ #else #define SHELLMAGIC 0x2321 #endif extern struct linker_set linux_ioctl_handler_set; static int elf_linux_fixup __P((long **stack_base, struct image_params *iparams)); static int elf_linux_fixup(long **stack_base, struct image_params *imgp) { long *pos; Elf64_Auxargs *args; args = (Elf64_Auxargs *)imgp->auxargs; pos = *stack_base + (imgp->argc + imgp->envc + 2); if (args->trace) { AUXARGS_ENTRY(pos, AT_DEBUG, 1); } if (args->execfd != -1) { AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); } AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); AUXARGS_ENTRY(pos, AT_PHENT, args->phent); AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); AUXARGS_ENTRY(pos, AT_BASE, args->base); AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_cred->p_ruid); AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_cred->p_svuid); AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_cred->p_rgid); AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_cred->p_svgid); AUXARGS_ENTRY(pos, AT_NULL, 0); free(imgp->auxargs, M_TEMP); imgp->auxargs = NULL; (*stack_base)--; **stack_base = (long)imgp->argc; return 0; } extern int _ucodesel, _udatasel; void osf1_sendsig __P((sig_t, int , sigset_t *, u_long )); void osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code); /* * If a linux binary is exec'ing something, try this image activator * first. We override standard shell script execution in order to * be able to modify the interpreter path. We only do this if a linux * binary is doing the exec, so we do not create an EXEC module for it. */ static int exec_linux_imgact_try __P((struct image_params *iparams)); static int exec_linux_imgact_try(imgp) struct image_params *imgp; { const char *head; int error; head = (const char *)imgp->image_header; error = -1; /* * The interpreter for shell scripts run from a linux binary needs * to be located in /compat/linux if possible in order to recursively * maintain linux path emulation. */ if (((const short *)head)[0] == SHELLMAGIC) { /* * Run our normal shell image activator. If it succeeds * attempt to use the alternate path for the interpreter. If * an alternate path is found, use our stringspace to store it. */ if ((error = exec_shell_imgact(imgp)) == 0) { char *rpath = NULL; linux_emul_find(imgp->proc, NULL, linux_emul_path, imgp->interpreter_name, &rpath, 0); if (rpath != imgp->interpreter_name) { int len = strlen(rpath) + 1; if (len <= MAXSHELLCMDLEN) { memcpy(imgp->interpreter_name, rpath, len); } free(rpath, M_TEMP); } } } return(error); } /* * To maintain OSF/1 compat, linux uses BSD signals & errnos on their * alpha port. This greatly simplfies things for us. */ struct sysentvec elf_linux_sysvec = { LINUX_SYS_MAXSYSCALL, linux_sysent, 0, 0, 0, 0, 0, 0, elf_linux_fixup, osendsig, linux_sigcode, &linux_szsigcode, 0, "Linux ELF", elf_coredump, - exec_linux_imgact_try + exec_linux_imgact_try, + LINUX_MINSIGSTKSZ }; static Elf64_Brandinfo linux_brand = { ELFOSABI_LINUX, "/compat/linux", "/lib/ld-linux.so.1", &elf_linux_sysvec }; static Elf64_Brandinfo linux_glibc2brand = { ELFOSABI_LINUX, "/compat/linux", "/lib/ld-linux.so.2", &elf_linux_sysvec }; Elf64_Brandinfo *linux_brandlist[] = { &linux_brand, &linux_glibc2brand, NULL }; static int linux_elf_modevent(module_t mod, int type, void *data) { Elf64_Brandinfo **brandinfo; int error; error = 0; switch(type) { case MOD_LOAD: for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL; ++brandinfo) if (elf_insert_brand_entry(*brandinfo) < 0) error = EINVAL; if (error) printf("cannot insert Linux elf brand handler\n"); else { linux_ioctl_register_handlers(&linux_ioctl_handler_set); if (bootverbose) printf("Linux-ELF exec handler installed\n"); } break; case MOD_UNLOAD: linux_ioctl_unregister_handlers(&linux_ioctl_handler_set); for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL; ++brandinfo) if (elf_brand_inuse(*brandinfo)) error = EBUSY; if (error == 0) { for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL; ++brandinfo) if (elf_remove_brand_entry(*brandinfo) < 0) error = EINVAL; } if (error) printf("Could not deinstall ELF interpreter entry\n"); else if (bootverbose) printf("Linux-elf exec handler removed\n"); break; default: break; } return error; } static moduledata_t linux_elf_mod = { "linuxelf", linux_elf_modevent, 0 }; DUMMY(rt_sigreturn); DECLARE_MODULE(linuxelf, linux_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY); Index: head/sys/alpha/osf1/osf1.h =================================================================== --- head/sys/alpha/osf1/osf1.h (revision 68519) +++ head/sys/alpha/osf1/osf1.h (revision 68520) @@ -1,297 +1,298 @@ /* * Copyright (c) 1998-1999 Andrew Gallatin * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software withough specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ extern struct sysent osf1_sysent[]; extern int bsd_to_osf1_sig[]; extern int bsd_to_osf1_errno[]; +#define OSF1_MINSIGSTKSZ 4096 /* osf/1 ioctls */ #define OSF1_IOCPARM_MASK 0x1fff /* parameter length, at most 13 bits */ #define OSF1_IOCPARM_LEN(x) (((x) >> 16) & OSF1_IOCPARM_MASK) #define OSF1_IOCGROUP(x) (((x) >> 8) & 0xff) #define OSF1_IOCPARM_MAX NBPG /* max size of ioctl */ #define OSF1_IOC_VOID 0x20000000 /* no parameters */ #define OSF1_IOC_OUT 0x40000000 /* copy out parameters */ #define OSF1_IOC_IN 0x80000000 /* copy in parameters */ #define OSF1_IOC_INOUT (OSF1_IOC_IN|OSF1_IOC_OUT) #define OSF1_IOC_DIRMASK 0xe0000000 /* mask for IN/OUT/VOID */ #define OSF1_IOCCMD(x) ((x) & 0xff) /* for get sysinfo */ #define OSF_GET_MAX_UPROCS 2 #define OSF_GET_PHYSMEM 19 #define OSF_GET_MAX_CPU 30 #define OSF_GET_IEEE_FP_CONTROL 45 #define OSF_GET_CPUS_IN_BOX 55 #define OSF_GET_CPU_INFO 59 #define OSF_GET_PROC_TYPE 60 #define OSF_GET_HWRPB 101 #define OSF_GET_PLATFORM_NAME 103 struct osf1_cpu_info { int current_cpu; int cpus_in_box; int cpu_type; int ncpus; u_int64_t cpus_present; u_int64_t cpus_running; u_int64_t cpu_binding; u_int64_t cpu_ex_binding; int mhz; int unused[3]; }; /* for set sysinfo */ #define OSF_SET_IEEE_FP_CONTROL 14 /* for rlimit */ #define OSF1_RLIMIT_LASTCOMMON 5 /* last one that's common */ #define OSF1_RLIMIT_NOFILE 6 /* OSF1's RLIMIT_NOFILE */ #define OSF1_RLIMIT_NLIMITS 8 /* Number of OSF1 rlimits */ /* mmap flags */ #define OSF1_MAP_SHARED 0x001 #define OSF1_MAP_PRIVATE 0x002 #define OSF1_MAP_ANONYMOUS 0x010 #define OSF1_MAP_FILE 0x000 #define OSF1_MAP_TYPE 0x0f0 #define OSF1_MAP_FIXED 0x100 #define OSF1_MAP_HASSEMAPHORE 0x200 #define OSF1_MAP_INHERIT 0x400 #define OSF1_MAP_UNALIGNED 0x800 /* msync flags */ #define OSF1_MS_ASYNC 1 #define OSF1_MS_SYNC 2 #define OSF1_MS_INVALIDATE 4 #define OSF1_F_DUPFD 0 #define OSF1_F_GETFD 1 #define OSF1_F_SETFD 2 #define OSF1_F_GETFL 3 #define OSF1_F_SETFL 4 #define _OSF1_PC_CHOWN_RESTRICTED 10 #define _OSF1_PC_LINK_MAX 11 #define _OSF1_PC_MAX_CANON 12 #define _OSF1_PC_MAX_INPUT 13 #define _OSF1_PC_NAME_MAX 14 #define _OSF1_PC_NO_TRUNC 15 #define _OSF1_PC_PATH_MAX 16 #define _OSF1_PC_PIPE_BUF 17 #define _OSF1_PC_VDISABLE 18 #define OSF1_FNONBLOCK 0x00004 /* XXX OSF1_O_NONBLOCK */ #define OSF1_FAPPEND 0x00008 /* XXX OSF1_O_APPEND */ #define OSF1_FDEFER 0x00020 #define OSF1_FASYNC 0x00040 #define OSF1_FCREAT 0x00200 #define OSF1_FTRUNC 0x00400 #define OSF1_FEXCL 0x00800 #define OSF1_FSYNC 0x04000 /* XXX OSF1_O_SYNC */ #define OSF1_FNDELAY 0x08000 #define OSF1_RB_ASKNAME 0x001 #define OSF1_RB_SINGLE 0x002 #define OSF1_RB_NOSYNC 0x004 #define OSF1_RB_HALT 0x008 #define OSF1_RB_INITNAME 0x010 #define OSF1_RB_DFLTROOT 0x020 #define OSF1_RB_ALTBOOT 0x040 #define OSF1_RB_UNIPROC 0x080 #define OSF1_RB_ALLFLAGS 0x0ff /* all of the above */ /* * osf/1 uses ints in its struct timeval, this means that * any syscalls which means that any system calls using * timevals need to be intercepted. */ struct osf1_timeval { int tv_sec; /* seconds */ int tv_usec; /* microseconds */ }; struct osf1_itimerval { struct osf1_timeval it_interval; /* timer interval */ struct osf1_timeval it_value; /* current value */ }; #define TV_CP(src,dst) {dst.tv_usec = src.tv_usec; dst.tv_sec = src.tv_sec;} #define timersub(tvp, uvp, vvp) \ do { \ (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ if ((vvp)->tv_usec < 0) { \ (vvp)->tv_sec--; \ (vvp)->tv_usec += 1000000; \ } \ } while (0) struct osf1_rusage { struct osf1_timeval ru_utime; /* user time used */ struct osf1_timeval ru_stime; /* system time used */ long ru_maxrss; /* max resident set size */ #define ru_first ru_ixrss long ru_ixrss; /* integral shared memory size */ long ru_idrss; /* integral unshared data " */ long ru_isrss; /* integral unshared stack " */ long ru_minflt; /* page reclaims */ long ru_majflt; /* page faults */ long ru_nswap; /* swaps */ long ru_inblock; /* block input operations */ long ru_oublock; /* block output operations */ long ru_msgsnd; /* messages sent */ long ru_msgrcv; /* messages received */ long ru_nsignals; /* signals received */ long ru_nvcsw; /* voluntary context switches */ long ru_nivcsw; /* involuntary " */ #define ru_last ru_nivcsw }; #define OSF1_USC_GET 1 #define OSF1_USC_SET 2 #define OSF1_USW_NULLP 0x100 /* File system type numbers. */ #define OSF1_MOUNT_NONE 0 #define OSF1_MOUNT_UFS 1 #define OSF1_MOUNT_NFS 2 #define OSF1_MOUNT_MFS 3 #define OSF1_MOUNT_PC 4 #define OSF1_MOUNT_S5FS 5 #define OSF1_MOUNT_CDFS 6 #define OSF1_MOUNT_DFS 7 #define OSF1_MOUNT_EFS 8 #define OSF1_MOUNT_PROCFS 9 #define OSF1_MOUNT_MSFS 10 #define OSF1_MOUNT_FFM 11 #define OSF1_MOUNT_FDFS 12 #define OSF1_MOUNT_ADDON 13 #define OSF1_MOUNT_MAXTYPE OSF1_MOUNT_ADDON #define OSF1_MNT_WAIT 0x1 #define OSF1_MNT_NOWAIT 0x2 #define OSF1_MNT_FORCE 0x1 #define OSF1_MNT_NOFORCE 0x2 /* acceptable flags for various calls */ #define OSF1_GETFSSTAT_FLAGS (OSF1_MNT_WAIT|OSF1_MNT_NOWAIT) #define OSF1_MOUNT_FLAGS 0xffffffff /* XXX */ #define OSF1_UNMOUNT_FLAGS (OSF1_MNT_FORCE|OSF1_MNT_NOFORCE) struct osf1_statfs { int16_t f_type; /* 0 */ int16_t f_flags; /* 2 */ int32_t f_fsize; /* 4 */ int32_t f_bsize; /* 8 */ int32_t f_blocks; /* 12 */ int32_t f_bfree; /* 16 */ int32_t f_bavail; /* 20 */ int32_t f_files; /* 24 */ int32_t f_ffree; /* 28 */ int64_t f_fsid; /* 32 */ int32_t f_spare[9]; /* 40 (36 bytes) */ char f_mntonname[90]; /* 76 (90 bytes) */ char f_mntfromname[90]; /* 166 (90 bytes) */ char f_xxx[80]; /* 256 (80 bytes) XXX */ }; /* Arguments to mount() for various FS types. */ #ifdef notyet /* XXX */ struct osf1_ufs_args { char *fspec; int32_t exflags; u_int32_t exroot; }; struct osf1_cdfs_args { char *fspec; int32_t exflags; u_int32_t exroot; int32_t flags; }; #endif struct osf1_mfs_args { char *name; caddr_t base; u_int size; }; struct osf1_nfs_args { struct sockaddr_in *addr; void *fh; int32_t flags; int32_t wsize; int32_t rsize; int32_t timeo; int32_t retrans; char *hostname; int32_t acregmin; int32_t acregmax; int32_t acdirmin; int32_t acdirmax; char *netname; void *pathconf; }; #define OSF1_NFSMNT_SOFT 0x00001 #define OSF1_NFSMNT_WSIZE 0x00002 #define OSF1_NFSMNT_RSIZE 0x00004 #define OSF1_NFSMNT_TIMEO 0x00008 #define OSF1_NFSMNT_RETRANS 0x00010 #define OSF1_NFSMNT_HOSTNAME 0x00020 #define OSF1_NFSMNT_INT 0x00040 #define OSF1_NFSMNT_NOCONN 0x00080 #define OSF1_NFSMNT_NOAC 0x00100 /* ??? */ #define OSF1_NFSMNT_ACREGMIN 0x00200 /* ??? */ #define OSF1_NFSMNT_ACREGMAX 0x00400 /* ??? */ #define OSF1_NFSMNT_ACDIRMIN 0x00800 /* ??? */ #define OSF1_NFSMNT_ACDIRMAX 0x01000 /* ??? */ #define OSF1_NFSMNT_NOCTO 0x02000 /* ??? */ #define OSF1_NFSMNT_POSIX 0x04000 /* ??? */ #define OSF1_NFSMNT_AUTO 0x08000 /* ??? */ #define OSF1_NFSMNT_FLAGS \ (OSF1_NFSMNT_SOFT|OSF1_NFSMNT_WSIZE|OSF1_NFSMNT_RSIZE| \ OSF1_NFSMNT_TIMEO|OSF1_NFSMNT_RETRANS|OSF1_NFSMNT_HOSTNAME| \ OSF1_NFSMNT_INT|OSF1_NFSMNT_NOCONN) #define memset(x,y,z) bzero((x),(z)) Index: head/sys/alpha/osf1/osf1_sysvec.c =================================================================== --- head/sys/alpha/osf1/osf1_sysvec.c (revision 68519) +++ head/sys/alpha/osf1/osf1_sysvec.c (revision 68520) @@ -1,135 +1,136 @@ /*- * Copyright (c) 1998-1999 Andrew Gallatin * All rights reserved. * * Based heavily on linux_sysvec.c * Which is Copyright (c) 1994-1996 Søren Schmidt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software withough specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ /* XXX we use functions that might not exist. */ #include "opt_compat.h" #ifndef COMPAT_43 #error "Unable to compile Osf1-emulator due to missing COMPAT_43 option!" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include MODULE_VERSION(osf1, 1); int osf1_szsigcode; extern char sigcode[]; static int osf1_freebsd_fixup __P((long **stack_base, struct image_params *imgp)); struct sysentvec osf1_sysvec = { OSF1_SYS_MAXSYSCALL, osf1_sysent, 0x0, NSIG, bsd_to_osf1_sig, 0, 0, 0, /* trap-to-signal translation function */ osf1_freebsd_fixup, /* fixup */ osf1_sendsig, sigcode, /* use generic trampoline */ &osf1_szsigcode, /* use generic trampoline size */ 0, /* prepsyscall */ "OSF/1 ECOFF", - NULL /* we don't have an ECOFF coredump function */ - + NULL, /* we don't have an ECOFF coredump function */ + NULL, + OSF1_MINSIGSTKSZ }; /* * Do some magic to setup the stack properly for the osf1 dynamic loader * OSF/1 binaries need an auxargs vector describing the name of the * executable (must be a full path). * * If we're executing a dynamic binary, the loader will expect its * name, /sbin/loader, to be in the auxargs vectore as well. * Bear in mind that when we execute a dynamic binary, we begin by * executing the loader. The loader then takes care of mapping * executable (which is why it needs the full path) * and its requisite shared libs, then it transfers control * to the executable after calling set_program_attributes(). */ #define AUXARGS_ENTRY(pos, id, val) {suword(pos++, id); suword(pos++, val);} static int osf1_freebsd_fixup(long **stack_base, struct image_params *imgp) { char *destp; int sz; long *pos; struct ps_strings *arginfo; Osf_Auxargs *args; args = (Osf_Auxargs *)imgp->auxargs; pos = *stack_base + (imgp->argc + imgp->envc + 2); arginfo = (struct ps_strings *)PS_STRINGS; sz = *(imgp->proc->p_sysent->sv_szsigcode); destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - roundup((ARG_MAX - imgp->stringspace), sizeof(char *)); destp -= imgp->stringspace; destp -= strlen(args->executable)+2; copyout(args->executable, destp, strlen(args->executable)+1); AUXARGS_ENTRY(pos, OSF1_EXEC_NAME, (long)destp); if (args->loader) { /* the loader seems to want the name here, then it overwrites it with the FD of the executable. I have NFC what's going on here.. */ AUXARGS_ENTRY(pos, OSF1_EXEC_NAME, (long)destp); destp-= (strlen("/sbin/loader")+1); copyout("/sbin/loader", destp, strlen("/sbin/loader")+1); AUXARGS_ENTRY(pos, OSF1_LOADER_NAME, (long)destp); AUXARGS_ENTRY(pos, OSF1_LOADER_FLAGS, 0); } free(imgp->auxargs, M_TEMP); imgp->auxargs = NULL; (*stack_base)--; **stack_base = (long)imgp->argc; return 0; } Index: head/sys/amd64/include/signal.h =================================================================== --- head/sys/amd64/include/signal.h (revision 68519) +++ head/sys/amd64/include/signal.h (revision 68520) @@ -1,126 +1,132 @@ /* * Copyright (c) 1986, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)signal.h 8.1 (Berkeley) 6/11/93 * $FreeBSD$ */ #ifndef _MACHINE_SIGNAL_H_ #define _MACHINE_SIGNAL_H_ /* * Machine-dependent signal definitions */ typedef int sig_atomic_t; #if !defined(_ANSI_SOURCE) && !defined(_POSIX_SOURCE) +/* + * Minimum signal stack size. The current signal frame + * for i386 is 408 bytes large. + */ +#define MINSIGSTKSZ (512 * 4) + #include /* codes for SIGILL, SIGFPE */ /* * Information pushed on stack when a signal is delivered. * This is used by the kernel to restore state following * execution of the signal handler. It is also made available * to the handler to allow it to restore state properly if * a non-standard exit is performed. */ typedef unsigned int osigset_t; struct osigcontext { int sc_onstack; /* sigstack state to restore */ osigset_t sc_mask; /* signal mask to restore */ int sc_esp; /* machine state follows: */ int sc_ebp; int sc_isp; int sc_eip; int sc_efl; int sc_es; int sc_ds; int sc_cs; int sc_ss; int sc_edi; int sc_esi; int sc_ebx; int sc_edx; int sc_ecx; int sc_eax; int sc_gs; int sc_fs; int sc_trapno; int sc_err; }; /* * The sequence of the fields/registers in struct sigcontext should match * those in mcontext_t. */ struct sigcontext { sigset_t sc_mask; /* signal mask to restore */ int sc_onstack; /* sigstack state to restore */ int sc_gs; /* machine state (struct trapframe): */ int sc_fs; int sc_es; int sc_ds; int sc_edi; int sc_esi; int sc_ebp; int sc_isp; int sc_ebx; int sc_edx; int sc_ecx; int sc_eax; int sc_trapno; int sc_err; int sc_eip; int sc_cs; int sc_efl; int sc_esp; int sc_ss; /* * XXX FPU state is 27 * 4 bytes h/w, 1 * 4 bytes s/w (probably not * needed here), or that + 16 * 4 bytes for emulators (probably all * needed here). The "spare" bytes are mostly not spare. */ int sc_fpregs[28]; /* machine state (FPU): */ int sc_spare[17]; }; #define sc_sp sc_esp #define sc_fp sc_ebp #define sc_pc sc_eip #define sc_ps sc_efl #define sc_eflags sc_efl #endif /* !_ANSI_SOURCE && !_POSIX_SOURCE */ #endif /* !_MACHINE_SIGNAL_H_ */ Index: head/sys/compat/svr4/svr4_signal.h =================================================================== --- head/sys/compat/svr4/svr4_signal.h (revision 68519) +++ head/sys/compat/svr4/svr4_signal.h (revision 68520) @@ -1,141 +1,143 @@ /* * Copyright (c) 1998 Mark Newton * Copyright (c) 1994 Christos Zoulas * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SVR4_SIGNAL_H_ #define _SVR4_SIGNAL_H_ #include #include #define SVR4_SIGHUP 1 #define SVR4_SIGINT 2 #define SVR4_SIGQUIT 3 #define SVR4_SIGILL 4 #define SVR4_SIGTRAP 5 #define SVR4_SIGIOT 6 #define SVR4_SIGABRT 6 #define SVR4_SIGEMT 7 #define SVR4_SIGFPE 8 #define SVR4_SIGKILL 9 #define SVR4_SIGBUS 10 #define SVR4_SIGSEGV 11 #define SVR4_SIGSYS 12 #define SVR4_SIGPIPE 13 #define SVR4_SIGALRM 14 #define SVR4_SIGTERM 15 #define SVR4_SIGUSR1 16 #define SVR4_SIGUSR2 17 #define SVR4_SIGCLD 18 #define SVR4_SIGCHLD 18 #define SVR4_SIGPWR 19 #define SVR4_SIGWINCH 20 #define SVR4_SIGURG 21 #define SVR4_SIGPOLL 22 #define SVR4_SIGIO 22 #define SVR4_SIGSTOP 23 #define SVR4_SIGTSTP 24 #define SVR4_SIGCONT 25 #define SVR4_SIGTTIN 26 #define SVR4_SIGTTOU 27 #define SVR4_SIGVTALRM 28 #define SVR4_SIGPROF 29 #define SVR4_SIGXCPU 30 #define SVR4_SIGXFSZ 31 #define SVR4_NSIG 32 #define SVR4_SIGTBLSZ 31 #define SVR4_SIGNO_MASK 0x00FF #define SVR4_SIGNAL_MASK 0x0000 #define SVR4_SIGDEFER_MASK 0x0100 #define SVR4_SIGHOLD_MASK 0x0200 #define SVR4_SIGRELSE_MASK 0x0400 #define SVR4_SIGIGNORE_MASK 0x0800 #define SVR4_SIGPAUSE_MASK 0x1000 typedef void (*svr4_sig_t) __P((int, svr4_siginfo_t *, void *)); #define SVR4_SIG_DFL (svr4_sig_t) 0 #define SVR4_SIG_ERR (svr4_sig_t) -1 #define SVR4_SIG_IGN (svr4_sig_t) 1 #define SVR4_SIG_HOLD (svr4_sig_t) 2 #define SVR4_SIGNO(a) ((a) & SVR4_SIGNO_MASK) #define SVR4_SIGCALL(a) ((a) & ~SVR4_SIGNO_MASK) #define SVR4_SIG_BLOCK 1 #define SVR4_SIG_UNBLOCK 2 #define SVR4_SIG_SETMASK 3 extern int bsd_to_svr4_sig[]; extern int svr4_to_bsd_sig[]; #define SVR4_BSD2SVR4_SIG(sig) \ (((sig) <= SVR4_SIGTBLSZ) ? bsd_to_svr4_sig[_SIG_IDX(sig)] : sig) #define SVR4_SVR42BSD_SIG(sig) \ (((sig) <= SVR4_SIGTBLSZ) ? svr4_to_bsd_sig[_SIG_IDX(sig)] : sig) typedef struct { u_long bits[4]; } svr4_sigset_t; struct svr4_sigaction { int ssa_flags; svr4_sig_t ssa_handler; svr4_sigset_t ssa_mask; int ssa_reserved[2]; }; struct svr4_sigaltstack { char *ss_sp; int ss_size; int ss_flags; }; /* sa_flags */ #define SVR4_SA_ONSTACK 0x00000001 #define SVR4_SA_RESETHAND 0x00000002 #define SVR4_SA_RESTART 0x00000004 #define SVR4_SA_SIGINFO 0x00000008 #define SVR4_SA_NODEFER 0x00000010 #define SVR4_SA_NOCLDWAIT 0x00010000 /* No zombies */ #define SVR4_SA_NOCLDSTOP 0x00020000 /* No jcl */ #define SVR4_SA_ALLBITS 0x0003001f /* ss_flags */ #define SVR4_SS_ONSTACK 0x00000001 #define SVR4_SS_DISABLE 0x00000002 #define SVR4_SS_ALLBITS 0x00000003 +#define SVR4_MINSIGSTKSZ 8192 + void bsd_to_svr4_sigaltstack __P((const struct sigaltstack *, struct svr4_sigaltstack *)); void bsd_to_svr4_sigset __P((const sigset_t *, svr4_sigset_t *)); void svr4_to_bsd_sigaltstack __P((const struct svr4_sigaltstack *, struct sigaltstack *)); void svr4_to_bsd_sigset __P((const svr4_sigset_t *, sigset_t *)); void svr4_sendsig(sig_t, int, sigset_t *, u_long); #endif /* !_SVR4_SIGNAL_H_ */ Index: head/sys/compat/svr4/svr4_sysvec.c =================================================================== --- head/sys/compat/svr4/svr4_sysvec.c (revision 68519) +++ head/sys/compat/svr4/svr4_sysvec.c (revision 68520) @@ -1,405 +1,407 @@ /* * Copyright (c) 1998 Mark Newton * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Christos Zoulas. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ /* XXX we use functions that might not exist. */ #include "opt_compat.h" #ifndef COMPAT_43 #error "Unable to compile SVR4-emulator due to missing COMPAT_43 option!" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include int bsd_to_svr4_errno[ELAST+1] = { 0, SVR4_EPERM, SVR4_ENOENT, SVR4_ESRCH, SVR4_EINTR, SVR4_EIO, SVR4_ENXIO, SVR4_E2BIG, SVR4_ENOEXEC, SVR4_EBADF, SVR4_ECHILD, SVR4_EDEADLK, SVR4_ENOMEM, SVR4_EACCES, SVR4_EFAULT, SVR4_ENOTBLK, SVR4_EBUSY, SVR4_EEXIST, SVR4_EXDEV, SVR4_ENODEV, SVR4_ENOTDIR, SVR4_EISDIR, SVR4_EINVAL, SVR4_ENFILE, SVR4_EMFILE, SVR4_ENOTTY, SVR4_ETXTBSY, SVR4_EFBIG, SVR4_ENOSPC, SVR4_ESPIPE, SVR4_EROFS, SVR4_EMLINK, SVR4_EPIPE, SVR4_EDOM, SVR4_ERANGE, SVR4_EAGAIN, SVR4_EINPROGRESS, SVR4_EALREADY, SVR4_ENOTSOCK, SVR4_EDESTADDRREQ, SVR4_EMSGSIZE, SVR4_EPROTOTYPE, SVR4_ENOPROTOOPT, SVR4_EPROTONOSUPPORT, SVR4_ESOCKTNOSUPPORT, SVR4_EOPNOTSUPP, SVR4_EPFNOSUPPORT, SVR4_EAFNOSUPPORT, SVR4_EADDRINUSE, SVR4_EADDRNOTAVAIL, SVR4_ENETDOWN, SVR4_ENETUNREACH, SVR4_ENETRESET, SVR4_ECONNABORTED, SVR4_ECONNRESET, SVR4_ENOBUFS, SVR4_EISCONN, SVR4_ENOTCONN, SVR4_ESHUTDOWN, SVR4_ETOOMANYREFS, SVR4_ETIMEDOUT, SVR4_ECONNREFUSED, SVR4_ELOOP, SVR4_ENAMETOOLONG, SVR4_EHOSTDOWN, SVR4_EHOSTUNREACH, SVR4_ENOTEMPTY, SVR4_EPROCLIM, SVR4_EUSERS, SVR4_EDQUOT, SVR4_ESTALE, SVR4_EREMOTE, SVR4_EBADRPC, SVR4_ERPCMISMATCH, SVR4_EPROGUNAVAIL, SVR4_EPROGMISMATCH, SVR4_EPROCUNAVAIL, SVR4_ENOLCK, SVR4_ENOSYS, SVR4_EFTYPE, SVR4_EAUTH, SVR4_ENEEDAUTH, SVR4_EIDRM, SVR4_ENOMSG, }; static int svr4_fixup(register_t **stack_base, struct image_params *imgp); extern struct sysent svr4_sysent[]; #undef szsigcode #undef sigcode extern int svr4_szsigcode; extern char svr4_sigcode[]; struct sysentvec svr4_sysvec = { SVR4_SYS_MAXSYSCALL, svr4_sysent, 0xff, SVR4_SIGTBLSZ, bsd_to_svr4_sig, ELAST, /* ELAST */ bsd_to_svr4_errno, 0, svr4_fixup, svr4_sendsig, svr4_sigcode, &svr4_szsigcode, NULL, "SVR4", - elf_coredump + elf_coredump, + NULL, + SVR4_MINSIGSTKSZ }; Elf32_Brandinfo svr4_brand = { ELFOSABI_SOLARIS, /* XXX Or should we use ELFOSABI_SYSV here? */ svr4_emul_path, "/lib/libc.so.1", &svr4_sysvec }; const char svr4_emul_path[] = "/compat/svr4"; static int svr4_fixup(register_t **stack_base, struct image_params *imgp) { Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs; register_t *pos; pos = *stack_base + (imgp->argc + imgp->envc + 2); if (args->trace) { AUXARGS_ENTRY(pos, AT_DEBUG, 1); } if (args->execfd != -1) { AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); } AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); AUXARGS_ENTRY(pos, AT_PHENT, args->phent); AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); AUXARGS_ENTRY(pos, AT_BASE, args->base); AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_cred->p_ruid); AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_cred->p_svuid); AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_cred->p_rgid); AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_cred->p_svgid); AUXARGS_ENTRY(pos, AT_NULL, 0); free(imgp->auxargs, M_TEMP); imgp->auxargs = NULL; (*stack_base)--; **stack_base = (int)imgp->argc; return 0; } /* * Search an alternate path before passing pathname arguments on * to system calls. Useful for keeping a seperate 'emulation tree'. * * If cflag is set, we check if an attempt can be made to create * the named file, i.e. we check if the directory it should * be in exists. * * Code shamelessly stolen by Mark Newton from IBCS2 emulation code. */ int svr4_emul_find(p, sgp, prefix, path, pbuf, cflag) struct proc *p; caddr_t *sgp; /* Pointer to stackgap memory */ const char *prefix; char *path; char **pbuf; int cflag; { struct nameidata nd; struct nameidata ndroot; struct vattr vat; struct vattr vatroot; int error; char *ptr, *buf, *cp; size_t sz, len; buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK); *pbuf = path; for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++) continue; sz = MAXPATHLEN - (ptr - buf); /* * If sgp is not given then the path is already in kernel space */ if (sgp == NULL) error = copystr(path, ptr, sz, &len); else error = copyinstr(path, ptr, sz, &len); if (error) { free(buf, M_TEMP); return error; } if (*ptr != '/') { free(buf, M_TEMP); return EINVAL; } /* * We know that there is a / somewhere in this pathname. * Search backwards for it, to find the file's parent dir * to see if it exists in the alternate tree. If it does, * and we want to create a file (cflag is set). We don't * need to worry about the root comparison in this case. */ if (cflag) { for (cp = &ptr[len] - 1; *cp != '/'; cp--); *cp = '\0'; NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, p); if ((error = namei(&nd)) != 0) { free(buf, M_TEMP); return error; } NDFREE(&nd, NDF_ONLY_PNBUF); *cp = '/'; } else { NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, p); if ((error = namei(&nd)) != 0) { free(buf, M_TEMP); return error; } NDFREE(&nd, NDF_ONLY_PNBUF); /* * We now compare the vnode of the svr4_root to the one * vnode asked. If they resolve to be the same, then we * ignore the match so that the real root gets used. * This avoids the problem of traversing "../.." to find the * root directory and never finding it, because "/" resolves * to the emulation root directory. This is expensive :-( */ NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, svr4_emul_path, p); if ((error = namei(&ndroot)) != 0) { /* Cannot happen! */ free(buf, M_TEMP); vrele(nd.ni_vp); return error; } NDFREE(&ndroot, NDF_ONLY_PNBUF); if ((error = VOP_GETATTR(nd.ni_vp, &vat, p->p_ucred, p)) != 0) { goto done; } if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, p->p_ucred, p)) != 0) { goto done; } if (vat.va_fsid == vatroot.va_fsid && vat.va_fileid == vatroot.va_fileid) { error = ENOENT; goto done; } } if (sgp == NULL) *pbuf = buf; else { sz = &ptr[len] - buf; *pbuf = stackgap_alloc(sgp, sz + 1); error = copyout(buf, *pbuf, sz); free(buf, M_TEMP); } done: vrele(nd.ni_vp); if (!cflag) vrele(ndroot.ni_vp); return error; } static int svr4_elf_modevent(module_t mod, int type, void *data) { int error; error = 0; switch(type) { case MOD_LOAD: if (elf_insert_brand_entry(&svr4_brand) < 0) error = EINVAL; if (error) printf("cannot insert svr4 elf brand handler\n"); else if (bootverbose) printf("svr4 ELF exec handler installed\n"); break; case MOD_UNLOAD: /* Only allow the emulator to be removed if it isn't in use. */ if (elf_brand_inuse(&svr4_brand) != 0) { error = EBUSY; } else if (elf_remove_brand_entry(&svr4_brand) < 0) { error = EINVAL; } if (error) printf("Could not deinstall ELF interpreter entry (error %d)\n", error); else if (bootverbose) printf("svr4 ELF exec handler removed\n"); break; default: break; } return error; } static moduledata_t svr4_elf_mod = { "svr4elf", svr4_elf_modevent, 0 }; DECLARE_MODULE(svr4elf, svr4_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY); MODULE_DEPEND(svr4elf, streams, 1, 1, 1); Index: head/sys/i386/ibcs2/ibcs2_signal.h =================================================================== --- head/sys/i386/ibcs2/ibcs2_signal.h (revision 68519) +++ head/sys/i386/ibcs2/ibcs2_signal.h (revision 68520) @@ -1,108 +1,110 @@ /* $NetBSD: ibcs2_signal.h,v 1.7 1995/08/14 02:26:01 mycroft Exp $ */ /* * Copyright (c) 1994, 1995 Scott Bartram * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Scott Bartram. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _IBCS2_SIGNAL_H #define _IBCS2_SIGNAL_H #define IBCS2_SIGHUP 1 #define IBCS2_SIGINT 2 #define IBCS2_SIGQUIT 3 #define IBCS2_SIGILL 4 #define IBCS2_SIGTRAP 5 #define IBCS2_SIGIOT 6 #define IBCS2_SIGABRT 6 #define IBCS2_SIGEMT 7 #define IBCS2_SIGFPE 8 #define IBCS2_SIGKILL 9 #define IBCS2_SIGBUS 10 #define IBCS2_SIGSEGV 11 #define IBCS2_SIGSYS 12 #define IBCS2_SIGPIPE 13 #define IBCS2_SIGALRM 14 #define IBCS2_SIGTERM 15 #define IBCS2_SIGUSR1 16 #define IBCS2_SIGUSR2 17 #define IBCS2_SIGCLD 18 #define IBCS2_SIGPWR 19 #define IBCS2_SIGWINCH 20 #define IBCS2_SIGPOLL 22 #define IBCS2_NSIG 32 #define IBCS2_SIGTBLSZ 32 /* * SCO-specific */ #define IBCS2_SIGSTOP 23 #define IBCS2_SIGTSTP 24 #define IBCS2_SIGCONT 25 #define IBCS2_SIGTTIN 26 #define IBCS2_SIGTTOU 27 #define IBCS2_SIGVTALRM 28 #define IBCS2_SIGPROF 29 #define IBCS2_SIGNO_MASK 0x00FF #define IBCS2_SIGNAL_MASK 0x0000 #define IBCS2_SIGSET_MASK 0x0100 #define IBCS2_SIGHOLD_MASK 0x0200 #define IBCS2_SIGRELSE_MASK 0x0400 #define IBCS2_SIGIGNORE_MASK 0x0800 #define IBCS2_SIGPAUSE_MASK 0x1000 #define IBCS2_SIGNO(x) ((x) & IBCS2_SIGNO_MASK) #define IBCS2_SIGCALL(x) ((x) & ~IBCS2_SIGNO_MASK) typedef long ibcs2_sigset_t; typedef void (*ibcs2_sig_t) __P((int)); struct ibcs2_sigaction { ibcs2_sig_t isa_handler; ibcs2_sigset_t isa_mask; int isa_flags; }; #define IBCS2_SIG_DFL ((ibcs2_sig_t)0) #define IBCS2_SIG_ERR ((ibcs2_sig_t)-1) #define IBCS2_SIG_IGN ((ibcs2_sig_t)1) #define IBCS2_SIG_HOLD ((ibcs2_sig_t)2) #define IBCS2_SIG_SETMASK 0 #define IBCS2_SIG_BLOCK 1 #define IBCS2_SIG_UNBLOCK 2 /* sa_flags */ #define IBCS2_SA_NOCLDSTOP 1 +#define IBCS2_MINSIGSTKSZ 8192 + extern int bsd_to_ibcs2_sig[]; #endif /* _IBCS2_SIGNAL_H */ Index: head/sys/i386/ibcs2/ibcs2_sysvec.c =================================================================== --- head/sys/i386/ibcs2/ibcs2_sysvec.c (revision 68519) +++ head/sys/i386/ibcs2/ibcs2_sysvec.c (revision 68520) @@ -1,94 +1,96 @@ /* * Copyright (c) 1995 Steven Wallace * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Steven Wallace. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include MODULE_VERSION(ibcs2, 1); extern int bsd_to_ibcs2_errno[]; extern struct sysent ibcs2_sysent[IBCS2_SYS_MAXSYSCALL]; extern int szsigcode; extern char sigcode[]; struct sysentvec ibcs2_svr3_sysvec = { sizeof (ibcs2_sysent) / sizeof (ibcs2_sysent[0]), ibcs2_sysent, 0xFF, IBCS2_SIGTBLSZ, bsd_to_ibcs2_sig, ELAST + 1, bsd_to_ibcs2_errno, 0, /* trap-to-signal translation function */ 0, /* fixup */ sendsig, sigcode, /* use generic trampoline */ &szsigcode, /* use generic trampoline size */ 0, /* prepsyscall */ "IBCS2 COFF", - NULL /* we don't have a COFF coredump function */ + NULL, /* we don't have a COFF coredump function */ + NULL, + IBCS2_MINSIGSTKSZ }; /* * Create an "ibcs2" module that does nothing but allow checking for * the presence of the subsystem. */ static int ibcs2_modevent(module_t mod, int type, void *unused) { struct proc *p = NULL; switch(type) { case MOD_UNLOAD: /* if this was an ELF module we'd use elf_brand_inuse()... */ for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { if (p->p_sysent == &ibcs2_svr3_sysvec) return EBUSY; } default: /* do not care */ } return 0; } static moduledata_t ibcs2_mod = { "ibcs2", ibcs2_modevent, 0 }; DECLARE_MODULE(ibcs2, ibcs2_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); Index: head/sys/i386/include/signal.h =================================================================== --- head/sys/i386/include/signal.h (revision 68519) +++ head/sys/i386/include/signal.h (revision 68520) @@ -1,126 +1,132 @@ /* * Copyright (c) 1986, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)signal.h 8.1 (Berkeley) 6/11/93 * $FreeBSD$ */ #ifndef _MACHINE_SIGNAL_H_ #define _MACHINE_SIGNAL_H_ /* * Machine-dependent signal definitions */ typedef int sig_atomic_t; #if !defined(_ANSI_SOURCE) && !defined(_POSIX_SOURCE) +/* + * Minimum signal stack size. The current signal frame + * for i386 is 408 bytes large. + */ +#define MINSIGSTKSZ (512 * 4) + #include /* codes for SIGILL, SIGFPE */ /* * Information pushed on stack when a signal is delivered. * This is used by the kernel to restore state following * execution of the signal handler. It is also made available * to the handler to allow it to restore state properly if * a non-standard exit is performed. */ typedef unsigned int osigset_t; struct osigcontext { int sc_onstack; /* sigstack state to restore */ osigset_t sc_mask; /* signal mask to restore */ int sc_esp; /* machine state follows: */ int sc_ebp; int sc_isp; int sc_eip; int sc_efl; int sc_es; int sc_ds; int sc_cs; int sc_ss; int sc_edi; int sc_esi; int sc_ebx; int sc_edx; int sc_ecx; int sc_eax; int sc_gs; int sc_fs; int sc_trapno; int sc_err; }; /* * The sequence of the fields/registers in struct sigcontext should match * those in mcontext_t. */ struct sigcontext { sigset_t sc_mask; /* signal mask to restore */ int sc_onstack; /* sigstack state to restore */ int sc_gs; /* machine state (struct trapframe): */ int sc_fs; int sc_es; int sc_ds; int sc_edi; int sc_esi; int sc_ebp; int sc_isp; int sc_ebx; int sc_edx; int sc_ecx; int sc_eax; int sc_trapno; int sc_err; int sc_eip; int sc_cs; int sc_efl; int sc_esp; int sc_ss; /* * XXX FPU state is 27 * 4 bytes h/w, 1 * 4 bytes s/w (probably not * needed here), or that + 16 * 4 bytes for emulators (probably all * needed here). The "spare" bytes are mostly not spare. */ int sc_fpregs[28]; /* machine state (FPU): */ int sc_spare[17]; }; #define sc_sp sc_esp #define sc_fp sc_ebp #define sc_pc sc_eip #define sc_ps sc_efl #define sc_eflags sc_efl #endif /* !_ANSI_SOURCE && !_POSIX_SOURCE */ #endif /* !_MACHINE_SIGNAL_H_ */ Index: head/sys/i386/linux/linux_machdep.c =================================================================== --- head/sys/i386/linux/linux_machdep.c (revision 68519) +++ head/sys/i386/linux/linux_machdep.c (revision 68520) @@ -1,693 +1,690 @@ /*- * Copyright (c) 2000 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct linux_descriptor { unsigned int entry_number; unsigned long base_addr; unsigned int limit; unsigned int seg_32bit:1; unsigned int contents:2; unsigned int read_exec_only:1; unsigned int limit_in_pages:1; unsigned int seg_not_present:1; unsigned int useable:1; }; struct linux_select_argv { int nfds; fd_set *readfds; fd_set *writefds; fd_set *exceptfds; struct timeval *timeout; }; int linux_to_bsd_sigaltstack(int lsa) { int bsa = 0; if (lsa & LINUX_SS_DISABLE) bsa |= SS_DISABLE; if (lsa & LINUX_SS_ONSTACK) bsa |= SS_ONSTACK; if (lsa == LINUX_SS_ONSTACK_BC) bsa = SS_ONSTACK; return (bsa); } int bsd_to_linux_sigaltstack(int bsa) { int lsa = 0; if (bsa & SS_DISABLE) lsa |= LINUX_SS_DISABLE; if (bsa & SS_ONSTACK) lsa |= LINUX_SS_ONSTACK; return (lsa); } int linux_execve(struct proc *p, struct linux_execve_args *args) { struct execve_args bsd; caddr_t sg; sg = stackgap_init(); CHECKALTEXIST(p, &sg, args->path); #ifdef DEBUG printf("Linux-emul(%d): execve(%s)\n", p->p_pid, args->path); #endif bsd.fname = args->path; bsd.argv = args->argp; bsd.envv = args->envp; return (execve(p, &bsd)); } int linux_ipc(struct proc *p, struct linux_ipc_args *args) { switch (args->what) { case LINUX_SEMOP: return (linux_semop(p, args)); case LINUX_SEMGET: return (linux_semget(p, args)); case LINUX_SEMCTL: return (linux_semctl(p, args)); case LINUX_MSGSND: return (linux_msgsnd(p, args)); case LINUX_MSGRCV: return (linux_msgrcv(p, args)); case LINUX_MSGGET: return (linux_msgget(p, args)); case LINUX_MSGCTL: return (linux_msgctl(p, args)); case LINUX_SHMAT: return (linux_shmat(p, args)); case LINUX_SHMDT: return (linux_shmdt(p, args)); case LINUX_SHMGET: return (linux_shmget(p, args)); case LINUX_SHMCTL: return (linux_shmctl(p, args)); } uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what); return (ENOSYS); } int linux_select(struct proc *p, struct linux_select_args *args) { struct linux_select_argv linux_args; struct linux_newselect_args newsel; int error; #ifdef SELECT_DEBUG printf("Linux-emul(%ld): select(%x)\n", (long)p->p_pid, args->ptr); #endif error = copyin(args->ptr, &linux_args, sizeof(linux_args)); if (error) return (error); newsel.nfds = linux_args.nfds; newsel.readfds = linux_args.readfds; newsel.writefds = linux_args.writefds; newsel.exceptfds = linux_args.exceptfds; newsel.timeout = linux_args.timeout; return (linux_newselect(p, &newsel)); } int linux_fork(struct proc *p, struct linux_fork_args *args) { int error; #ifdef DEBUG printf("Linux-emul(%ld): fork()\n", (long)p->p_pid); #endif if ((error = fork(p, (struct fork_args *)args)) != 0) return (error); if (p->p_retval[1] == 1) p->p_retval[0] = 0; return (0); } int linux_vfork(struct proc *p, struct linux_vfork_args *args) { int error; #ifdef DEBUG printf("Linux-emul(%ld): vfork()\n", (long)p->p_pid); #endif if ((error = vfork(p, (struct vfork_args *)args)) != 0) return (error); /* Are we the child? */ if (p->p_retval[1] == 1) p->p_retval[0] = 0; return (0); } #define CLONE_VM 0x100 #define CLONE_FS 0x200 #define CLONE_FILES 0x400 #define CLONE_SIGHAND 0x800 #define CLONE_PID 0x1000 int linux_clone(struct proc *p, struct linux_clone_args *args) { int error, ff = RFPROC; struct proc *p2; int exit_signal; vm_offset_t start; struct rfork_args rf_args; #ifdef DEBUG if (args->flags & CLONE_PID) printf("linux_clone(%ld): CLONE_PID not yet supported\n", (long)p->p_pid); printf("linux_clone(%ld): invoked with flags %x and stack %x\n", (long)p->p_pid, (unsigned int)args->flags, (unsigned int)args->stack); #endif if (!args->stack) return (EINVAL); exit_signal = args->flags & 0x000000ff; if (exit_signal >= LINUX_NSIG) return (EINVAL); if (exit_signal <= LINUX_SIGTBLSZ) exit_signal = linux_to_bsd_signal[_SIG_IDX(exit_signal)]; /* RFTHREAD probably not necessary here, but it shouldn't hurt */ ff |= RFTHREAD; if (args->flags & CLONE_VM) ff |= RFMEM; if (args->flags & CLONE_SIGHAND) ff |= RFSIGSHARE; if (!(args->flags & CLONE_FILES)) ff |= RFFDG; error = 0; start = 0; rf_args.flags = ff; if ((error = rfork(p, &rf_args)) != 0) return (error); p2 = pfind(p->p_retval[0]); if (p2 == 0) return (ESRCH); p2->p_sigparent = exit_signal; p2->p_md.md_regs->tf_esp = (unsigned int)args->stack; #ifdef DEBUG printf ("linux_clone(%ld): successful rfork to %ld\n", (long)p->p_pid, (long)p2->p_pid); #endif return (0); } /* XXX move */ struct linux_mmap_argv { linux_caddr_t addr; int len; int prot; int flags; int fd; int pos; }; #define STACK_SIZE (2 * 1024 * 1024) #define GUARD_SIZE (4 * PAGE_SIZE) int linux_mmap(struct proc *p, struct linux_mmap_args *args) { struct mmap_args /* { caddr_t addr; size_t len; int prot; int flags; int fd; long pad; off_t pos; } */ bsd_args; int error; struct linux_mmap_argv linux_args; error = copyin(args->ptr, &linux_args, sizeof(linux_args)); if (error) return (error); #ifdef DEBUG printf("Linux-emul(%ld): mmap(%p, %d, %d, 0x%08x, %d, %d)", (long)p->p_pid, (void *)linux_args.addr, linux_args.len, linux_args.prot, linux_args.flags, linux_args.fd, linux_args.pos); #endif bsd_args.flags = 0; if (linux_args.flags & LINUX_MAP_SHARED) bsd_args.flags |= MAP_SHARED; if (linux_args.flags & LINUX_MAP_PRIVATE) bsd_args.flags |= MAP_PRIVATE; if (linux_args.flags & LINUX_MAP_FIXED) bsd_args.flags |= MAP_FIXED; if (linux_args.flags & LINUX_MAP_ANON) bsd_args.flags |= MAP_ANON; if (linux_args.flags & LINUX_MAP_GROWSDOWN) { bsd_args.flags |= MAP_STACK; /* The linux MAP_GROWSDOWN option does not limit auto * growth of the region. Linux mmap with this option * takes as addr the inital BOS, and as len, the initial * region size. It can then grow down from addr without * limit. However, linux threads has an implicit internal * limit to stack size of STACK_SIZE. Its just not * enforced explicitly in linux. But, here we impose * a limit of (STACK_SIZE - GUARD_SIZE) on the stack * region, since we can do this with our mmap. * * Our mmap with MAP_STACK takes addr as the maximum * downsize limit on BOS, and as len the max size of * the region. It them maps the top SGROWSIZ bytes, * and autgrows the region down, up to the limit * in addr. * * If we don't use the MAP_STACK option, the effect * of this code is to allocate a stack region of a * fixed size of (STACK_SIZE - GUARD_SIZE). */ /* This gives us TOS */ bsd_args.addr = linux_args.addr + linux_args.len; if (bsd_args.addr > p->p_vmspace->vm_maxsaddr) { /* Some linux apps will attempt to mmap * thread stacks near the top of their * address space. If their TOS is greater * than vm_maxsaddr, vm_map_growstack() * will confuse the thread stack with the * process stack and deliver a SEGV if they * attempt to grow the thread stack past their * current stacksize rlimit. To avoid this, * adjust vm_maxsaddr upwards to reflect * the current stacksize rlimit rather * than the maximum possible stacksize. * It would be better to adjust the * mmap'ed region, but some apps do not check * mmap's return value. */ p->p_vmspace->vm_maxsaddr = (char *)USRSTACK - p->p_rlimit[RLIMIT_STACK].rlim_cur; } /* This gives us our maximum stack size */ if (linux_args.len > STACK_SIZE - GUARD_SIZE) bsd_args.len = linux_args.len; else bsd_args.len = STACK_SIZE - GUARD_SIZE; /* This gives us a new BOS. If we're using VM_STACK, then * mmap will just map the top SGROWSIZ bytes, and let * the stack grow down to the limit at BOS. If we're * not using VM_STACK we map the full stack, since we * don't have a way to autogrow it. */ bsd_args.addr -= bsd_args.len; } else { bsd_args.addr = linux_args.addr; bsd_args.len = linux_args.len; } bsd_args.prot = linux_args.prot | PROT_READ; /* always required */ if (linux_args.flags & LINUX_MAP_ANON) bsd_args.fd = -1; else bsd_args.fd = linux_args.fd; bsd_args.pos = linux_args.pos; bsd_args.pad = 0; #ifdef DEBUG printf("-> (%p, %d, %d, 0x%08x, %d, %d)\n", (void *)bsd_args.addr, bsd_args.len, bsd_args.prot, bsd_args.flags, bsd_args.fd, (int)bsd_args.pos); #endif return (mmap(p, &bsd_args)); } int linux_pipe(struct proc *p, struct linux_pipe_args *args) { int error; int reg_edx; #ifdef DEBUG printf("Linux-emul(%ld): pipe(*)\n", (long)p->p_pid); #endif reg_edx = p->p_retval[1]; error = pipe(p, 0); if (error) { p->p_retval[1] = reg_edx; return (error); } error = copyout(p->p_retval, args->pipefds, 2*sizeof(int)); if (error) { p->p_retval[1] = reg_edx; return (error); } p->p_retval[1] = reg_edx; p->p_retval[0] = 0; return (0); } int linux_ioperm(struct proc *p, struct linux_ioperm_args *args) { struct sysarch_args sa; struct i386_ioperm_args *iia; caddr_t sg; sg = stackgap_init(); iia = stackgap_alloc(&sg, sizeof(struct i386_ioperm_args)); iia->start = args->start; iia->length = args->length; iia->enable = args->enable; sa.op = I386_SET_IOPERM; sa.parms = (char *)iia; return (sysarch(p, &sa)); } int linux_iopl(struct proc *p, struct linux_iopl_args *args) { int error; if (args->level < 0 || args->level > 3) return (EINVAL); if ((error = suser(p)) != 0) return (error); if (securelevel > 0) return (EPERM); p->p_md.md_regs->tf_eflags = (p->p_md.md_regs->tf_eflags & ~PSL_IOPL) | (args->level * (PSL_IOPL / 3)); return (0); } int linux_modify_ldt(p, uap) struct proc *p; struct linux_modify_ldt_args *uap; { int error; caddr_t sg; struct sysarch_args args; struct i386_ldt_args *ldt; struct linux_descriptor ld; union descriptor *desc; sg = stackgap_init(); if (uap->ptr == NULL) return (EINVAL); switch (uap->func) { case 0x00: /* read_ldt */ ldt = stackgap_alloc(&sg, sizeof(*ldt)); ldt->start = 0; ldt->descs = uap->ptr; ldt->num = uap->bytecount / sizeof(union descriptor); args.op = I386_GET_LDT; args.parms = (char*)ldt; error = sysarch(p, &args); p->p_retval[0] *= sizeof(union descriptor); break; case 0x01: /* write_ldt */ case 0x11: /* write_ldt */ if (uap->bytecount != sizeof(ld)) return (EINVAL); error = copyin(uap->ptr, &ld, sizeof(ld)); if (error) return (error); ldt = stackgap_alloc(&sg, sizeof(*ldt)); desc = stackgap_alloc(&sg, sizeof(*desc)); ldt->start = ld.entry_number; ldt->descs = desc; ldt->num = 1; desc->sd.sd_lolimit = (ld.limit & 0x0000ffff); desc->sd.sd_hilimit = (ld.limit & 0x000f0000) >> 16; desc->sd.sd_lobase = (ld.base_addr & 0x00ffffff); desc->sd.sd_hibase = (ld.base_addr & 0xff000000) >> 24; desc->sd.sd_type = SDT_MEMRO | ((ld.read_exec_only ^ 1) << 1) | (ld.contents << 2); desc->sd.sd_dpl = 3; desc->sd.sd_p = (ld.seg_not_present ^ 1); desc->sd.sd_xx = 0; desc->sd.sd_def32 = ld.seg_32bit; desc->sd.sd_gran = ld.limit_in_pages; args.op = I386_SET_LDT; args.parms = (char*)ldt; error = sysarch(p, &args); break; default: error = EINVAL; break; } if (error == EOPNOTSUPP) { printf("linux: modify_ldt needs kernel option USER_LDT\n"); error = ENOSYS; } return (error); } int linux_sigaction(struct proc *p, struct linux_sigaction_args *args) { linux_osigaction_t osa; linux_sigaction_t act, oact; int error; #ifdef DEBUG printf("Linux-emul(%ld): sigaction(%d, %p, %p)\n", (long)p->p_pid, args->sig, (void *)args->nsa, (void *)args->osa); #endif if (args->nsa != NULL) { error = copyin(args->nsa, &osa, sizeof(linux_osigaction_t)); if (error) return (error); act.lsa_handler = osa.lsa_handler; act.lsa_flags = osa.lsa_flags; act.lsa_restorer = osa.lsa_restorer; LINUX_SIGEMPTYSET(act.lsa_mask); act.lsa_mask.__bits[0] = osa.lsa_mask; } error = linux_do_sigaction(p, args->sig, args->nsa ? &act : NULL, args->osa ? &oact : NULL); if (args->osa != NULL && !error) { osa.lsa_handler = oact.lsa_handler; osa.lsa_flags = oact.lsa_flags; osa.lsa_restorer = oact.lsa_restorer; osa.lsa_mask = oact.lsa_mask.__bits[0]; error = copyout(&osa, args->osa, sizeof(linux_osigaction_t)); } return (error); } /* * Linux has two extra args, restart and oldmask. We dont use these, * but it seems that "restart" is actually a context pointer that * enables the signal to happen with a different register set. */ int linux_sigsuspend(struct proc *p, struct linux_sigsuspend_args *args) { struct sigsuspend_args bsd; sigset_t *sigmask; linux_sigset_t mask; caddr_t sg = stackgap_init(); #ifdef DEBUG printf("Linux-emul(%ld): sigsuspend(%08lx)\n", (long)p->p_pid, (unsigned long)args->mask); #endif sigmask = stackgap_alloc(&sg, sizeof(sigset_t)); LINUX_SIGEMPTYSET(mask); mask.__bits[0] = args->mask; linux_to_bsd_sigset(&mask, sigmask); bsd.sigmask = sigmask; return (sigsuspend(p, &bsd)); } int linux_rt_sigsuspend(p, uap) struct proc *p; struct linux_rt_sigsuspend_args *uap; { linux_sigset_t lmask; sigset_t *bmask; struct sigsuspend_args bsd; caddr_t sg = stackgap_init(); int error; #ifdef DEBUG printf("Linux-emul(%ld): rt_sigsuspend(%p, %d)\n", (long)p->p_pid, (void *)uap->newset, uap->sigsetsize); #endif if (uap->sigsetsize != sizeof(linux_sigset_t)) return (EINVAL); error = copyin(uap->newset, &lmask, sizeof(linux_sigset_t)); if (error) return (error); bmask = stackgap_alloc(&sg, sizeof(sigset_t)); linux_to_bsd_sigset(&lmask, bmask); bsd.sigmask = bmask; return (sigsuspend(p, &bsd)); } int linux_pause(struct proc *p, struct linux_pause_args *args) { struct sigsuspend_args bsd; sigset_t *sigmask; caddr_t sg = stackgap_init(); #ifdef DEBUG printf("Linux-emul(%d): pause()\n", p->p_pid); #endif sigmask = stackgap_alloc(&sg, sizeof(sigset_t)); *sigmask = p->p_sigmask; bsd.sigmask = sigmask; return (sigsuspend(p, &bsd)); } int linux_sigaltstack(p, uap) struct proc *p; struct linux_sigaltstack_args *uap; { struct sigaltstack_args bsd; stack_t *ss, *oss; linux_stack_t lss; int error; caddr_t sg = stackgap_init(); #ifdef DEBUG printf("Linux-emul(%ld): sigaltstack(%p, %p)\n", (long)p->p_pid, uap->uss, uap->uoss); #endif if (uap->uss == NULL) { ss = NULL; } else { error = copyin(uap->uss, &lss, sizeof(linux_stack_t)); if (error) return (error); ss = stackgap_alloc(&sg, sizeof(stack_t)); ss->ss_sp = lss.ss_sp; - ss->ss_size = (lss.ss_size >= LINUX_MINSIGSTKSZ && - lss.ss_size < MINSIGSTKSZ) ? MINSIGSTKSZ : lss.ss_size; + ss->ss_size = lss.ss_size; ss->ss_flags = linux_to_bsd_sigaltstack(lss.ss_flags); } oss = (uap->uoss != NULL) ? stackgap_alloc(&sg, sizeof(stack_t)) : NULL; bsd.ss = ss; bsd.oss = oss; error = sigaltstack(p, &bsd); if (!error && oss != NULL) { lss.ss_sp = oss->ss_sp; lss.ss_size = oss->ss_size; lss.ss_flags = bsd_to_linux_sigaltstack(oss->ss_flags); error = copyout(&lss, uap->uoss, sizeof(linux_stack_t)); } - if (!error && (ss != NULL) && (lss.ss_size < ss->ss_size)) - p->p_sigstk.ss_size = lss.ss_size; return (error); } Index: head/sys/i386/linux/linux_sysvec.c =================================================================== --- head/sys/i386/linux/linux_sysvec.c (revision 68519) +++ head/sys/i386/linux/linux_sysvec.c (revision 68520) @@ -1,821 +1,821 @@ /*- * Copyright (c) 1994-1996 Søren Schmidt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software withough specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ /* XXX we use functions that might not exist. */ #include "opt_compat.h" #ifndef COMPAT_43 #error "Unable to compile Linux-emulator due to missing COMPAT_43 option!" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include MODULE_VERSION(linux, 1); MALLOC_DEFINE(M_LINUX, "linux", "Linux mode structures"); #if BYTE_ORDER == LITTLE_ENDIAN #define SHELLMAGIC 0x2123 /* #! */ #else #define SHELLMAGIC 0x2321 #endif extern char linux_sigcode[]; extern int linux_szsigcode; extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL]; extern struct linker_set linux_ioctl_handler_set; static int linux_fixup __P((register_t **stack_base, struct image_params *iparams)); static int elf_linux_fixup __P((register_t **stack_base, struct image_params *iparams)); static void linux_prepsyscall __P((struct trapframe *tf, int *args, u_int *code, caddr_t *params)); static void linux_sendsig __P((sig_t catcher, int sig, sigset_t *mask, u_long code)); /* * Linux syscalls return negative errno's, we do positive and map them */ static int bsd_to_linux_errno[ELAST + 1] = { -0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -35, -12, -13, -14, -15, -16, -17, -18, -19, -20, -21, -22, -23, -24, -25, -26, -27, -28, -29, -30, -31, -32, -33, -34, -11,-115,-114, -88, -89, -90, -91, -92, -93, -94, -95, -96, -97, -98, -99, -100,-101,-102,-103,-104,-105,-106,-107,-108,-109, -110,-111, -40, -36,-112,-113, -39, -11, -87,-122, -116, -66, -6, -6, -6, -6, -6, -37, -38, -9, -6, -6, -43, -42, -75, -6, -84 }; int bsd_to_linux_signal[LINUX_SIGTBLSZ] = { LINUX_SIGHUP, LINUX_SIGINT, LINUX_SIGQUIT, LINUX_SIGILL, LINUX_SIGTRAP, LINUX_SIGABRT, 0, LINUX_SIGFPE, LINUX_SIGKILL, LINUX_SIGBUS, LINUX_SIGSEGV, 0, LINUX_SIGPIPE, LINUX_SIGALRM, LINUX_SIGTERM, LINUX_SIGURG, LINUX_SIGSTOP, LINUX_SIGTSTP, LINUX_SIGCONT, LINUX_SIGCHLD, LINUX_SIGTTIN, LINUX_SIGTTOU, LINUX_SIGIO, LINUX_SIGXCPU, LINUX_SIGXFSZ, LINUX_SIGVTALRM, LINUX_SIGPROF, LINUX_SIGWINCH, 0, LINUX_SIGUSR1, LINUX_SIGUSR2 }; int linux_to_bsd_signal[LINUX_SIGTBLSZ] = { SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGBUS, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, SIGIO, SIGURG, 0 }; /* * If FreeBSD & Linux have a difference of opinion about what a trap * means, deal with it here. */ static int translate_traps(int signal, int trap_code) { if (signal != SIGBUS) return signal; switch (trap_code) { case T_PROTFLT: case T_TSSFLT: case T_DOUBLEFLT: case T_PAGEFLT: return SIGSEGV; default: return signal; } } static int linux_fixup(register_t **stack_base, struct image_params *imgp) { register_t *argv, *envp; argv = *stack_base; envp = *stack_base + (imgp->argc + 1); (*stack_base)--; **stack_base = (intptr_t)(void *)envp; (*stack_base)--; **stack_base = (intptr_t)(void *)argv; (*stack_base)--; **stack_base = imgp->argc; return 0; } static int elf_linux_fixup(register_t **stack_base, struct image_params *imgp) { Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs; register_t *pos; pos = *stack_base + (imgp->argc + imgp->envc + 2); if (args->trace) { AUXARGS_ENTRY(pos, AT_DEBUG, 1); } if (args->execfd != -1) { AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); } AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); AUXARGS_ENTRY(pos, AT_PHENT, args->phent); AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); AUXARGS_ENTRY(pos, AT_BASE, args->base); AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_cred->p_ruid); AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_cred->p_svuid); AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_cred->p_rgid); AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_cred->p_svgid); AUXARGS_ENTRY(pos, AT_NULL, 0); free(imgp->auxargs, M_TEMP); imgp->auxargs = NULL; (*stack_base)--; **stack_base = (long)imgp->argc; return 0; } extern int _ucodesel, _udatasel; extern unsigned long _linux_sznonrtsigcode; static void linux_rt_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) { register struct proc *p = curproc; register struct trapframe *regs; struct linux_rt_sigframe *fp, frame; struct sigacts *psp = p->p_sigacts; int oonstack; regs = p->p_md.md_regs; oonstack = p->p_sigstk.ss_flags & SS_ONSTACK; #ifdef DEBUG printf("Linux-emul(%ld): linux_rt_sendsig(%p, %d, %p, %lu)\n", (long)p->p_pid, catcher, sig, (void*)mask, code); #endif /* * Allocate space for the signal handler context. */ if ((p->p_flag & P_ALTSTACK) && !oonstack && SIGISMEMBER(psp->ps_sigonstack, sig)) { fp = (struct linux_rt_sigframe *)(p->p_sigstk.ss_sp + p->p_sigstk.ss_size - sizeof(struct linux_rt_sigframe)); p->p_sigstk.ss_flags |= SS_ONSTACK; } else { fp = (struct linux_rt_sigframe *)regs->tf_esp - 1; } /* * grow() will return FALSE if the fp will not fit inside the stack * and the stack can not be grown. useracc will return FALSE * if access is denied. */ if ((grow_stack (p, (int)fp) == FALSE) || !useracc((caddr_t)fp, sizeof (struct linux_rt_sigframe), VM_PROT_WRITE)) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ SIGACTION(p, SIGILL) = SIG_DFL; SIGDELSET(p->p_sigignore, SIGILL); SIGDELSET(p->p_sigcatch, SIGILL); SIGDELSET(p->p_sigmask, SIGILL); #ifdef DEBUG printf("Linux-emul(%ld): linux_rt_sendsig -- bad stack %p, SS_ONSTACK: 0x%x ", (long)p->p_pid, fp, p->p_sigstk.ss_flags & SS_ONSTACK); #endif psignal(p, SIGILL); return; } /* * Build the argument list for the signal handler. */ if (p->p_sysent->sv_sigtbl) if (sig <= p->p_sysent->sv_sigsize) sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; frame.sf_handler = catcher; frame.sf_sig = sig; frame.sf_siginfo = &fp->sf_si; frame.sf_ucontext = &fp->sf_sc; /* Fill siginfo structure. */ frame.sf_si.lsi_signo = sig; frame.sf_si.lsi_code = code; frame.sf_si.lsi_addr = (void *)regs->tf_err; /* * Build the signal context to be used by sigreturn. */ frame.sf_sc.uc_mcontext.sc_mask = mask->__bits[0]; frame.sf_sc.uc_mcontext.sc_gs = rgs(); frame.sf_sc.uc_mcontext.sc_fs = regs->tf_fs; frame.sf_sc.uc_mcontext.sc_es = regs->tf_es; frame.sf_sc.uc_mcontext.sc_ds = regs->tf_ds; frame.sf_sc.uc_mcontext.sc_edi = regs->tf_edi; frame.sf_sc.uc_mcontext.sc_esi = regs->tf_esi; frame.sf_sc.uc_mcontext.sc_ebp = regs->tf_ebp; frame.sf_sc.uc_mcontext.sc_ebx = regs->tf_ebx; frame.sf_sc.uc_mcontext.sc_edx = regs->tf_edx; frame.sf_sc.uc_mcontext.sc_ecx = regs->tf_ecx; frame.sf_sc.uc_mcontext.sc_eax = regs->tf_eax; frame.sf_sc.uc_mcontext.sc_eip = regs->tf_eip; frame.sf_sc.uc_mcontext.sc_cs = regs->tf_cs; frame.sf_sc.uc_mcontext.sc_eflags = regs->tf_eflags; frame.sf_sc.uc_mcontext.sc_esp_at_signal = regs->tf_esp; frame.sf_sc.uc_mcontext.sc_ss = regs->tf_ss; frame.sf_sc.uc_mcontext.sc_err = regs->tf_err; frame.sf_sc.uc_mcontext.sc_trapno = code; /* XXX ???? */ /* * Build the remainder of the ucontext struct to be used by sigreturn. */ frame.sf_sc.uc_flags = 0; /* XXX ??? */ frame.sf_sc.uc_link = NULL; /* XXX ??? */ frame.sf_sc.uc_stack.ss_sp = p->p_sigstk.ss_sp; frame.sf_sc.uc_stack.ss_flags = bsd_to_linux_sigaltstack(p->p_sigstk.ss_flags); frame.sf_sc.uc_stack.ss_size = p->p_sigstk.ss_size; #ifdef DEBUG printf("Linux-emul(%ld): rt_sendsig flags: 0x%x, sp: %p, ss: 0x%x, mask: 0x%x\n", (long)p->p_pid, frame.sf_sc.uc_stack.ss_flags, p->p_sigstk.ss_sp, p->p_sigstk.ss_size, frame.sf_sc.uc_mcontext.sc_mask); #endif bsd_to_linux_sigset(&p->p_sigmask, &frame.sf_sc.uc_sigmask); if (copyout(&frame, fp, sizeof(frame)) != 0) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ sigexit(p, SIGILL); /* NOTREACHED */ } /* * Build context to run handler in. */ regs->tf_esp = (int)fp; regs->tf_eip = PS_STRINGS - *(p->p_sysent->sv_szsigcode) + _linux_sznonrtsigcode; regs->tf_eflags &= ~PSL_VM; regs->tf_cs = _ucodesel; regs->tf_ds = _udatasel; regs->tf_es = _udatasel; regs->tf_fs = _udatasel; load_gs(_udatasel); regs->tf_ss = _udatasel; } /* * Send an interrupt to process. * * Stack is set up to allow sigcode stored * in u. to call routine, followed by kcall * to sigreturn routine below. After sigreturn * resets the signal mask, the stack, and the * frame pointer, it returns to the user * specified pc, psl. */ static void linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) { register struct proc *p = curproc; register struct trapframe *regs; struct linux_sigframe *fp, frame; struct sigacts *psp = p->p_sigacts; int oonstack; regs = p->p_md.md_regs; oonstack = p->p_sigstk.ss_flags & SS_ONSTACK; #ifdef DEBUG printf("Linux-emul(%ld): linux_sendsig(%p, %d, %p, %lu)\n", (long)p->p_pid, catcher, sig, (void*)mask, code); #endif if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { /* Signal handler installed with SA_SIGINFO. */ linux_rt_sendsig(catcher, sig, mask, code); return; } /* * Allocate space for the signal handler context. */ if ((p->p_flag & P_ALTSTACK) && !oonstack && SIGISMEMBER(psp->ps_sigonstack, sig)) { fp = (struct linux_sigframe *)(p->p_sigstk.ss_sp + p->p_sigstk.ss_size - sizeof(struct linux_sigframe)); p->p_sigstk.ss_flags |= SS_ONSTACK; } else { fp = (struct linux_sigframe *)regs->tf_esp - 1; } /* * grow() will return FALSE if the fp will not fit inside the stack * and the stack can not be grown. useracc will return FALSE * if access is denied. */ if ((grow_stack (p, (int)fp) == FALSE) || !useracc((caddr_t)fp, sizeof (struct linux_sigframe), VM_PROT_WRITE)) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ SIGACTION(p, SIGILL) = SIG_DFL; SIGDELSET(p->p_sigignore, SIGILL); SIGDELSET(p->p_sigcatch, SIGILL); SIGDELSET(p->p_sigmask, SIGILL); psignal(p, SIGILL); return; } /* * Build the argument list for the signal handler. */ if (p->p_sysent->sv_sigtbl) if (sig <= p->p_sysent->sv_sigsize) sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; frame.sf_handler = catcher; frame.sf_sig = sig; /* * Build the signal context to be used by sigreturn. */ frame.sf_sc.sc_mask = mask->__bits[0]; frame.sf_sc.sc_gs = rgs(); frame.sf_sc.sc_fs = regs->tf_fs; frame.sf_sc.sc_es = regs->tf_es; frame.sf_sc.sc_ds = regs->tf_ds; frame.sf_sc.sc_edi = regs->tf_edi; frame.sf_sc.sc_esi = regs->tf_esi; frame.sf_sc.sc_ebp = regs->tf_ebp; frame.sf_sc.sc_ebx = regs->tf_ebx; frame.sf_sc.sc_edx = regs->tf_edx; frame.sf_sc.sc_ecx = regs->tf_ecx; frame.sf_sc.sc_eax = regs->tf_eax; frame.sf_sc.sc_eip = regs->tf_eip; frame.sf_sc.sc_cs = regs->tf_cs; frame.sf_sc.sc_eflags = regs->tf_eflags; frame.sf_sc.sc_esp_at_signal = regs->tf_esp; frame.sf_sc.sc_ss = regs->tf_ss; frame.sf_sc.sc_err = regs->tf_err; frame.sf_sc.sc_trapno = code; /* XXX ???? */ if (copyout(&frame, fp, sizeof(frame)) != 0) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ sigexit(p, SIGILL); /* NOTREACHED */ } /* * Build context to run handler in. */ regs->tf_esp = (int)fp; regs->tf_eip = PS_STRINGS - *(p->p_sysent->sv_szsigcode); regs->tf_eflags &= ~PSL_VM; regs->tf_cs = _ucodesel; regs->tf_ds = _udatasel; regs->tf_es = _udatasel; regs->tf_fs = _udatasel; load_gs(_udatasel); regs->tf_ss = _udatasel; } /* * System call to cleanup state after a signal * has been taken. Reset signal mask and * stack state from context left by sendsig (above). * Return to previous pc and psl as specified by * context left by sendsig. Check carefully to * make sure that the user has not modified the * psl to gain improper privileges or to cause * a machine fault. */ int linux_sigreturn(p, args) struct proc *p; struct linux_sigreturn_args *args; { struct linux_sigcontext context; register struct trapframe *regs; int eflags; regs = p->p_md.md_regs; #ifdef DEBUG printf("Linux-emul(%ld): linux_sigreturn(%p)\n", (long)p->p_pid, (void *)args->scp); #endif /* * The trampoline code hands us the context. * It is unsafe to keep track of it ourselves, in the event that a * program jumps out of a signal handler. */ if (copyin((caddr_t)args->scp, &context, sizeof(context)) != 0) return (EFAULT); /* * Check for security violations. */ #define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) eflags = context.sc_eflags; /* * XXX do allow users to change the privileged flag PSL_RF. The * cpu sets PSL_RF in tf_eflags for faults. Debuggers should * sometimes set it there too. tf_eflags is kept in the signal * context during signal handling and there is no other place * to remember it, so the PSL_RF bit may be corrupted by the * signal handler without us knowing. Corruption of the PSL_RF * bit at worst causes one more or one less debugger trap, so * allowing it is fairly harmless. */ if (!EFLAGS_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) { return(EINVAL); } /* * Don't allow users to load a valid privileged %cs. Let the * hardware check for invalid selectors, excess privilege in * other selectors, invalid %eip's and invalid %esp's. */ #define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) if (!CS_SECURE(context.sc_cs)) { trapsignal(p, SIGBUS, T_PROTFLT); return(EINVAL); } p->p_sigstk.ss_flags &= ~SS_ONSTACK; SIGSETOLD(p->p_sigmask, context.sc_mask); SIG_CANTMASK(p->p_sigmask); /* * Restore signal context. */ /* %gs was restored by the trampoline. */ regs->tf_fs = context.sc_fs; regs->tf_es = context.sc_es; regs->tf_ds = context.sc_ds; regs->tf_edi = context.sc_edi; regs->tf_esi = context.sc_esi; regs->tf_ebp = context.sc_ebp; regs->tf_ebx = context.sc_ebx; regs->tf_edx = context.sc_edx; regs->tf_ecx = context.sc_ecx; regs->tf_eax = context.sc_eax; regs->tf_eip = context.sc_eip; regs->tf_cs = context.sc_cs; regs->tf_eflags = eflags; regs->tf_esp = context.sc_esp_at_signal; regs->tf_ss = context.sc_ss; return (EJUSTRETURN); } /* * System call to cleanup state after a signal * has been taken. Reset signal mask and * stack state from context left by rt_sendsig (above). * Return to previous pc and psl as specified by * context left by sendsig. Check carefully to * make sure that the user has not modified the * psl to gain improper privileges or to cause * a machine fault. */ int linux_rt_sigreturn(p, args) struct proc *p; struct linux_rt_sigreturn_args *args; { struct sigaltstack_args sasargs; struct linux_ucontext uc; struct linux_sigcontext *context; linux_stack_t *lss; stack_t *ss; register struct trapframe *regs; int eflags; caddr_t sg = stackgap_init(); regs = p->p_md.md_regs; #ifdef DEBUG printf("Linux-emul(%ld): linux_rt_sigreturn(%p)\n", (long)p->p_pid, (void *)args->ucp); #endif /* * The trampoline code hands us the u_context. * It is unsafe to keep track of it ourselves, in the event that a * program jumps out of a signal handler. */ if (copyin((caddr_t)args->ucp, &uc, sizeof(uc)) != 0) return (EFAULT); context = &uc.uc_mcontext; /* * Check for security violations. */ #define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) eflags = context->sc_eflags; /* * XXX do allow users to change the privileged flag PSL_RF. The * cpu sets PSL_RF in tf_eflags for faults. Debuggers should * sometimes set it there too. tf_eflags is kept in the signal * context during signal handling and there is no other place * to remember it, so the PSL_RF bit may be corrupted by the * signal handler without us knowing. Corruption of the PSL_RF * bit at worst causes one more or one less debugger trap, so * allowing it is fairly harmless. */ if (!EFLAGS_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) { return(EINVAL); } /* * Don't allow users to load a valid privileged %cs. Let the * hardware check for invalid selectors, excess privilege in * other selectors, invalid %eip's and invalid %esp's. */ #define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) if (!CS_SECURE(context->sc_cs)) { trapsignal(p, SIGBUS, T_PROTFLT); return(EINVAL); } p->p_sigstk.ss_flags &= ~SS_ONSTACK; SIGSETOLD(p->p_sigmask, context->sc_mask); SIG_CANTMASK(p->p_sigmask); /* * Restore signal context-> */ /* %gs was restored by the trampoline. */ regs->tf_fs = context->sc_fs; regs->tf_es = context->sc_es; regs->tf_ds = context->sc_ds; regs->tf_edi = context->sc_edi; regs->tf_esi = context->sc_esi; regs->tf_ebp = context->sc_ebp; regs->tf_ebx = context->sc_ebx; regs->tf_edx = context->sc_edx; regs->tf_ecx = context->sc_ecx; regs->tf_eax = context->sc_eax; regs->tf_eip = context->sc_eip; regs->tf_cs = context->sc_cs; regs->tf_eflags = eflags; regs->tf_esp = context->sc_esp_at_signal; regs->tf_ss = context->sc_ss; - /* * call sigaltstack & ignore results.. */ ss = stackgap_alloc(&sg, sizeof(stack_t)); lss = &uc.uc_stack; ss->ss_sp = lss->ss_sp; - ss->ss_size = (lss->ss_size >= LINUX_MINSIGSTKSZ && - lss->ss_size < MINSIGSTKSZ) ? MINSIGSTKSZ : lss->ss_size; + ss->ss_size = lss->ss_size; ss->ss_flags = linux_to_bsd_sigaltstack(lss->ss_flags); #ifdef DEBUG printf("Linux-emul(%ld): rt_sigret flags: 0x%x, sp: %p, ss: 0x%x, mask: 0x%x\n", (long)p->p_pid, ss->ss_flags, ss->ss_sp, ss->ss_size, context->sc_mask); #endif sasargs.ss = ss; sasargs.oss = NULL; (void) sigaltstack(p, &sasargs); return (EJUSTRETURN); } static void linux_prepsyscall(struct trapframe *tf, int *args, u_int *code, caddr_t *params) { args[0] = tf->tf_ebx; args[1] = tf->tf_ecx; args[2] = tf->tf_edx; args[3] = tf->tf_esi; args[4] = tf->tf_edi; *params = NULL; /* no copyin */ } /* * If a linux binary is exec'ing something, try this image activator * first. We override standard shell script execution in order to * be able to modify the interpreter path. We only do this if a linux * binary is doing the exec, so we do not create an EXEC module for it. */ static int exec_linux_imgact_try __P((struct image_params *iparams)); static int exec_linux_imgact_try(imgp) struct image_params *imgp; { const char *head = (const char *)imgp->image_header; int error = -1; /* * The interpreter for shell scripts run from a linux binary needs * to be located in /compat/linux if possible in order to recursively * maintain linux path emulation. */ if (((const short *)head)[0] == SHELLMAGIC) { /* * Run our normal shell image activator. If it succeeds attempt * to use the alternate path for the interpreter. If an alternate * path is found, use our stringspace to store it. */ if ((error = exec_shell_imgact(imgp)) == 0) { char *rpath = NULL; linux_emul_find(imgp->proc, NULL, linux_emul_path, imgp->interpreter_name, &rpath, 0); if (rpath != imgp->interpreter_name) { int len = strlen(rpath) + 1; if (len <= MAXSHELLCMDLEN) { memcpy(imgp->interpreter_name, rpath, len); } free(rpath, M_TEMP); } } } return(error); } struct sysentvec linux_sysvec = { LINUX_SYS_MAXSYSCALL, linux_sysent, 0xff, LINUX_SIGTBLSZ, bsd_to_linux_signal, ELAST + 1, bsd_to_linux_errno, translate_traps, linux_fixup, linux_sendsig, linux_sigcode, &linux_szsigcode, linux_prepsyscall, "Linux a.out", aout_coredump, - exec_linux_imgact_try + exec_linux_imgact_try, + LINUX_MINSIGSTKSZ }; struct sysentvec elf_linux_sysvec = { LINUX_SYS_MAXSYSCALL, linux_sysent, 0xff, LINUX_SIGTBLSZ, bsd_to_linux_signal, ELAST + 1, bsd_to_linux_errno, translate_traps, elf_linux_fixup, linux_sendsig, linux_sigcode, &linux_szsigcode, linux_prepsyscall, "Linux ELF", elf_coredump, - exec_linux_imgact_try + exec_linux_imgact_try, + LINUX_MINSIGSTKSZ }; static Elf32_Brandinfo linux_brand = { ELFOSABI_LINUX, "/compat/linux", "/lib/ld-linux.so.1", &elf_linux_sysvec }; static Elf32_Brandinfo linux_glibc2brand = { ELFOSABI_LINUX, "/compat/linux", "/lib/ld-linux.so.2", &elf_linux_sysvec }; Elf32_Brandinfo *linux_brandlist[] = { &linux_brand, &linux_glibc2brand, NULL }; static int linux_elf_modevent(module_t mod, int type, void *data) { Elf32_Brandinfo **brandinfo; int error; error = 0; switch(type) { case MOD_LOAD: for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL; ++brandinfo) if (elf_insert_brand_entry(*brandinfo) < 0) error = EINVAL; if (error) printf("cannot insert Linux elf brand handler\n"); else { linux_ioctl_register_handlers(&linux_ioctl_handler_set); if (bootverbose) printf("Linux-ELF exec handler installed\n"); } break; case MOD_UNLOAD: linux_ioctl_unregister_handlers(&linux_ioctl_handler_set); for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL; ++brandinfo) if (elf_brand_inuse(*brandinfo)) error = EBUSY; if (error == 0) { for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL; ++brandinfo) if (elf_remove_brand_entry(*brandinfo) < 0) error = EINVAL; } if (error) printf("Could not deinstall ELF interpreter entry\n"); else if (bootverbose) printf("Linux-elf exec handler removed\n"); break; default: break; } return error; } static moduledata_t linux_elf_mod = { "linuxelf", linux_elf_modevent, 0 }; DECLARE_MODULE(linuxelf, linux_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY); Index: head/sys/ia64/include/signal.h =================================================================== --- head/sys/ia64/include/signal.h (revision 68519) +++ head/sys/ia64/include/signal.h (revision 68520) @@ -1,88 +1,94 @@ /* $FreeBSD$ */ /* From: NetBSD: signal.h,v 1.3 1997/04/06 08:47:43 cgd Exp */ /* * Copyright (c) 1994, 1995 Carnegie-Mellon University. * All rights reserved. * * Author: Chris G. Demetriou * * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ #ifndef _MACHINE_SIGNAL_H_ #define _MACHINE_SIGNAL_H_ typedef long sig_atomic_t; #ifndef _ANSI_SOURCE +/* + * Minimum signal stack size. The current signal frame + * for IA-64 is 2656 bytes large. + */ +#define MINSIGSTKSZ (3072 * 4) + #ifndef _IA64_FPREG_DEFINED struct ia64_fpreg { unsigned long fpr_bits[2]; } __attribute__ ((aligned (16))); #define _IA64_FPREG_DEFINED #endif /* * Information pushed on stack when a signal is delivered. * This is used by the kernel to restore state following * execution of the signal handler. It is also made available * to the handler to allow it to restore state properly if * a non-standard exit is performed. * * Note that sc_regs[] and sc_fpregs[]+sc_fpcr are inline * representations of 'struct reg' and 'struct fpreg', respectively. */ typedef unsigned int osigset_t; struct osigcontext {}; /* * The sequence of the fields should match those in * mcontext_t. Keep them in sync! */ struct sigcontext { sigset_t sc_mask; /* signal mask to restore */ unsigned long sc_onstack; unsigned long sc_flags; unsigned long sc_nat; unsigned long sc_sp; unsigned long sc_ip; unsigned long sc_cfm; unsigned long sc_um; unsigned long sc_ar_rsc; unsigned long sc_ar_bsp; unsigned long sc_ar_rnat; unsigned long sc_ar_ccv; unsigned long sc_ar_unat; unsigned long sc_ar_fpsr; unsigned long sc_ar_pfs; unsigned long sc_pr; unsigned long sc_br[8]; unsigned long sc_gr[32]; struct ia64_fpreg sc_fr[128]; }; #endif /* !_ANSI_SOURCE */ #endif /* !_MACHINE_SIGNAL_H_*/ Index: head/sys/kern/imgact_aout.c =================================================================== --- head/sys/kern/imgact_aout.c (revision 68519) +++ head/sys/kern/imgact_aout.c (revision 68520) @@ -1,275 +1,277 @@ /* * Copyright (c) 1993, David Greenman * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int exec_aout_imgact __P((struct image_params *imgp)); struct sysentvec aout_sysvec = { SYS_MAXSYSCALL, sysent, 0, 0, 0, 0, 0, 0, 0, sendsig, sigcode, &szsigcode, 0, "FreeBSD a.out", - aout_coredump + aout_coredump, + NULL, + MINSIGSTKSZ }; static int exec_aout_imgact(imgp) struct image_params *imgp; { const struct exec *a_out = (const struct exec *) imgp->image_header; struct vmspace *vmspace; struct vnode *vp; vm_map_t map; vm_object_t object; vm_offset_t text_end, data_end; unsigned long virtual_offset; unsigned long file_offset; unsigned long bss_size; int error; /* * Linux and *BSD binaries look very much alike, * only the machine id is different: * 0x64 for Linux, 0x86 for *BSD, 0x00 for BSDI. * NetBSD is in network byte order.. ugh. */ if (((a_out->a_magic >> 16) & 0xff) != 0x86 && ((a_out->a_magic >> 16) & 0xff) != 0 && ((((int)ntohl(a_out->a_magic)) >> 16) & 0xff) != 0x86) return -1; /* * Set file/virtual offset based on a.out variant. * We do two cases: host byte order and network byte order * (for NetBSD compatibility) */ switch ((int)(a_out->a_magic & 0xffff)) { case ZMAGIC: virtual_offset = 0; if (a_out->a_text) { file_offset = PAGE_SIZE; } else { /* Bill's "screwball mode" */ file_offset = 0; } break; case QMAGIC: virtual_offset = PAGE_SIZE; file_offset = 0; /* Pass PS_STRINGS for BSD/OS binaries only. */ if (N_GETMID(*a_out) == MID_ZERO) imgp->ps_strings = PS_STRINGS; break; default: /* NetBSD compatibility */ switch ((int)(ntohl(a_out->a_magic) & 0xffff)) { case ZMAGIC: case QMAGIC: virtual_offset = PAGE_SIZE; file_offset = 0; break; default: return (-1); } } bss_size = roundup(a_out->a_bss, PAGE_SIZE); /* * Check various fields in header for validity/bounds. */ if (/* entry point must lay with text region */ a_out->a_entry < virtual_offset || a_out->a_entry >= virtual_offset + a_out->a_text || /* text and data size must each be page rounded */ a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) return (-1); /* text + data can't exceed file size */ if (a_out->a_data + a_out->a_text > imgp->attr->va_size) return (EFAULT); /* * text/data/bss must not exceed limits */ if (/* text can't exceed maximum text size */ a_out->a_text > MAXTSIZ || /* data + bss can't exceed rlimit */ a_out->a_data + bss_size > imgp->proc->p_rlimit[RLIMIT_DATA].rlim_cur) return (ENOMEM); /* copy in arguments and/or environment from old process */ error = exec_extract_strings(imgp); if (error) return (error); /* * Destroy old process VM and create a new one (with a new stack) */ exec_new_vmspace(imgp); /* * The vm space can be changed by exec_new_vmspace */ vmspace = imgp->proc->p_vmspace; vp = imgp->vp; map = &vmspace->vm_map; vm_map_lock(map); VOP_GETVOBJECT(vp, &object); vm_object_reference(object); text_end = virtual_offset + a_out->a_text; error = vm_map_insert(map, object, file_offset, virtual_offset, text_end, VM_PROT_READ | VM_PROT_EXECUTE, VM_PROT_ALL, MAP_COPY_ON_WRITE | MAP_PREFAULT); if (error) { vm_map_unlock(map); return (error); } data_end = text_end + a_out->a_data; if (a_out->a_data) { vm_object_reference(object); error = vm_map_insert(map, object, file_offset + a_out->a_text, text_end, data_end, VM_PROT_ALL, VM_PROT_ALL, MAP_COPY_ON_WRITE | MAP_PREFAULT); if (error) { vm_map_unlock(map); return (error); } } if (bss_size) { error = vm_map_insert(map, NULL, 0, data_end, data_end + bss_size, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) { vm_map_unlock(map); return (error); } } vm_map_unlock(map); /* Fill in process VM information */ vmspace->vm_tsize = a_out->a_text >> PAGE_SHIFT; vmspace->vm_dsize = (a_out->a_data + bss_size) >> PAGE_SHIFT; vmspace->vm_taddr = (caddr_t) (uintptr_t) virtual_offset; vmspace->vm_daddr = (caddr_t) (uintptr_t) (virtual_offset + a_out->a_text); /* Fill in image_params */ imgp->interpreted = 0; imgp->entry_addr = a_out->a_entry; imgp->proc->p_sysent = &aout_sysvec; /* Indicate that this file should not be modified */ imgp->vp->v_flag |= VTEXT; return (0); } /* * Dump core, into a file named as described in the comments for * expand_name(), unless the process was setuid/setgid. */ int aout_coredump(p, vp, limit) register struct proc *p; register struct vnode *vp; off_t limit; { register struct ucred *cred = p->p_ucred; register struct vmspace *vm = p->p_vmspace; int error; if (ctob(UPAGES + vm->vm_dsize + vm->vm_ssize) >= limit) return (EFAULT); bcopy(p, &p->p_addr->u_kproc.kp_proc, sizeof(struct proc)); fill_eproc(p, &p->p_addr->u_kproc.kp_eproc); error = cpu_coredump(p, vp, cred); if (error == 0) error = vn_rdwr(UIO_WRITE, vp, vm->vm_daddr, (int)ctob(vm->vm_dsize), (off_t)ctob(UPAGES), UIO_USERSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p); if (error == 0) error = vn_rdwr(UIO_WRITE, vp, (caddr_t) trunc_page(USRSTACK - ctob(vm->vm_ssize)), round_page(ctob(vm->vm_ssize)), (off_t)ctob(UPAGES) + ctob(vm->vm_dsize), UIO_USERSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p); return (error); } /* * Tell kern_execve.c about it, with a little help from the linker. */ static struct execsw aout_execsw = { exec_aout_imgact, "a.out" }; EXEC_SET(aout, aout_execsw); Index: head/sys/kern/imgact_elf.c =================================================================== --- head/sys/kern/imgact_elf.c (revision 68519) +++ head/sys/kern/imgact_elf.c (revision 68520) @@ -1,1024 +1,1026 @@ /*- * Copyright (c) 1995-1996 Søren Schmidt * Copyright (c) 1996 Peter Wemm * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software withough specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #include "opt_rlimit.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define OLD_EI_BRAND 8 __ElfType(Brandinfo); __ElfType(Auxargs); static int elf_check_header __P((const Elf_Ehdr *hdr)); static int elf_freebsd_fixup __P((register_t **stack_base, struct image_params *imgp)); static int elf_load_file __P((struct proc *p, const char *file, u_long *addr, u_long *entry)); static int elf_load_section __P((struct proc *p, struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot)); static int exec_elf_imgact __P((struct image_params *imgp)); static int elf_trace = 0; SYSCTL_INT(_debug, OID_AUTO, elf_trace, CTLFLAG_RW, &elf_trace, 0, ""); struct sysentvec elf_freebsd_sysvec = { SYS_MAXSYSCALL, sysent, 0, 0, 0, 0, 0, 0, elf_freebsd_fixup, sendsig, sigcode, &szsigcode, 0, "FreeBSD ELF", - elf_coredump + elf_coredump, + NULL, + MINSIGSTKSZ }; static Elf_Brandinfo freebsd_brand_info = { ELFOSABI_FREEBSD, "", "/usr/libexec/ld-elf.so.1", &elf_freebsd_sysvec }; static Elf_Brandinfo *elf_brand_list[MAX_BRANDS] = { &freebsd_brand_info, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; int elf_insert_brand_entry(Elf_Brandinfo *entry) { int i; for (i=1; ip_sysent == entry->sysvec) return TRUE; } return FALSE; } static int elf_check_header(const Elf_Ehdr *hdr) { if (!IS_ELF(*hdr) || hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || hdr->e_ident[EI_DATA] != ELF_TARG_DATA || hdr->e_ident[EI_VERSION] != EV_CURRENT) return ENOEXEC; if (!ELF_MACHINE_OK(hdr->e_machine)) return ENOEXEC; if (hdr->e_version != ELF_TARG_VER) return ENOEXEC; return 0; } static int elf_load_section(struct proc *p, struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot) { size_t map_len; vm_offset_t map_addr; int error, rv; size_t copy_len; vm_object_t object; vm_offset_t file_addr; vm_offset_t data_buf = 0; VOP_GETVOBJECT(vp, &object); error = 0; /* * It's necessary to fail if the filsz + offset taken from the * header is greater than the actual file pager object's size. * If we were to allow this, then the vm_map_find() below would * walk right off the end of the file object and into the ether. * * While I'm here, might as well check for something else that * is invalid: filsz cannot be greater than memsz. */ if ((off_t)filsz + offset > object->un_pager.vnp.vnp_size || filsz > memsz) { uprintf("elf_load_section: truncated ELF file\n"); return (ENOEXEC); } map_addr = trunc_page((vm_offset_t)vmaddr); file_addr = trunc_page(offset); /* * We have two choices. We can either clear the data in the last page * of an oversized mapping, or we can start the anon mapping a page * early and copy the initialized data into that first page. We * choose the second.. */ if (memsz > filsz) map_len = trunc_page(offset+filsz) - file_addr; else map_len = round_page(offset+filsz) - file_addr; if (map_len != 0) { vm_object_reference(object); vm_map_lock(&vmspace->vm_map); rv = vm_map_insert(&vmspace->vm_map, object, file_addr, /* file offset */ map_addr, /* virtual start */ map_addr + map_len,/* virtual end */ prot, VM_PROT_ALL, MAP_COPY_ON_WRITE | MAP_PREFAULT); vm_map_unlock(&vmspace->vm_map); if (rv != KERN_SUCCESS) { vm_object_deallocate(object); return EINVAL; } /* we can stop now if we've covered it all */ if (memsz == filsz) return 0; } /* * We have to get the remaining bit of the file into the first part * of the oversized map segment. This is normally because the .data * segment in the file is extended to provide bss. It's a neat idea * to try and save a page, but it's a pain in the behind to implement. */ copy_len = (offset + filsz) - trunc_page(offset + filsz); map_addr = trunc_page((vm_offset_t)vmaddr + filsz); map_len = round_page((vm_offset_t)vmaddr + memsz) - map_addr; /* This had damn well better be true! */ if (map_len != 0) { vm_map_lock(&vmspace->vm_map); rv = vm_map_insert(&vmspace->vm_map, NULL, 0, map_addr, map_addr + map_len, VM_PROT_ALL, VM_PROT_ALL, 0); vm_map_unlock(&vmspace->vm_map); if (rv != KERN_SUCCESS) return EINVAL; } if (copy_len != 0) { vm_object_reference(object); rv = vm_map_find(exec_map, object, trunc_page(offset + filsz), &data_buf, PAGE_SIZE, TRUE, VM_PROT_READ, VM_PROT_ALL, MAP_COPY_ON_WRITE | MAP_PREFAULT_PARTIAL); if (rv != KERN_SUCCESS) { vm_object_deallocate(object); return EINVAL; } /* send the page fragment to user space */ error = copyout((caddr_t)data_buf, (caddr_t)map_addr, copy_len); vm_map_remove(exec_map, data_buf, data_buf + PAGE_SIZE); if (error) return (error); } /* * set it to the specified protection */ vm_map_protect(&vmspace->vm_map, map_addr, map_addr + map_len, prot, FALSE); return error; } /* * Load the file "file" into memory. It may be either a shared object * or an executable. * * The "addr" reference parameter is in/out. On entry, it specifies * the address where a shared object should be loaded. If the file is * an executable, this value is ignored. On exit, "addr" specifies * where the file was actually loaded. * * The "entry" reference parameter is out only. On exit, it specifies * the entry point for the loaded file. */ static int elf_load_file(struct proc *p, const char *file, u_long *addr, u_long *entry) { const Elf_Ehdr *hdr = NULL; const Elf_Phdr *phdr = NULL; struct nameidata nd; struct vmspace *vmspace = p->p_vmspace; struct vattr attr; struct image_params image_params, *imgp; vm_prot_t prot; u_long rbase; u_long base_addr = 0; int error, i, numsegs; imgp = &image_params; /* * Initialize part of the common data */ imgp->proc = p; imgp->uap = NULL; imgp->attr = &attr; imgp->firstpage = NULL; imgp->image_header = (char *)kmem_alloc_wait(exec_map, PAGE_SIZE); if (imgp->image_header == NULL) { nd.ni_vp = NULL; error = ENOMEM; goto fail; } NDINIT(&nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_SYSSPACE, file, p); if ((error = namei(&nd)) != 0) { nd.ni_vp = NULL; goto fail; } NDFREE(&nd, NDF_ONLY_PNBUF); imgp->vp = nd.ni_vp; /* * Check permissions, modes, uid, etc on the file, and "open" it. */ error = exec_check_permissions(imgp); if (error) { VOP_UNLOCK(nd.ni_vp, 0, p); goto fail; } error = exec_map_first_page(imgp); /* * Also make certain that the interpreter stays the same, so set * its VTEXT flag, too. */ if (error == 0) nd.ni_vp->v_flag |= VTEXT; VOP_UNLOCK(nd.ni_vp, 0, p); if (error) goto fail; hdr = (const Elf_Ehdr *)imgp->image_header; if ((error = elf_check_header(hdr)) != 0) goto fail; if (hdr->e_type == ET_DYN) rbase = *addr; else if (hdr->e_type == ET_EXEC) rbase = 0; else { error = ENOEXEC; goto fail; } /* Only support headers that fit within first page for now */ if ((hdr->e_phoff > PAGE_SIZE) || (hdr->e_phoff + hdr->e_phentsize * hdr->e_phnum) > PAGE_SIZE) { error = ENOEXEC; goto fail; } phdr = (const Elf_Phdr *)(imgp->image_header + hdr->e_phoff); for (i = 0, numsegs = 0; i < hdr->e_phnum; i++) { if (phdr[i].p_type == PT_LOAD) { /* Loadable segment */ prot = 0; if (phdr[i].p_flags & PF_X) prot |= VM_PROT_EXECUTE; if (phdr[i].p_flags & PF_W) prot |= VM_PROT_WRITE; if (phdr[i].p_flags & PF_R) prot |= VM_PROT_READ; if ((error = elf_load_section(p, vmspace, nd.ni_vp, phdr[i].p_offset, (caddr_t)phdr[i].p_vaddr + rbase, phdr[i].p_memsz, phdr[i].p_filesz, prot)) != 0) goto fail; /* * Establish the base address if this is the * first segment. */ if (numsegs == 0) base_addr = trunc_page(phdr[i].p_vaddr + rbase); numsegs++; } } *addr = base_addr; *entry=(unsigned long)hdr->e_entry + rbase; fail: if (imgp->firstpage) exec_unmap_first_page(imgp); if (imgp->image_header) kmem_free_wakeup(exec_map, (vm_offset_t)imgp->image_header, PAGE_SIZE); if (nd.ni_vp) vrele(nd.ni_vp); return error; } static int fallback_elf_brand = ELFOSABI_FREEBSD; SYSCTL_INT(_kern, OID_AUTO, fallback_elf_brand, CTLFLAG_RW, &fallback_elf_brand, ELFOSABI_FREEBSD, "ELF brand of last resort"); static int exec_elf_imgact(struct image_params *imgp) { const Elf_Ehdr *hdr = (const Elf_Ehdr *) imgp->image_header; const Elf_Phdr *phdr; Elf_Auxargs *elf_auxargs = NULL; struct vmspace *vmspace; vm_prot_t prot; u_long text_size = 0, data_size = 0; u_long text_addr = 0, data_addr = 0; u_long addr, entry = 0, proghdr = 0; int error, i; const char *interp = NULL; Elf_Brandinfo *brand_info; char path[MAXPATHLEN]; /* * Do we have a valid ELF header ? */ if (elf_check_header(hdr) != 0 || hdr->e_type != ET_EXEC) return -1; /* * From here on down, we return an errno, not -1, as we've * detected an ELF file. */ if ((hdr->e_phoff > PAGE_SIZE) || (hdr->e_phoff + hdr->e_phentsize * hdr->e_phnum) > PAGE_SIZE) { /* Only support headers in first page for now */ return ENOEXEC; } phdr = (const Elf_Phdr*)(imgp->image_header + hdr->e_phoff); /* * From this point on, we may have resources that need to be freed. */ /* * Yeah, I'm paranoid. There is every reason in the world to get * VTEXT now since from here on out, there are places we can have * a context switch. Better safe than sorry; I really don't want * the file to change while it's being loaded. */ mtx_enter(&imgp->vp->v_interlock, MTX_DEF); imgp->vp->v_flag |= VTEXT; mtx_exit(&imgp->vp->v_interlock, MTX_DEF); if ((error = exec_extract_strings(imgp)) != 0) goto fail; exec_new_vmspace(imgp); vmspace = imgp->proc->p_vmspace; for (i = 0; i < hdr->e_phnum; i++) { switch(phdr[i].p_type) { case PT_LOAD: /* Loadable segment */ prot = 0; if (phdr[i].p_flags & PF_X) prot |= VM_PROT_EXECUTE; if (phdr[i].p_flags & PF_W) prot |= VM_PROT_WRITE; if (phdr[i].p_flags & PF_R) prot |= VM_PROT_READ; if ((error = elf_load_section(imgp->proc, vmspace, imgp->vp, phdr[i].p_offset, (caddr_t)phdr[i].p_vaddr, phdr[i].p_memsz, phdr[i].p_filesz, prot)) != 0) goto fail; /* * Is this .text or .data ?? * * We only handle one each of those yet XXX */ if (hdr->e_entry >= phdr[i].p_vaddr && hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) { text_addr = trunc_page(phdr[i].p_vaddr); text_size = round_page(phdr[i].p_memsz + phdr[i].p_vaddr - text_addr); entry = (u_long)hdr->e_entry; } else { data_addr = trunc_page(phdr[i].p_vaddr); data_size = round_page(phdr[i].p_memsz + phdr[i].p_vaddr - data_addr); } break; case PT_INTERP: /* Path to interpreter */ if (phdr[i].p_filesz > MAXPATHLEN || phdr[i].p_offset + phdr[i].p_filesz > PAGE_SIZE) { error = ENOEXEC; goto fail; } interp = imgp->image_header + phdr[i].p_offset; break; case PT_PHDR: /* Program header table info */ proghdr = phdr[i].p_vaddr; break; default: break; } } vmspace->vm_tsize = text_size >> PAGE_SHIFT; vmspace->vm_taddr = (caddr_t)(uintptr_t)text_addr; vmspace->vm_dsize = data_size >> PAGE_SHIFT; vmspace->vm_daddr = (caddr_t)(uintptr_t)data_addr; addr = ELF_RTLD_ADDR(vmspace); imgp->entry_addr = entry; brand_info = NULL; /* XXX For now we look for the magic "FreeBSD" that we used to put * into the ELF header at the EI_ABIVERSION location. If found use * that information rather than figuring out the ABI from proper * branding. This should be removed for 5.0-RELEASE. The Linux caes * can be figured out from the `interp_path' field. */ if (strcmp("FreeBSD", (const char *)&hdr->e_ident[OLD_EI_BRAND]) == 0) brand_info = &freebsd_brand_info; /* If the executable has a brand, search for it in the brand list. */ if (brand_info == NULL) { for (i = 0; i < MAX_BRANDS; i++) { Elf_Brandinfo *bi = elf_brand_list[i]; if (bi != NULL && hdr->e_ident[EI_OSABI] == bi->brand) { brand_info = bi; break; } } } /* Lacking a known brand, search for a recognized interpreter. */ if (brand_info == NULL && interp != NULL) { for (i = 0; i < MAX_BRANDS; i++) { Elf_Brandinfo *bi = elf_brand_list[i]; if (bi != NULL && strcmp(interp, bi->interp_path) == 0) { brand_info = bi; break; } } } /* Lacking a recognized interpreter, try the default brand */ if (brand_info == NULL) { for (i = 0; i < MAX_BRANDS; i++) { Elf_Brandinfo *bi = elf_brand_list[i]; if (bi != NULL && fallback_elf_brand == bi->brand) { brand_info = bi; break; } } } /* XXX - Assume FreeBSD after the branding method change. */ if (brand_info == NULL) brand_info = &freebsd_brand_info; if (brand_info == NULL) { uprintf("ELF binary type \"%u\" not known.\n", hdr->e_ident[EI_OSABI]); error = ENOEXEC; goto fail; } imgp->proc->p_sysent = brand_info->sysvec; if (interp != NULL) { snprintf(path, sizeof(path), "%s%s", brand_info->emul_path, interp); if ((error = elf_load_file(imgp->proc, path, &addr, &imgp->entry_addr)) != 0) { if ((error = elf_load_file(imgp->proc, interp, &addr, &imgp->entry_addr)) != 0) { uprintf("ELF interpreter %s not found\n", path); goto fail; } } } /* * Construct auxargs table (used by the fixup routine) */ elf_auxargs = malloc(sizeof(Elf_Auxargs), M_TEMP, M_WAITOK); elf_auxargs->execfd = -1; elf_auxargs->phdr = proghdr; elf_auxargs->phent = hdr->e_phentsize; elf_auxargs->phnum = hdr->e_phnum; elf_auxargs->pagesz = PAGE_SIZE; elf_auxargs->base = addr; elf_auxargs->flags = 0; elf_auxargs->entry = entry; elf_auxargs->trace = elf_trace; imgp->auxargs = elf_auxargs; imgp->interpreted = 0; fail: return error; } static int elf_freebsd_fixup(register_t **stack_base, struct image_params *imgp) { Elf_Auxargs *args = (Elf_Auxargs *)imgp->auxargs; register_t *pos; pos = *stack_base + (imgp->argc + imgp->envc + 2); if (args->trace) { AUXARGS_ENTRY(pos, AT_DEBUG, 1); } if (args->execfd != -1) { AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); } AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); AUXARGS_ENTRY(pos, AT_PHENT, args->phent); AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); AUXARGS_ENTRY(pos, AT_BASE, args->base); AUXARGS_ENTRY(pos, AT_NULL, 0); free(imgp->auxargs, M_TEMP); imgp->auxargs = NULL; (*stack_base)--; suword(*stack_base, (long) imgp->argc); return 0; } /* * Code for generating ELF core dumps. */ typedef void (*segment_callback) __P((vm_map_entry_t, void *)); /* Closure for cb_put_phdr(). */ struct phdr_closure { Elf_Phdr *phdr; /* Program header to fill in */ Elf_Off offset; /* Offset of segment in core file */ }; /* Closure for cb_size_segment(). */ struct sseg_closure { int count; /* Count of writable segments. */ size_t size; /* Total size of all writable segments. */ }; static void cb_put_phdr __P((vm_map_entry_t, void *)); static void cb_size_segment __P((vm_map_entry_t, void *)); static void each_writable_segment __P((struct proc *, segment_callback, void *)); static int elf_corehdr __P((struct proc *, struct vnode *, struct ucred *, int, void *, size_t)); static void elf_puthdr __P((struct proc *, void *, size_t *, const prstatus_t *, const prfpregset_t *, const prpsinfo_t *, int)); static void elf_putnote __P((void *, size_t *, const char *, int, const void *, size_t)); extern int osreldate; int elf_coredump(p, vp, limit) register struct proc *p; register struct vnode *vp; off_t limit; { register struct ucred *cred = p->p_ucred; int error = 0; struct sseg_closure seginfo; void *hdr; size_t hdrsize; /* Size the program segments. */ seginfo.count = 0; seginfo.size = 0; each_writable_segment(p, cb_size_segment, &seginfo); /* * Calculate the size of the core file header area by making * a dry run of generating it. Nothing is written, but the * size is calculated. */ hdrsize = 0; elf_puthdr((struct proc *)NULL, (void *)NULL, &hdrsize, (const prstatus_t *)NULL, (const prfpregset_t *)NULL, (const prpsinfo_t *)NULL, seginfo.count); if (hdrsize + seginfo.size >= limit) return (EFAULT); /* * Allocate memory for building the header, fill it up, * and write it out. */ hdr = malloc(hdrsize, M_TEMP, M_WAITOK); if (hdr == NULL) { return EINVAL; } error = elf_corehdr(p, vp, cred, seginfo.count, hdr, hdrsize); /* Write the contents of all of the writable segments. */ if (error == 0) { Elf_Phdr *php; off_t offset; int i; php = (Elf_Phdr *)((char *)hdr + sizeof(Elf_Ehdr)) + 1; offset = hdrsize; for (i = 0; i < seginfo.count; i++) { error = vn_rdwr(UIO_WRITE, vp, (caddr_t)php->p_vaddr, php->p_filesz, offset, UIO_USERSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p); if (error != 0) break; offset += php->p_filesz; php++; } } free(hdr, M_TEMP); return error; } /* * A callback for each_writable_segment() to write out the segment's * program header entry. */ static void cb_put_phdr(entry, closure) vm_map_entry_t entry; void *closure; { struct phdr_closure *phc = (struct phdr_closure *)closure; Elf_Phdr *phdr = phc->phdr; phc->offset = round_page(phc->offset); phdr->p_type = PT_LOAD; phdr->p_offset = phc->offset; phdr->p_vaddr = entry->start; phdr->p_paddr = 0; phdr->p_filesz = phdr->p_memsz = entry->end - entry->start; phdr->p_align = PAGE_SIZE; phdr->p_flags = 0; if (entry->protection & VM_PROT_READ) phdr->p_flags |= PF_R; if (entry->protection & VM_PROT_WRITE) phdr->p_flags |= PF_W; if (entry->protection & VM_PROT_EXECUTE) phdr->p_flags |= PF_X; phc->offset += phdr->p_filesz; phc->phdr++; } /* * A callback for each_writable_segment() to gather information about * the number of segments and their total size. */ static void cb_size_segment(entry, closure) vm_map_entry_t entry; void *closure; { struct sseg_closure *ssc = (struct sseg_closure *)closure; ssc->count++; ssc->size += entry->end - entry->start; } /* * For each writable segment in the process's memory map, call the given * function with a pointer to the map entry and some arbitrary * caller-supplied data. */ static void each_writable_segment(p, func, closure) struct proc *p; segment_callback func; void *closure; { vm_map_t map = &p->p_vmspace->vm_map; vm_map_entry_t entry; for (entry = map->header.next; entry != &map->header; entry = entry->next) { vm_object_t obj; if ((entry->eflags & MAP_ENTRY_IS_SUB_MAP) || (entry->protection & (VM_PROT_READ|VM_PROT_WRITE)) != (VM_PROT_READ|VM_PROT_WRITE)) continue; /* ** Dont include memory segment in the coredump if ** MAP_NOCORE is set in mmap(2) or MADV_NOCORE in ** madvise(2). */ if (entry->eflags & MAP_ENTRY_NOCOREDUMP) continue; if ((obj = entry->object.vm_object) == NULL) continue; /* Find the deepest backing object. */ while (obj->backing_object != NULL) obj = obj->backing_object; /* Ignore memory-mapped devices and such things. */ if (obj->type != OBJT_DEFAULT && obj->type != OBJT_SWAP && obj->type != OBJT_VNODE) continue; (*func)(entry, closure); } } /* * Write the core file header to the file, including padding up to * the page boundary. */ static int elf_corehdr(p, vp, cred, numsegs, hdr, hdrsize) struct proc *p; struct vnode *vp; struct ucred *cred; int numsegs; size_t hdrsize; void *hdr; { size_t off; prstatus_t status; prfpregset_t fpregset; prpsinfo_t psinfo; /* Gather the information for the header. */ bzero(&status, sizeof status); status.pr_version = PRSTATUS_VERSION; status.pr_statussz = sizeof(prstatus_t); status.pr_gregsetsz = sizeof(gregset_t); status.pr_fpregsetsz = sizeof(fpregset_t); status.pr_osreldate = osreldate; status.pr_cursig = p->p_sig; status.pr_pid = p->p_pid; fill_regs(p, &status.pr_reg); fill_fpregs(p, &fpregset); bzero(&psinfo, sizeof psinfo); psinfo.pr_version = PRPSINFO_VERSION; psinfo.pr_psinfosz = sizeof(prpsinfo_t); strncpy(psinfo.pr_fname, p->p_comm, MAXCOMLEN); /* XXX - We don't fill in the command line arguments properly yet. */ strncpy(psinfo.pr_psargs, p->p_comm, PRARGSZ); /* Fill in the header. */ bzero(hdr, hdrsize); off = 0; elf_puthdr(p, hdr, &off, &status, &fpregset, &psinfo, numsegs); /* Write it to the core file. */ return vn_rdwr(UIO_WRITE, vp, hdr, hdrsize, (off_t)0, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, NULL, p); } static void elf_puthdr(struct proc *p, void *dst, size_t *off, const prstatus_t *status, const prfpregset_t *fpregset, const prpsinfo_t *psinfo, int numsegs) { size_t ehoff; size_t phoff; size_t noteoff; size_t notesz; ehoff = *off; *off += sizeof(Elf_Ehdr); phoff = *off; *off += (numsegs + 1) * sizeof(Elf_Phdr); noteoff = *off; elf_putnote(dst, off, "FreeBSD", NT_PRSTATUS, status, sizeof *status); elf_putnote(dst, off, "FreeBSD", NT_FPREGSET, fpregset, sizeof *fpregset); elf_putnote(dst, off, "FreeBSD", NT_PRPSINFO, psinfo, sizeof *psinfo); notesz = *off - noteoff; /* Align up to a page boundary for the program segments. */ *off = round_page(*off); if (dst != NULL) { Elf_Ehdr *ehdr; Elf_Phdr *phdr; struct phdr_closure phc; /* * Fill in the ELF header. */ ehdr = (Elf_Ehdr *)((char *)dst + ehoff); ehdr->e_ident[EI_MAG0] = ELFMAG0; ehdr->e_ident[EI_MAG1] = ELFMAG1; ehdr->e_ident[EI_MAG2] = ELFMAG2; ehdr->e_ident[EI_MAG3] = ELFMAG3; ehdr->e_ident[EI_CLASS] = ELF_CLASS; ehdr->e_ident[EI_DATA] = ELF_DATA; ehdr->e_ident[EI_VERSION] = EV_CURRENT; ehdr->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; ehdr->e_ident[EI_ABIVERSION] = 0; ehdr->e_ident[EI_PAD] = 0; ehdr->e_type = ET_CORE; ehdr->e_machine = ELF_ARCH; ehdr->e_version = EV_CURRENT; ehdr->e_entry = 0; ehdr->e_phoff = phoff; ehdr->e_flags = 0; ehdr->e_ehsize = sizeof(Elf_Ehdr); ehdr->e_phentsize = sizeof(Elf_Phdr); ehdr->e_phnum = numsegs + 1; ehdr->e_shentsize = sizeof(Elf_Shdr); ehdr->e_shnum = 0; ehdr->e_shstrndx = SHN_UNDEF; /* * Fill in the program header entries. */ phdr = (Elf_Phdr *)((char *)dst + phoff); /* The note segement. */ phdr->p_type = PT_NOTE; phdr->p_offset = noteoff; phdr->p_vaddr = 0; phdr->p_paddr = 0; phdr->p_filesz = notesz; phdr->p_memsz = 0; phdr->p_flags = 0; phdr->p_align = 0; phdr++; /* All the writable segments from the program. */ phc.phdr = phdr; phc.offset = *off; each_writable_segment(p, cb_put_phdr, &phc); } } static void elf_putnote(void *dst, size_t *off, const char *name, int type, const void *desc, size_t descsz) { Elf_Note note; note.n_namesz = strlen(name) + 1; note.n_descsz = descsz; note.n_type = type; if (dst != NULL) bcopy(¬e, (char *)dst + *off, sizeof note); *off += sizeof note; if (dst != NULL) bcopy(name, (char *)dst + *off, note.n_namesz); *off += roundup2(note.n_namesz, sizeof(Elf_Size)); if (dst != NULL) bcopy(desc, (char *)dst + *off, note.n_descsz); *off += roundup2(note.n_descsz, sizeof(Elf_Size)); } /* * Tell kern_execve.c about it, with a little help from the linker. */ static struct execsw elf_execsw = {exec_elf_imgact, "ELF"}; EXEC_SET(elf, elf_execsw); Index: head/sys/kern/kern_sig.c =================================================================== --- head/sys/kern/kern_sig.c (revision 68519) +++ head/sys/kern/kern_sig.c (revision 68520) @@ -1,1787 +1,1787 @@ /* * Copyright (c) 1982, 1986, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_sig.c 8.7 (Berkeley) 4/18/94 * $FreeBSD$ */ #include "opt_compat.h" #include "opt_ktrace.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define ONSIG 32 /* NSIG for osig* syscalls. XXX. */ static int coredump __P((struct proc *)); static int do_sigaction __P((struct proc *p, int sig, struct sigaction *act, struct sigaction *oact, int old)); static int do_sigprocmask __P((struct proc *p, int how, sigset_t *set, sigset_t *oset, int old)); static char *expand_name __P((const char *, uid_t, pid_t)); static int killpg1 __P((struct proc *cp, int sig, int pgid, int all)); static int sig_ffs __P((sigset_t *set)); static int sigprop __P((int sig)); static void stop __P((struct proc *)); static int filt_sigattach(struct knote *kn); static void filt_sigdetach(struct knote *kn); static int filt_signal(struct knote *kn, long hint); struct filterops sig_filtops = { 0, filt_sigattach, filt_sigdetach, filt_signal }; static int kern_logsigexit = 1; SYSCTL_INT(_kern, KERN_LOGSIGEXIT, logsigexit, CTLFLAG_RW, &kern_logsigexit, 0, "Log processes quitting on abnormal signals to syslog(3)"); /* * Can process p, with pcred pc, send the signal sig to process q? */ #define CANSIGNAL(p, q, sig) \ (!p_can(p, q, P_CAN_KILL, NULL) || \ ((sig) == SIGCONT && (q)->p_session == (p)->p_session)) /* * Policy -- Can real uid ruid with ucred uc send a signal to process q? */ #define CANSIGIO(ruid, uc, q) \ ((uc)->cr_uid == 0 || \ (ruid) == (q)->p_cred->p_ruid || \ (uc)->cr_uid == (q)->p_cred->p_ruid || \ (ruid) == (q)->p_ucred->cr_uid || \ (uc)->cr_uid == (q)->p_ucred->cr_uid) int sugid_coredump; SYSCTL_INT(_kern, OID_AUTO, sugid_coredump, CTLFLAG_RW, &sugid_coredump, 0, "Enable coredumping set user/group ID processes"); static int do_coredump = 1; SYSCTL_INT(_kern, OID_AUTO, coredump, CTLFLAG_RW, &do_coredump, 0, "Enable/Disable coredumps"); /* * Signal properties and actions. * The array below categorizes the signals and their default actions * according to the following properties: */ #define SA_KILL 0x01 /* terminates process by default */ #define SA_CORE 0x02 /* ditto and coredumps */ #define SA_STOP 0x04 /* suspend process */ #define SA_TTYSTOP 0x08 /* ditto, from tty */ #define SA_IGNORE 0x10 /* ignore by default */ #define SA_CONT 0x20 /* continue if suspended */ #define SA_CANTMASK 0x40 /* non-maskable, catchable */ static int sigproptbl[NSIG] = { SA_KILL, /* SIGHUP */ SA_KILL, /* SIGINT */ SA_KILL|SA_CORE, /* SIGQUIT */ SA_KILL|SA_CORE, /* SIGILL */ SA_KILL|SA_CORE, /* SIGTRAP */ SA_KILL|SA_CORE, /* SIGABRT */ SA_KILL|SA_CORE, /* SIGEMT */ SA_KILL|SA_CORE, /* SIGFPE */ SA_KILL, /* SIGKILL */ SA_KILL|SA_CORE, /* SIGBUS */ SA_KILL|SA_CORE, /* SIGSEGV */ SA_KILL|SA_CORE, /* SIGSYS */ SA_KILL, /* SIGPIPE */ SA_KILL, /* SIGALRM */ SA_KILL, /* SIGTERM */ SA_IGNORE, /* SIGURG */ SA_STOP, /* SIGSTOP */ SA_STOP|SA_TTYSTOP, /* SIGTSTP */ SA_IGNORE|SA_CONT, /* SIGCONT */ SA_IGNORE, /* SIGCHLD */ SA_STOP|SA_TTYSTOP, /* SIGTTIN */ SA_STOP|SA_TTYSTOP, /* SIGTTOU */ SA_IGNORE, /* SIGIO */ SA_KILL, /* SIGXCPU */ SA_KILL, /* SIGXFSZ */ SA_KILL, /* SIGVTALRM */ SA_KILL, /* SIGPROF */ SA_IGNORE, /* SIGWINCH */ SA_IGNORE, /* SIGINFO */ SA_KILL, /* SIGUSR1 */ SA_KILL, /* SIGUSR2 */ }; /* * Determine signal that should be delivered to process p, the current * process, 0 if none. If there is a pending stop signal with default * action, the process stops in issignal(). * * MP SAFE. */ int CURSIG(struct proc *p) { sigset_t tmpset; int r; if (SIGISEMPTY(p->p_siglist)) return (0); tmpset = p->p_siglist; SIGSETNAND(tmpset, p->p_sigmask); if (SIGISEMPTY(tmpset) && (p->p_flag & P_TRACED) == 0) return (0); mtx_enter(&Giant, MTX_DEF); r = issignal(p); mtx_exit(&Giant, MTX_DEF); return (r); } static __inline int sigprop(int sig) { if (sig > 0 && sig < NSIG) return (sigproptbl[_SIG_IDX(sig)]); return (0); } static __inline int sig_ffs(sigset_t *set) { int i; for (i = 0; i < _SIG_WORDS; i++) if (set->__bits[i]) return (ffs(set->__bits[i]) + (i * 32)); return (0); } /* * do_sigaction * sigaction * osigaction */ static int do_sigaction(p, sig, act, oact, old) struct proc *p; register int sig; struct sigaction *act, *oact; int old; { register struct sigacts *ps = p->p_sigacts; if (sig <= 0 || sig > _SIG_MAXSIG) return (EINVAL); if (oact) { oact->sa_handler = ps->ps_sigact[_SIG_IDX(sig)]; oact->sa_mask = ps->ps_catchmask[_SIG_IDX(sig)]; oact->sa_flags = 0; if (SIGISMEMBER(ps->ps_sigonstack, sig)) oact->sa_flags |= SA_ONSTACK; if (!SIGISMEMBER(ps->ps_sigintr, sig)) oact->sa_flags |= SA_RESTART; if (SIGISMEMBER(ps->ps_sigreset, sig)) oact->sa_flags |= SA_RESETHAND; if (SIGISMEMBER(ps->ps_signodefer, sig)) oact->sa_flags |= SA_NODEFER; if (SIGISMEMBER(ps->ps_siginfo, sig)) oact->sa_flags |= SA_SIGINFO; if (sig == SIGCHLD && p->p_procsig->ps_flag & PS_NOCLDSTOP) oact->sa_flags |= SA_NOCLDSTOP; if (sig == SIGCHLD && p->p_procsig->ps_flag & PS_NOCLDWAIT) oact->sa_flags |= SA_NOCLDWAIT; } if (act) { if ((sig == SIGKILL || sig == SIGSTOP) && act->sa_handler != SIG_DFL) return (EINVAL); /* * Change setting atomically. */ (void) splhigh(); ps->ps_catchmask[_SIG_IDX(sig)] = act->sa_mask; SIG_CANTMASK(ps->ps_catchmask[_SIG_IDX(sig)]); if (act->sa_flags & SA_SIGINFO) { ps->ps_sigact[_SIG_IDX(sig)] = act->sa_handler; SIGADDSET(ps->ps_siginfo, sig); } else { ps->ps_sigact[_SIG_IDX(sig)] = (__sighandler_t *)act->sa_sigaction; SIGDELSET(ps->ps_siginfo, sig); } if (!(act->sa_flags & SA_RESTART)) SIGADDSET(ps->ps_sigintr, sig); else SIGDELSET(ps->ps_sigintr, sig); if (act->sa_flags & SA_ONSTACK) SIGADDSET(ps->ps_sigonstack, sig); else SIGDELSET(ps->ps_sigonstack, sig); if (act->sa_flags & SA_RESETHAND) SIGADDSET(ps->ps_sigreset, sig); else SIGDELSET(ps->ps_sigreset, sig); if (act->sa_flags & SA_NODEFER) SIGADDSET(ps->ps_signodefer, sig); else SIGDELSET(ps->ps_signodefer, sig); #ifdef COMPAT_SUNOS if (act->sa_flags & SA_USERTRAMP) SIGADDSET(ps->ps_usertramp, sig); else SIGDELSET(ps->ps_usertramp, seg); #endif if (sig == SIGCHLD) { if (act->sa_flags & SA_NOCLDSTOP) p->p_procsig->ps_flag |= PS_NOCLDSTOP; else p->p_procsig->ps_flag &= ~PS_NOCLDSTOP; if (act->sa_flags & SA_NOCLDWAIT) { /* * Paranoia: since SA_NOCLDWAIT is implemented * by reparenting the dying child to PID 1 (and * trust it to reap the zombie), PID 1 itself * is forbidden to set SA_NOCLDWAIT. */ if (p->p_pid == 1) p->p_procsig->ps_flag &= ~PS_NOCLDWAIT; else p->p_procsig->ps_flag |= PS_NOCLDWAIT; } else p->p_procsig->ps_flag &= ~PS_NOCLDWAIT; } /* * Set bit in p_sigignore for signals that are set to SIG_IGN, * and for signals set to SIG_DFL where the default is to * ignore. However, don't put SIGCONT in p_sigignore, as we * have to restart the process. */ if (ps->ps_sigact[_SIG_IDX(sig)] == SIG_IGN || (sigprop(sig) & SA_IGNORE && ps->ps_sigact[_SIG_IDX(sig)] == SIG_DFL)) { /* never to be seen again */ SIGDELSET(p->p_siglist, sig); if (sig != SIGCONT) /* easier in psignal */ SIGADDSET(p->p_sigignore, sig); SIGDELSET(p->p_sigcatch, sig); } else { SIGDELSET(p->p_sigignore, sig); if (ps->ps_sigact[_SIG_IDX(sig)] == SIG_DFL) SIGDELSET(p->p_sigcatch, sig); else SIGADDSET(p->p_sigcatch, sig); } if (ps->ps_sigact[_SIG_IDX(sig)] == SIG_IGN || ps->ps_sigact[_SIG_IDX(sig)] == SIG_DFL || !old) SIGDELSET(ps->ps_osigset, sig); else SIGADDSET(ps->ps_osigset, sig); (void) spl0(); } return (0); } #ifndef _SYS_SYSPROTO_H_ struct sigaction_args { int sig; struct sigaction *act; struct sigaction *oact; }; #endif /* ARGSUSED */ int sigaction(p, uap) struct proc *p; register struct sigaction_args *uap; { struct sigaction act, oact; register struct sigaction *actp, *oactp; int error; actp = (uap->act != NULL) ? &act : NULL; oactp = (uap->oact != NULL) ? &oact : NULL; if (actp) { error = copyin(uap->act, actp, sizeof(act)); if (error) return (error); } error = do_sigaction(p, uap->sig, actp, oactp, 0); if (oactp && !error) { error = copyout(oactp, uap->oact, sizeof(oact)); } return (error); } #ifdef COMPAT_43 /* XXX - COMPAT_FBSD3 */ #ifndef _SYS_SYSPROTO_H_ struct osigaction_args { int signum; struct osigaction *nsa; struct osigaction *osa; }; #endif /* ARGSUSED */ int osigaction(p, uap) struct proc *p; register struct osigaction_args *uap; { struct osigaction sa; struct sigaction nsa, osa; register struct sigaction *nsap, *osap; int error; if (uap->signum <= 0 || uap->signum >= ONSIG) return (EINVAL); nsap = (uap->nsa != NULL) ? &nsa : NULL; osap = (uap->osa != NULL) ? &osa : NULL; if (nsap) { error = copyin(uap->nsa, &sa, sizeof(sa)); if (error) return (error); nsap->sa_handler = sa.sa_handler; nsap->sa_flags = sa.sa_flags; OSIG2SIG(sa.sa_mask, nsap->sa_mask); } error = do_sigaction(p, uap->signum, nsap, osap, 1); if (osap && !error) { sa.sa_handler = osap->sa_handler; sa.sa_flags = osap->sa_flags; SIG2OSIG(osap->sa_mask, sa.sa_mask); error = copyout(&sa, uap->osa, sizeof(sa)); } return (error); } #endif /* COMPAT_43 */ /* * Initialize signal state for process 0; * set to ignore signals that are ignored by default. */ void siginit(p) struct proc *p; { register int i; for (i = 1; i <= NSIG; i++) if (sigprop(i) & SA_IGNORE && i != SIGCONT) SIGADDSET(p->p_sigignore, i); } /* * Reset signals for an exec of the specified process. */ void execsigs(p) register struct proc *p; { register struct sigacts *ps = p->p_sigacts; register int sig; /* * Reset caught signals. Held signals remain held * through p_sigmask (unless they were caught, * and are now ignored by default). */ while (SIGNOTEMPTY(p->p_sigcatch)) { sig = sig_ffs(&p->p_sigcatch); SIGDELSET(p->p_sigcatch, sig); if (sigprop(sig) & SA_IGNORE) { if (sig != SIGCONT) SIGADDSET(p->p_sigignore, sig); SIGDELSET(p->p_siglist, sig); } ps->ps_sigact[_SIG_IDX(sig)] = SIG_DFL; } /* * Reset stack state to the user stack. * Clear set of signals caught on the signal stack. */ p->p_sigstk.ss_flags = SS_DISABLE; p->p_sigstk.ss_size = 0; p->p_sigstk.ss_sp = 0; /* * Reset no zombies if child dies flag as Solaris does. */ p->p_procsig->ps_flag &= ~PS_NOCLDWAIT; } /* * do_sigprocmask() - MP SAFE ONLY IF p == curproc * * Manipulate signal mask. This routine is MP SAFE *ONLY* if * p == curproc. Also remember that in order to remain MP SAFE * no spl*() calls may be made. */ static int do_sigprocmask(p, how, set, oset, old) struct proc *p; int how; sigset_t *set, *oset; int old; { int error; if (oset != NULL) *oset = p->p_sigmask; error = 0; if (set != NULL) { switch (how) { case SIG_BLOCK: SIG_CANTMASK(*set); SIGSETOR(p->p_sigmask, *set); break; case SIG_UNBLOCK: SIGSETNAND(p->p_sigmask, *set); break; case SIG_SETMASK: SIG_CANTMASK(*set); if (old) SIGSETLO(p->p_sigmask, *set); else p->p_sigmask = *set; break; default: error = EINVAL; break; } } return (error); } /* * sigprocmask() - MP SAFE */ #ifndef _SYS_SYSPROTO_H_ struct sigprocmask_args { int how; const sigset_t *set; sigset_t *oset; }; #endif int sigprocmask(p, uap) register struct proc *p; struct sigprocmask_args *uap; { sigset_t set, oset; sigset_t *setp, *osetp; int error; setp = (uap->set != NULL) ? &set : NULL; osetp = (uap->oset != NULL) ? &oset : NULL; if (setp) { error = copyin(uap->set, setp, sizeof(set)); if (error) return (error); } error = do_sigprocmask(p, uap->how, setp, osetp, 0); if (osetp && !error) { error = copyout(osetp, uap->oset, sizeof(oset)); } return (error); } #ifdef COMPAT_43 /* XXX - COMPAT_FBSD3 */ /* * osigprocmask() - MP SAFE */ #ifndef _SYS_SYSPROTO_H_ struct osigprocmask_args { int how; osigset_t mask; }; #endif int osigprocmask(p, uap) register struct proc *p; struct osigprocmask_args *uap; { sigset_t set, oset; int error; OSIG2SIG(uap->mask, set); error = do_sigprocmask(p, uap->how, &set, &oset, 1); SIG2OSIG(oset, p->p_retval[0]); return (error); } #endif /* COMPAT_43 */ #ifndef _SYS_SYSPROTO_H_ struct sigpending_args { sigset_t *set; }; #endif /* ARGSUSED */ int sigpending(p, uap) struct proc *p; struct sigpending_args *uap; { return (copyout(&p->p_siglist, uap->set, sizeof(sigset_t))); } #ifdef COMPAT_43 /* XXX - COMPAT_FBSD3 */ #ifndef _SYS_SYSPROTO_H_ struct osigpending_args { int dummy; }; #endif /* ARGSUSED */ int osigpending(p, uap) struct proc *p; struct osigpending_args *uap; { SIG2OSIG(p->p_siglist, p->p_retval[0]); return (0); } #endif /* COMPAT_43 */ #if defined(COMPAT_43) || defined(COMPAT_SUNOS) /* * Generalized interface signal handler, 4.3-compatible. */ #ifndef _SYS_SYSPROTO_H_ struct osigvec_args { int signum; struct sigvec *nsv; struct sigvec *osv; }; #endif /* ARGSUSED */ int osigvec(p, uap) struct proc *p; register struct osigvec_args *uap; { struct sigvec vec; struct sigaction nsa, osa; register struct sigaction *nsap, *osap; int error; if (uap->signum <= 0 || uap->signum >= ONSIG) return (EINVAL); nsap = (uap->nsv != NULL) ? &nsa : NULL; osap = (uap->osv != NULL) ? &osa : NULL; if (nsap) { error = copyin(uap->nsv, &vec, sizeof(vec)); if (error) return (error); nsap->sa_handler = vec.sv_handler; OSIG2SIG(vec.sv_mask, nsap->sa_mask); nsap->sa_flags = vec.sv_flags; nsap->sa_flags ^= SA_RESTART; /* opposite of SV_INTERRUPT */ #ifdef COMPAT_SUNOS nsap->sa_flags |= SA_USERTRAMP; #endif } error = do_sigaction(p, uap->signum, nsap, osap, 1); if (osap && !error) { vec.sv_handler = osap->sa_handler; SIG2OSIG(osap->sa_mask, vec.sv_mask); vec.sv_flags = osap->sa_flags; vec.sv_flags &= ~SA_NOCLDWAIT; vec.sv_flags ^= SA_RESTART; #ifdef COMPAT_SUNOS vec.sv_flags &= ~SA_NOCLDSTOP; #endif error = copyout(&vec, uap->osv, sizeof(vec)); } return (error); } #ifndef _SYS_SYSPROTO_H_ struct osigblock_args { int mask; }; #endif int osigblock(p, uap) register struct proc *p; struct osigblock_args *uap; { sigset_t set; OSIG2SIG(uap->mask, set); SIG_CANTMASK(set); (void) splhigh(); SIG2OSIG(p->p_sigmask, p->p_retval[0]); SIGSETOR(p->p_sigmask, set); (void) spl0(); return (0); } #ifndef _SYS_SYSPROTO_H_ struct osigsetmask_args { int mask; }; #endif int osigsetmask(p, uap) struct proc *p; struct osigsetmask_args *uap; { sigset_t set; OSIG2SIG(uap->mask, set); SIG_CANTMASK(set); (void) splhigh(); SIG2OSIG(p->p_sigmask, p->p_retval[0]); SIGSETLO(p->p_sigmask, set); (void) spl0(); return (0); } #endif /* COMPAT_43 || COMPAT_SUNOS */ /* * Suspend process until signal, providing mask to be set * in the meantime. Note nonstandard calling convention: * libc stub passes mask, not pointer, to save a copyin. */ #ifndef _SYS_SYSPROTO_H_ struct sigsuspend_args { const sigset_t *sigmask; }; #endif /* ARGSUSED */ int sigsuspend(p, uap) register struct proc *p; struct sigsuspend_args *uap; { sigset_t mask; register struct sigacts *ps = p->p_sigacts; int error; error = copyin(uap->sigmask, &mask, sizeof(mask)); if (error) return (error); /* * When returning from sigsuspend, we want * the old mask to be restored after the * signal handler has finished. Thus, we * save it here and mark the sigacts structure * to indicate this. */ p->p_oldsigmask = p->p_sigmask; p->p_flag |= P_OLDMASK; SIG_CANTMASK(mask); p->p_sigmask = mask; while (tsleep((caddr_t) ps, PPAUSE|PCATCH, "pause", 0) == 0) /* void */; /* always return EINTR rather than ERESTART... */ return (EINTR); } #ifdef COMPAT_43 /* XXX - COMPAT_FBSD3 */ #ifndef _SYS_SYSPROTO_H_ struct osigsuspend_args { osigset_t mask; }; #endif /* ARGSUSED */ int osigsuspend(p, uap) register struct proc *p; struct osigsuspend_args *uap; { sigset_t mask; register struct sigacts *ps = p->p_sigacts; p->p_oldsigmask = p->p_sigmask; p->p_flag |= P_OLDMASK; OSIG2SIG(uap->mask, mask); SIG_CANTMASK(mask); SIGSETLO(p->p_sigmask, mask); while (tsleep((caddr_t) ps, PPAUSE|PCATCH, "opause", 0) == 0) /* void */; /* always return EINTR rather than ERESTART... */ return (EINTR); } #endif /* COMPAT_43 */ #if defined(COMPAT_43) || defined(COMPAT_SUNOS) #ifndef _SYS_SYSPROTO_H_ struct osigstack_args { struct sigstack *nss; struct sigstack *oss; }; #endif /* ARGSUSED */ int osigstack(p, uap) struct proc *p; register struct osigstack_args *uap; { struct sigstack ss; int error = 0; ss.ss_sp = p->p_sigstk.ss_sp; ss.ss_onstack = p->p_sigstk.ss_flags & SS_ONSTACK; if (uap->oss && (error = copyout(&ss, uap->oss, sizeof(struct sigstack)))) return (error); if (uap->nss && (error = copyin(uap->nss, &ss, sizeof(ss))) == 0) { p->p_sigstk.ss_sp = ss.ss_sp; p->p_sigstk.ss_size = 0; p->p_sigstk.ss_flags |= ss.ss_onstack & SS_ONSTACK; p->p_flag |= P_ALTSTACK; } return (error); } #endif /* COMPAT_43 || COMPAT_SUNOS */ #ifndef _SYS_SYSPROTO_H_ struct sigaltstack_args { stack_t *ss; stack_t *oss; }; #endif /* ARGSUSED */ int sigaltstack(p, uap) struct proc *p; register struct sigaltstack_args *uap; { stack_t ss; int error; if ((p->p_flag & P_ALTSTACK) == 0) p->p_sigstk.ss_flags |= SS_DISABLE; if (uap->oss && (error = copyout(&p->p_sigstk, uap->oss, sizeof(stack_t)))) return (error); if (uap->ss == 0) return (0); if ((error = copyin(uap->ss, &ss, sizeof(ss)))) return (error); if (ss.ss_flags & SS_DISABLE) { if (p->p_sigstk.ss_flags & SS_ONSTACK) return (EINVAL); p->p_flag &= ~P_ALTSTACK; p->p_sigstk.ss_flags = ss.ss_flags; return (0); } - if (ss.ss_size < MINSIGSTKSZ) + if (ss.ss_size < p->p_sysent->sv_minsigstksz) return (ENOMEM); p->p_flag |= P_ALTSTACK; p->p_sigstk = ss; return (0); } /* * Common code for kill process group/broadcast kill. * cp is calling process. */ int killpg1(cp, sig, pgid, all) register struct proc *cp; int sig, pgid, all; { register struct proc *p; struct pgrp *pgrp; int nfound = 0; if (all) /* * broadcast */ LIST_FOREACH(p, &allproc, p_list) { if (p->p_pid <= 1 || p->p_flag & P_SYSTEM || p == cp || !CANSIGNAL(cp, p, sig)) continue; nfound++; if (sig) psignal(p, sig); } else { if (pgid == 0) /* * zero pgid means send to my process group. */ pgrp = cp->p_pgrp; else { pgrp = pgfind(pgid); if (pgrp == NULL) return (ESRCH); } LIST_FOREACH(p, &pgrp->pg_members, p_pglist) { if (p->p_pid <= 1 || p->p_flag & P_SYSTEM || p->p_stat == SZOMB || !CANSIGNAL(cp, p, sig)) continue; nfound++; if (sig) psignal(p, sig); } } return (nfound ? 0 : ESRCH); } #ifndef _SYS_SYSPROTO_H_ struct kill_args { int pid; int signum; }; #endif /* ARGSUSED */ int kill(cp, uap) register struct proc *cp; register struct kill_args *uap; { register struct proc *p; if ((u_int)uap->signum > _SIG_MAXSIG) return (EINVAL); if (uap->pid > 0) { /* kill single process */ if ((p = pfind(uap->pid)) == NULL) return (ESRCH); if (!CANSIGNAL(cp, p, uap->signum)) return (EPERM); if (uap->signum) psignal(p, uap->signum); return (0); } switch (uap->pid) { case -1: /* broadcast signal */ return (killpg1(cp, uap->signum, 0, 1)); case 0: /* signal own process group */ return (killpg1(cp, uap->signum, 0, 0)); default: /* negative explicit process group */ return (killpg1(cp, uap->signum, -uap->pid, 0)); } /* NOTREACHED */ } #if defined(COMPAT_43) || defined(COMPAT_SUNOS) #ifndef _SYS_SYSPROTO_H_ struct okillpg_args { int pgid; int signum; }; #endif /* ARGSUSED */ int okillpg(p, uap) struct proc *p; register struct okillpg_args *uap; { if ((u_int)uap->signum > _SIG_MAXSIG) return (EINVAL); return (killpg1(p, uap->signum, uap->pgid, 0)); } #endif /* COMPAT_43 || COMPAT_SUNOS */ /* * Send a signal to a process group. */ void gsignal(pgid, sig) int pgid, sig; { struct pgrp *pgrp; if (pgid && (pgrp = pgfind(pgid))) pgsignal(pgrp, sig, 0); } /* * Send a signal to a process group. If checktty is 1, * limit to members which have a controlling terminal. */ void pgsignal(pgrp, sig, checkctty) struct pgrp *pgrp; int sig, checkctty; { register struct proc *p; if (pgrp) LIST_FOREACH(p, &pgrp->pg_members, p_pglist) if (checkctty == 0 || p->p_flag & P_CONTROLT) psignal(p, sig); } /* * Send a signal caused by a trap to the current process. * If it will be caught immediately, deliver it with correct code. * Otherwise, post it normally. */ void trapsignal(p, sig, code) struct proc *p; register int sig; u_long code; { register struct sigacts *ps = p->p_sigacts; if ((p->p_flag & P_TRACED) == 0 && SIGISMEMBER(p->p_sigcatch, sig) && SIGISMEMBER(p->p_sigmask, sig)) { p->p_stats->p_ru.ru_nsignals++; #ifdef KTRACE if (KTRPOINT(p, KTR_PSIG)) ktrpsig(p->p_tracep, sig, ps->ps_sigact[_SIG_IDX(sig)], &p->p_sigmask, code); #endif (*p->p_sysent->sv_sendsig)(ps->ps_sigact[_SIG_IDX(sig)], sig, &p->p_sigmask, code); SIGSETOR(p->p_sigmask, ps->ps_catchmask[_SIG_IDX(sig)]); if (!SIGISMEMBER(ps->ps_signodefer, sig)) SIGADDSET(p->p_sigmask, sig); if (SIGISMEMBER(ps->ps_sigreset, sig)) { /* * See do_sigaction() for origin of this code. */ SIGDELSET(p->p_sigcatch, sig); if (sig != SIGCONT && sigprop(sig) & SA_IGNORE) SIGADDSET(p->p_sigignore, sig); ps->ps_sigact[_SIG_IDX(sig)] = SIG_DFL; } } else { p->p_code = code; /* XXX for core dump/debugger */ p->p_sig = sig; /* XXX to verify code */ psignal(p, sig); } } /* * Send the signal to the process. If the signal has an action, the action * is usually performed by the target process rather than the caller; we add * the signal to the set of pending signals for the process. * * Exceptions: * o When a stop signal is sent to a sleeping process that takes the * default action, the process is stopped without awakening it. * o SIGCONT restarts stopped processes (or puts them back to sleep) * regardless of the signal action (eg, blocked or ignored). * * Other ignored signals are discarded immediately. */ void psignal(p, sig) register struct proc *p; register int sig; { register int s, prop; register sig_t action; if (sig > _SIG_MAXSIG || sig <= 0) { printf("psignal: signal %d\n", sig); panic("psignal signal number"); } KNOTE(&p->p_klist, NOTE_SIGNAL | sig); prop = sigprop(sig); /* * If proc is traced, always give parent a chance; * if signal event is tracked by procfs, give *that* * a chance, as well. */ if ((p->p_flag & P_TRACED) || (p->p_stops & S_SIG)) action = SIG_DFL; else { /* * If the signal is being ignored, * then we forget about it immediately. * (Note: we don't set SIGCONT in p_sigignore, * and if it is set to SIG_IGN, * action will be SIG_DFL here.) */ if (SIGISMEMBER(p->p_sigignore, sig) || (p->p_flag & P_WEXIT)) return; if (SIGISMEMBER(p->p_sigmask, sig)) action = SIG_HOLD; else if (SIGISMEMBER(p->p_sigcatch, sig)) action = SIG_CATCH; else action = SIG_DFL; } if (p->p_nice > NZERO && action == SIG_DFL && (prop & SA_KILL) && (p->p_flag & P_TRACED) == 0) p->p_nice = NZERO; if (prop & SA_CONT) SIG_STOPSIGMASK(p->p_siglist); if (prop & SA_STOP) { /* * If sending a tty stop signal to a member of an orphaned * process group, discard the signal here if the action * is default; don't stop the process below if sleeping, * and don't clear any pending SIGCONT. */ if (prop & SA_TTYSTOP && p->p_pgrp->pg_jobc == 0 && action == SIG_DFL) return; SIG_CONTSIGMASK(p->p_siglist); } SIGADDSET(p->p_siglist, sig); /* * Defer further processing for signals which are held, * except that stopped processes must be continued by SIGCONT. */ if (action == SIG_HOLD && (!(prop & SA_CONT) || p->p_stat != SSTOP)) return; s = splhigh(); switch (p->p_stat) { case SSLEEP: /* * If process is sleeping uninterruptibly * we can't interrupt the sleep... the signal will * be noticed when the process returns through * trap() or syscall(). */ if ((p->p_flag & P_SINTR) == 0) goto out; /* * Process is sleeping and traced... make it runnable * so it can discover the signal in issignal() and stop * for the parent. */ if (p->p_flag & P_TRACED) goto run; /* * If SIGCONT is default (or ignored) and process is * asleep, we are finished; the process should not * be awakened. */ if ((prop & SA_CONT) && action == SIG_DFL) { SIGDELSET(p->p_siglist, sig); goto out; } /* * When a sleeping process receives a stop * signal, process immediately if possible. * All other (caught or default) signals * cause the process to run. */ if (prop & SA_STOP) { if (action != SIG_DFL) goto runfast; /* * If a child holding parent blocked, * stopping could cause deadlock. */ if (p->p_flag & P_PPWAIT) goto out; SIGDELSET(p->p_siglist, sig); p->p_xstat = sig; if ((p->p_pptr->p_procsig->ps_flag & PS_NOCLDSTOP) == 0) psignal(p->p_pptr, SIGCHLD); stop(p); goto out; } else goto runfast; /*NOTREACHED*/ case SSTOP: /* * If traced process is already stopped, * then no further action is necessary. */ if (p->p_flag & P_TRACED) goto out; /* * Kill signal always sets processes running. */ if (sig == SIGKILL) goto runfast; if (prop & SA_CONT) { /* * If SIGCONT is default (or ignored), we continue the * process but don't leave the signal in p_siglist, as * it has no further action. If SIGCONT is held, we * continue the process and leave the signal in * p_siglist. If the process catches SIGCONT, let it * handle the signal itself. If it isn't waiting on * an event, then it goes back to run state. * Otherwise, process goes back to sleep state. */ if (action == SIG_DFL) SIGDELSET(p->p_siglist, sig); if (action == SIG_CATCH) goto runfast; if (p->p_wchan == 0) goto run; p->p_stat = SSLEEP; goto out; } if (prop & SA_STOP) { /* * Already stopped, don't need to stop again. * (If we did the shell could get confused.) */ SIGDELSET(p->p_siglist, sig); goto out; } /* * If process is sleeping interruptibly, then simulate a * wakeup so that when it is continued, it will be made * runnable and can look at the signal. But don't make * the process runnable, leave it stopped. */ if (p->p_wchan && p->p_flag & P_SINTR) unsleep(p); goto out; default: /* * SRUN, SIDL, SZOMB do nothing with the signal, * other than kicking ourselves if we are running. * It will either never be noticed, or noticed very soon. */ if (p == curproc) signotify(p); #ifdef SMP else if (p->p_stat == SRUN) forward_signal(p); #endif goto out; } /*NOTREACHED*/ runfast: /* * Raise priority to at least PUSER. */ if (p->p_priority > PUSER) p->p_priority = PUSER; run: setrunnable(p); out: splx(s); } /* * If the current process has received a signal (should be caught or cause * termination, should interrupt current syscall), return the signal number. * Stop signals with default action are processed immediately, then cleared; * they aren't returned. This is checked after each entry to the system for * a syscall or trap (though this can usually be done without calling issignal * by checking the pending signal masks in the CURSIG macro.) The normal call * sequence is * * while (sig = CURSIG(curproc)) * postsig(sig); */ int issignal(p) register struct proc *p; { sigset_t mask; register int sig, prop; for (;;) { int traced = (p->p_flag & P_TRACED) || (p->p_stops & S_SIG); mask = p->p_siglist; SIGSETNAND(mask, p->p_sigmask); if (p->p_flag & P_PPWAIT) SIG_STOPSIGMASK(mask); if (!SIGNOTEMPTY(mask)) /* no signal to send */ return (0); sig = sig_ffs(&mask); prop = sigprop(sig); STOPEVENT(p, S_SIG, sig); /* * We should see pending but ignored signals * only if P_TRACED was on when they were posted. */ if (SIGISMEMBER(p->p_sigignore, sig) && (traced == 0)) { SIGDELSET(p->p_siglist, sig); continue; } if (p->p_flag & P_TRACED && (p->p_flag & P_PPWAIT) == 0) { /* * If traced, always stop, and stay * stopped until released by the parent. */ p->p_xstat = sig; psignal(p->p_pptr, SIGCHLD); do { stop(p); mi_switch(); } while (!trace_req(p) && p->p_flag & P_TRACED); /* * If the traced bit got turned off, go back up * to the top to rescan signals. This ensures * that p_sig* and ps_sigact are consistent. */ if ((p->p_flag & P_TRACED) == 0) continue; /* * If parent wants us to take the signal, * then it will leave it in p->p_xstat; * otherwise we just look for signals again. */ SIGDELSET(p->p_siglist, sig); /* clear old signal */ sig = p->p_xstat; if (sig == 0) continue; /* * Put the new signal into p_siglist. If the * signal is being masked, look for other signals. */ SIGADDSET(p->p_siglist, sig); if (SIGISMEMBER(p->p_sigmask, sig)) continue; } /* * Decide whether the signal should be returned. * Return the signal's number, or fall through * to clear it from the pending mask. */ switch ((int)(intptr_t)p->p_sigacts->ps_sigact[_SIG_IDX(sig)]) { case (int)SIG_DFL: /* * Don't take default actions on system processes. */ if (p->p_pid <= 1) { #ifdef DIAGNOSTIC /* * Are you sure you want to ignore SIGSEGV * in init? XXX */ printf("Process (pid %lu) got signal %d\n", (u_long)p->p_pid, sig); #endif break; /* == ignore */ } /* * If there is a pending stop signal to process * with default action, stop here, * then clear the signal. However, * if process is member of an orphaned * process group, ignore tty stop signals. */ if (prop & SA_STOP) { if (p->p_flag & P_TRACED || (p->p_pgrp->pg_jobc == 0 && prop & SA_TTYSTOP)) break; /* == ignore */ p->p_xstat = sig; stop(p); if ((p->p_pptr->p_procsig->ps_flag & PS_NOCLDSTOP) == 0) psignal(p->p_pptr, SIGCHLD); mi_switch(); break; } else if (prop & SA_IGNORE) { /* * Except for SIGCONT, shouldn't get here. * Default action is to ignore; drop it. */ break; /* == ignore */ } else return (sig); /*NOTREACHED*/ case (int)SIG_IGN: /* * Masking above should prevent us ever trying * to take action on an ignored signal other * than SIGCONT, unless process is traced. */ if ((prop & SA_CONT) == 0 && (p->p_flag & P_TRACED) == 0) printf("issignal\n"); break; /* == ignore */ default: /* * This signal has an action, let * postsig() process it. */ return (sig); } SIGDELSET(p->p_siglist, sig); /* take the signal! */ } /* NOTREACHED */ } /* * Put the argument process into the stopped state and notify the parent * via wakeup. Signals are handled elsewhere. The process must not be * on the run queue. */ void stop(p) register struct proc *p; { p->p_stat = SSTOP; p->p_flag &= ~P_WAITED; wakeup((caddr_t)p->p_pptr); } /* * Take the action for the specified signal * from the current set of pending signals. */ void postsig(sig) register int sig; { register struct proc *p = curproc; struct sigacts *ps = p->p_sigacts; sig_t action; sigset_t returnmask; int code; KASSERT(sig != 0, ("postsig")); SIGDELSET(p->p_siglist, sig); action = ps->ps_sigact[_SIG_IDX(sig)]; #ifdef KTRACE if (KTRPOINT(p, KTR_PSIG)) ktrpsig(p->p_tracep, sig, action, p->p_flag & P_OLDMASK ? &p->p_oldsigmask : &p->p_sigmask, 0); #endif STOPEVENT(p, S_SIG, sig); if (action == SIG_DFL) { /* * Default action, where the default is to kill * the process. (Other cases were ignored above.) */ sigexit(p, sig); /* NOTREACHED */ } else { /* * If we get here, the signal must be caught. */ KASSERT(action != SIG_IGN && !SIGISMEMBER(p->p_sigmask, sig), ("postsig action")); /* * Set the new mask value and also defer further * occurrences of this signal. * * Special case: user has done a sigsuspend. Here the * current mask is not of interest, but rather the * mask from before the sigsuspend is what we want * restored after the signal processing is completed. */ (void) splhigh(); if (p->p_flag & P_OLDMASK) { returnmask = p->p_oldsigmask; p->p_flag &= ~P_OLDMASK; } else returnmask = p->p_sigmask; SIGSETOR(p->p_sigmask, ps->ps_catchmask[_SIG_IDX(sig)]); if (!SIGISMEMBER(ps->ps_signodefer, sig)) SIGADDSET(p->p_sigmask, sig); if (SIGISMEMBER(ps->ps_sigreset, sig)) { /* * See do_sigaction() for origin of this code. */ SIGDELSET(p->p_sigcatch, sig); if (sig != SIGCONT && sigprop(sig) & SA_IGNORE) SIGADDSET(p->p_sigignore, sig); ps->ps_sigact[_SIG_IDX(sig)] = SIG_DFL; } (void) spl0(); p->p_stats->p_ru.ru_nsignals++; if (p->p_sig != sig) { code = 0; } else { code = p->p_code; p->p_code = 0; p->p_sig = 0; } (*p->p_sysent->sv_sendsig)(action, sig, &returnmask, code); } } /* * Kill the current process for stated reason. */ void killproc(p, why) struct proc *p; char *why; { CTR3(KTR_PROC, "killproc: proc %p (pid %d, %s)", p, p->p_pid, p->p_comm); log(LOG_ERR, "pid %d (%s), uid %d, was killed: %s\n", p->p_pid, p->p_comm, p->p_cred && p->p_ucred ? p->p_ucred->cr_uid : -1, why); psignal(p, SIGKILL); } /* * Force the current process to exit with the specified signal, dumping core * if appropriate. We bypass the normal tests for masked and caught signals, * allowing unrecoverable failures to terminate the process without changing * signal state. Mark the accounting record with the signal termination. * If dumping core, save the signal number for the debugger. Calls exit and * does not return. */ void sigexit(p, sig) register struct proc *p; int sig; { p->p_acflag |= AXSIG; if (sigprop(sig) & SA_CORE) { p->p_sig = sig; /* * Log signals which would cause core dumps * (Log as LOG_INFO to appease those who don't want * these messages.) * XXX : Todo, as well as euid, write out ruid too */ if (coredump(p) == 0) sig |= WCOREFLAG; if (kern_logsigexit) log(LOG_INFO, "pid %d (%s), uid %d: exited on signal %d%s\n", p->p_pid, p->p_comm, p->p_cred && p->p_ucred ? p->p_ucred->cr_uid : -1, sig &~ WCOREFLAG, sig & WCOREFLAG ? " (core dumped)" : ""); } exit1(p, W_EXITCODE(0, sig)); /* NOTREACHED */ } static char corefilename[MAXPATHLEN+1] = {"%N.core"}; SYSCTL_STRING(_kern, OID_AUTO, corefile, CTLFLAG_RW, corefilename, sizeof(corefilename), "process corefile name format string"); /* * expand_name(name, uid, pid) * Expand the name described in corefilename, using name, uid, and pid. * corefilename is a printf-like string, with three format specifiers: * %N name of process ("name") * %P process id (pid) * %U user id (uid) * For example, "%N.core" is the default; they can be disabled completely * by using "/dev/null", or all core files can be stored in "/cores/%U/%N-%P". * This is controlled by the sysctl variable kern.corefile (see above). */ static char * expand_name(name, uid, pid) const char *name; uid_t uid; pid_t pid; { char *temp; char buf[11]; /* Buffer for pid/uid -- max 4B */ int i, n; char *format = corefilename; size_t namelen; temp = malloc(MAXPATHLEN + 1, M_TEMP, M_NOWAIT); if (temp == NULL) return NULL; namelen = strlen(name); for (i = 0, n = 0; n < MAXPATHLEN && format[i]; i++) { int l; switch (format[i]) { case '%': /* Format character */ i++; switch (format[i]) { case '%': temp[n++] = '%'; break; case 'N': /* process name */ if ((n + namelen) > MAXPATHLEN) { log(LOG_ERR, "pid %d (%s), uid (%u): Path `%s%s' is too long\n", pid, name, uid, temp, name); free(temp, M_TEMP); return NULL; } memcpy(temp+n, name, namelen); n += namelen; break; case 'P': /* process id */ l = sprintf(buf, "%u", pid); if ((n + l) > MAXPATHLEN) { log(LOG_ERR, "pid %d (%s), uid (%u): Path `%s%s' is too long\n", pid, name, uid, temp, name); free(temp, M_TEMP); return NULL; } memcpy(temp+n, buf, l); n += l; break; case 'U': /* user id */ l = sprintf(buf, "%u", uid); if ((n + l) > MAXPATHLEN) { log(LOG_ERR, "pid %d (%s), uid (%u): Path `%s%s' is too long\n", pid, name, uid, temp, name); free(temp, M_TEMP); return NULL; } memcpy(temp+n, buf, l); n += l; break; default: log(LOG_ERR, "Unknown format character %c in `%s'\n", format[i], format); } break; default: temp[n++] = format[i]; } } temp[n] = '\0'; return temp; } /* * Dump a process' core. The main routine does some * policy checking, and creates the name of the coredump; * then it passes on a vnode and a size limit to the process-specific * coredump routine if there is one; if there _is not_ one, it returns * ENOSYS; otherwise it returns the error from the process-specific routine. */ static int coredump(p) register struct proc *p; { register struct vnode *vp; register struct ucred *cred = p->p_ucred; struct nameidata nd; struct vattr vattr; int error, error1, flags; struct mount *mp; char *name; /* name of corefile */ off_t limit; STOPEVENT(p, S_CORE, 0); if (((sugid_coredump == 0) && p->p_flag & P_SUGID) || do_coredump == 0) return (EFAULT); /* * Note that the bulk of limit checking is done after * the corefile is created. The exception is if the limit * for corefiles is 0, in which case we don't bother * creating the corefile at all. This layout means that * a corefile is truncated instead of not being created, * if it is larger than the limit. */ limit = p->p_rlimit[RLIMIT_CORE].rlim_cur; if (limit == 0) return 0; restart: name = expand_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid); NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, p); flags = O_CREAT | FWRITE | O_NOFOLLOW; error = vn_open(&nd, &flags, S_IRUSR | S_IWUSR); free(name, M_TEMP); if (error) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); vp = nd.ni_vp; if (vn_start_write(vp, &mp, V_NOWAIT) != 0) { VOP_UNLOCK(vp, 0, p); if ((error = vn_close(vp, FWRITE, cred, p)) != 0) return (error); if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) return (error); goto restart; } /* Don't dump to non-regular files or files with links. */ if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred, p) || vattr.va_nlink != 1) { error = EFAULT; goto out; } VATTR_NULL(&vattr); vattr.va_size = 0; VOP_LEASE(vp, p, cred, LEASE_WRITE); VOP_SETATTR(vp, &vattr, cred, p); p->p_acflag |= ACORE; error = p->p_sysent->sv_coredump ? p->p_sysent->sv_coredump(p, vp, limit) : ENOSYS; out: VOP_UNLOCK(vp, 0, p); vn_finished_write(mp); error1 = vn_close(vp, FWRITE, cred, p); if (error == 0) error = error1; return (error); } /* * Nonexistent system call-- signal process (may want to handle it). * Flag error in case process won't see signal immediately (blocked or ignored). */ #ifndef _SYS_SYSPROTO_H_ struct nosys_args { int dummy; }; #endif /* ARGSUSED */ int nosys(p, args) struct proc *p; struct nosys_args *args; { psignal(p, SIGSYS); return (EINVAL); } /* * Send a signal to a SIGIO or SIGURG to a process or process group using * stored credentials rather than those of the current process. */ void pgsigio(sigio, sig, checkctty) struct sigio *sigio; int sig, checkctty; { if (sigio == NULL) return; if (sigio->sio_pgid > 0) { if (CANSIGIO(sigio->sio_ruid, sigio->sio_ucred, sigio->sio_proc)) psignal(sigio->sio_proc, sig); } else if (sigio->sio_pgid < 0) { struct proc *p; LIST_FOREACH(p, &sigio->sio_pgrp->pg_members, p_pglist) if (CANSIGIO(sigio->sio_ruid, sigio->sio_ucred, p) && (checkctty == 0 || (p->p_flag & P_CONTROLT))) psignal(p, sig); } } static int filt_sigattach(struct knote *kn) { struct proc *p = curproc; kn->kn_ptr.p_proc = p; kn->kn_flags |= EV_CLEAR; /* automatically set */ /* XXX lock the proc here while adding to the list? */ SLIST_INSERT_HEAD(&p->p_klist, kn, kn_selnext); return (0); } static void filt_sigdetach(struct knote *kn) { struct proc *p = kn->kn_ptr.p_proc; SLIST_REMOVE(&p->p_klist, kn, knote, kn_selnext); } /* * signal knotes are shared with proc knotes, so we apply a mask to * the hint in order to differentiate them from process hints. This * could be avoided by using a signal-specific knote list, but probably * isn't worth the trouble. */ static int filt_signal(struct knote *kn, long hint) { if (hint & NOTE_SIGNAL) { hint &= ~NOTE_SIGNAL; if (kn->kn_id == hint) kn->kn_data++; } return (kn->kn_data != 0); } Index: head/sys/sys/_sigset.h =================================================================== --- head/sys/sys/_sigset.h (revision 68519) +++ head/sys/sys/_sigset.h (revision 68520) @@ -1,300 +1,299 @@ /* * Copyright (c) 1982, 1986, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)signal.h 8.4 (Berkeley) 5/4/95 * $FreeBSD$ */ #ifndef _SYS_SIGNAL_H_ #define _SYS_SIGNAL_H_ #include #include /* * sigset_t macros. */ #define _SIG_WORDS 4 #define _SIG_MAXSIG 128 #define _SIG_IDX(sig) ((sig) - 1) #define _SIG_WORD(sig) (_SIG_IDX(sig) >> 5) #define _SIG_BIT(sig) (1 << (_SIG_IDX(sig) & 31)) /* * System defined signals. */ #define SIGHUP 1 /* hangup */ #define SIGINT 2 /* interrupt */ #define SIGQUIT 3 /* quit */ #define SIGILL 4 /* illegal instr. (not reset when caught) */ #ifndef _POSIX_SOURCE #define SIGTRAP 5 /* trace trap (not reset when caught) */ #endif #define SIGABRT 6 /* abort() */ #ifndef _POSIX_SOURCE #define SIGIOT SIGABRT /* compatibility */ #define SIGEMT 7 /* EMT instruction */ #endif #define SIGFPE 8 /* floating point exception */ #define SIGKILL 9 /* kill (cannot be caught or ignored) */ #ifndef _POSIX_SOURCE #define SIGBUS 10 /* bus error */ #endif #define SIGSEGV 11 /* segmentation violation */ #ifndef _POSIX_SOURCE #define SIGSYS 12 /* non-existent system call invoked */ #endif #define SIGPIPE 13 /* write on a pipe with no one to read it */ #define SIGALRM 14 /* alarm clock */ #define SIGTERM 15 /* software termination signal from kill */ #ifndef _POSIX_SOURCE #define SIGURG 16 /* urgent condition on IO channel */ #endif #define SIGSTOP 17 /* sendable stop signal not from tty */ #define SIGTSTP 18 /* stop signal from tty */ #define SIGCONT 19 /* continue a stopped process */ #define SIGCHLD 20 /* to parent on child stop or exit */ #define SIGTTIN 21 /* to readers pgrp upon background tty read */ #define SIGTTOU 22 /* like TTIN if (tp->t_local<OSTOP) */ #ifndef _POSIX_SOURCE #define SIGIO 23 /* input/output possible signal */ #define SIGXCPU 24 /* exceeded CPU time limit */ #define SIGXFSZ 25 /* exceeded file size limit */ #define SIGVTALRM 26 /* virtual time alarm */ #define SIGPROF 27 /* profiling time alarm */ #define SIGWINCH 28 /* window size changes */ #define SIGINFO 29 /* information request */ #endif #define SIGUSR1 30 /* user defined signal 1 */ #define SIGUSR2 31 /* user defined signal 2 */ /*- * Type of a signal handling function. * * Language spec sez signal handlers take exactly one arg, even though we * actually supply three. Ugh! * * We don't try to hide the difference by leaving out the args because * that would cause warnings about conformant programs. Nonconformant * programs can avoid the warnings by casting to (__sighandler_t *) or * sig_t before calling signal() or assigning to sa_handler or sv_handler. * * The kernel should reverse the cast before calling the function. It * has no way to do this, but on most machines 1-arg and 3-arg functions * have the same calling protocol so there is no problem in practice. * A bit in sa_flags could be used to specify the number of args. */ typedef void __sighandler_t __P((int)); #define SIG_DFL ((__sighandler_t *)0) #define SIG_IGN ((__sighandler_t *)1) #define SIG_ERR ((__sighandler_t *)-1) #if defined(_P1003_1B_VISIBLE) || defined(_KERNEL) union sigval { /* Members as suggested by Annex C of POSIX 1003.1b. */ int sigval_int; void *sigval_ptr; }; struct sigevent { int sigev_notify; /* Notification type */ int sigev_signo; /* Signal number */ union sigval sigev_value; /* Signal value */ }; #define SIGEV_NONE 0 /* No async notification */ #define SIGEV_SIGNAL 1 /* Generate a queued signal */ typedef struct __siginfo { int si_signo; /* signal number */ int si_errno; /* errno association */ /* * Cause of signal, one of the SI_ macros or signal-specific * values, i.e. one of the FPE_... values for SIGFPE. This * value is equivalent to the second argument to an old-style * FreeBSD signal handler. */ int si_code; /* signal code */ int si_pid; /* sending process */ unsigned int si_uid; /* sender's ruid */ int si_status; /* exit value */ void *si_addr; /* faulting instruction */ union sigval si_value; /* signal value */ long si_band; /* band event for SIGPOLL */ int __spare__[7]; /* gimme some slack */ } siginfo_t; #endif /* _P1003_1B_VISIBLE */ typedef struct __sigset { unsigned int __bits[_SIG_WORDS]; } sigset_t; /* * XXX - there are some nasty dependencies on include file order. Now that * sigset_t has been defined we can include the MD header. */ #include /* sig_atomic_t; trap codes; sigcontext */ #if !defined(_ANSI_SOURCE) struct __siginfo; /* * Signal vector "template" used in sigaction call. */ struct sigaction { union { void (*__sa_handler) __P((int)); void (*__sa_sigaction) __P((int, struct __siginfo *, void *)); } __sigaction_u; /* signal handler */ int sa_flags; /* see signal options below */ sigset_t sa_mask; /* signal mask to apply */ }; /* if SA_SIGINFO is set, sa_sigaction is to be used instead of sa_handler. */ #define sa_handler __sigaction_u.__sa_handler #define SA_NOCLDSTOP 0x0008 /* do not generate SIGCHLD on child stop */ #if !defined(_POSIX_SOURCE) #define sa_sigaction __sigaction_u.__sa_sigaction #define SA_ONSTACK 0x0001 /* take signal on signal stack */ #define SA_RESTART 0x0002 /* restart system call on signal return */ #define SA_RESETHAND 0x0004 /* reset to SIG_DFL when taking signal */ #define SA_NODEFER 0x0010 /* don't mask the signal we're delivering */ #define SA_NOCLDWAIT 0x0020 /* don't keep zombies around */ #define SA_SIGINFO 0x0040 /* signal handler with SA_SIGINFO args */ #ifdef COMPAT_SUNOS #define SA_USERTRAMP 0x0100 /* do not bounce off kernel's sigtramp */ #endif #define NSIG 32 /* number of old signals (counting 0) */ /* POSIX 1003.1b required values. */ #define SI_USER 0x10001 #define SI_QUEUE 0x10002 #define SI_TIMER 0x10003 #define SI_ASYNCIO 0x10004 #define SI_MESGQ 0x10005 /* Additional FreeBSD values. */ #define SI_UNDEFINED 0 typedef void __siginfohandler_t __P((int, struct __siginfo *, void *)); typedef __sighandler_t *sig_t; /* type of pointer to a signal function */ #ifdef _BSD_SIZE_T_ typedef _BSD_SIZE_T_ size_t; #undef _BSD_SIZE_T_ #endif /* * Structure used in sigaltstack call. */ typedef struct sigaltstack { char *ss_sp; /* signal stack base */ size_t ss_size; /* signal stack length */ int ss_flags; /* SS_DISABLE and/or SS_ONSTACK */ } stack_t; #define SS_ONSTACK 0x0001 /* take signal on alternate stack */ #define SS_DISABLE 0x0004 /* disable taking signals on alternate stack */ -#define MINSIGSTKSZ 8192 /* minimum allowable stack */ #define SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended stack size */ /* Have enough typedefs for this now. XXX */ #include /* * 4.3 compatibility: * Signal vector "template" used in sigvec call. */ struct sigvec { __sighandler_t *sv_handler; /* signal handler */ int sv_mask; /* signal mask to apply */ int sv_flags; /* see signal options below */ }; #define SV_ONSTACK SA_ONSTACK #define SV_INTERRUPT SA_RESTART /* same bit, opposite sense */ #define SV_RESETHAND SA_RESETHAND #define SV_NODEFER SA_NODEFER #define SV_NOCLDSTOP SA_NOCLDSTOP #define SV_SIGINFO SA_SIGINFO #define sv_onstack sv_flags /* isn't compatibility wonderful! */ /* * Structure used in sigstack call. */ struct sigstack { char *ss_sp; /* signal stack pointer */ int ss_onstack; /* current status */ }; /* * Macro for converting signal number to a mask suitable for * sigblock(). */ #define sigmask(m) (1 << ((m)-1)) #define BADSIG SIG_ERR #endif /* !_POSIX_SOURCE */ /* * Flags for sigprocmask: */ #define SIG_BLOCK 1 /* block specified signal set */ #define SIG_UNBLOCK 2 /* unblock specified signal set */ #define SIG_SETMASK 3 /* set specified signal set */ #endif /* !_ANSI_SOURCE */ /* * For historical reasons; programs expect signal's return value to be * defined by . */ __BEGIN_DECLS __sighandler_t *signal __P((int, __sighandler_t *)); __END_DECLS #endif /* !_SYS_SIGNAL_H_ */ Index: head/sys/sys/signal.h =================================================================== --- head/sys/sys/signal.h (revision 68519) +++ head/sys/sys/signal.h (revision 68520) @@ -1,300 +1,299 @@ /* * Copyright (c) 1982, 1986, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)signal.h 8.4 (Berkeley) 5/4/95 * $FreeBSD$ */ #ifndef _SYS_SIGNAL_H_ #define _SYS_SIGNAL_H_ #include #include /* * sigset_t macros. */ #define _SIG_WORDS 4 #define _SIG_MAXSIG 128 #define _SIG_IDX(sig) ((sig) - 1) #define _SIG_WORD(sig) (_SIG_IDX(sig) >> 5) #define _SIG_BIT(sig) (1 << (_SIG_IDX(sig) & 31)) /* * System defined signals. */ #define SIGHUP 1 /* hangup */ #define SIGINT 2 /* interrupt */ #define SIGQUIT 3 /* quit */ #define SIGILL 4 /* illegal instr. (not reset when caught) */ #ifndef _POSIX_SOURCE #define SIGTRAP 5 /* trace trap (not reset when caught) */ #endif #define SIGABRT 6 /* abort() */ #ifndef _POSIX_SOURCE #define SIGIOT SIGABRT /* compatibility */ #define SIGEMT 7 /* EMT instruction */ #endif #define SIGFPE 8 /* floating point exception */ #define SIGKILL 9 /* kill (cannot be caught or ignored) */ #ifndef _POSIX_SOURCE #define SIGBUS 10 /* bus error */ #endif #define SIGSEGV 11 /* segmentation violation */ #ifndef _POSIX_SOURCE #define SIGSYS 12 /* non-existent system call invoked */ #endif #define SIGPIPE 13 /* write on a pipe with no one to read it */ #define SIGALRM 14 /* alarm clock */ #define SIGTERM 15 /* software termination signal from kill */ #ifndef _POSIX_SOURCE #define SIGURG 16 /* urgent condition on IO channel */ #endif #define SIGSTOP 17 /* sendable stop signal not from tty */ #define SIGTSTP 18 /* stop signal from tty */ #define SIGCONT 19 /* continue a stopped process */ #define SIGCHLD 20 /* to parent on child stop or exit */ #define SIGTTIN 21 /* to readers pgrp upon background tty read */ #define SIGTTOU 22 /* like TTIN if (tp->t_local<OSTOP) */ #ifndef _POSIX_SOURCE #define SIGIO 23 /* input/output possible signal */ #define SIGXCPU 24 /* exceeded CPU time limit */ #define SIGXFSZ 25 /* exceeded file size limit */ #define SIGVTALRM 26 /* virtual time alarm */ #define SIGPROF 27 /* profiling time alarm */ #define SIGWINCH 28 /* window size changes */ #define SIGINFO 29 /* information request */ #endif #define SIGUSR1 30 /* user defined signal 1 */ #define SIGUSR2 31 /* user defined signal 2 */ /*- * Type of a signal handling function. * * Language spec sez signal handlers take exactly one arg, even though we * actually supply three. Ugh! * * We don't try to hide the difference by leaving out the args because * that would cause warnings about conformant programs. Nonconformant * programs can avoid the warnings by casting to (__sighandler_t *) or * sig_t before calling signal() or assigning to sa_handler or sv_handler. * * The kernel should reverse the cast before calling the function. It * has no way to do this, but on most machines 1-arg and 3-arg functions * have the same calling protocol so there is no problem in practice. * A bit in sa_flags could be used to specify the number of args. */ typedef void __sighandler_t __P((int)); #define SIG_DFL ((__sighandler_t *)0) #define SIG_IGN ((__sighandler_t *)1) #define SIG_ERR ((__sighandler_t *)-1) #if defined(_P1003_1B_VISIBLE) || defined(_KERNEL) union sigval { /* Members as suggested by Annex C of POSIX 1003.1b. */ int sigval_int; void *sigval_ptr; }; struct sigevent { int sigev_notify; /* Notification type */ int sigev_signo; /* Signal number */ union sigval sigev_value; /* Signal value */ }; #define SIGEV_NONE 0 /* No async notification */ #define SIGEV_SIGNAL 1 /* Generate a queued signal */ typedef struct __siginfo { int si_signo; /* signal number */ int si_errno; /* errno association */ /* * Cause of signal, one of the SI_ macros or signal-specific * values, i.e. one of the FPE_... values for SIGFPE. This * value is equivalent to the second argument to an old-style * FreeBSD signal handler. */ int si_code; /* signal code */ int si_pid; /* sending process */ unsigned int si_uid; /* sender's ruid */ int si_status; /* exit value */ void *si_addr; /* faulting instruction */ union sigval si_value; /* signal value */ long si_band; /* band event for SIGPOLL */ int __spare__[7]; /* gimme some slack */ } siginfo_t; #endif /* _P1003_1B_VISIBLE */ typedef struct __sigset { unsigned int __bits[_SIG_WORDS]; } sigset_t; /* * XXX - there are some nasty dependencies on include file order. Now that * sigset_t has been defined we can include the MD header. */ #include /* sig_atomic_t; trap codes; sigcontext */ #if !defined(_ANSI_SOURCE) struct __siginfo; /* * Signal vector "template" used in sigaction call. */ struct sigaction { union { void (*__sa_handler) __P((int)); void (*__sa_sigaction) __P((int, struct __siginfo *, void *)); } __sigaction_u; /* signal handler */ int sa_flags; /* see signal options below */ sigset_t sa_mask; /* signal mask to apply */ }; /* if SA_SIGINFO is set, sa_sigaction is to be used instead of sa_handler. */ #define sa_handler __sigaction_u.__sa_handler #define SA_NOCLDSTOP 0x0008 /* do not generate SIGCHLD on child stop */ #if !defined(_POSIX_SOURCE) #define sa_sigaction __sigaction_u.__sa_sigaction #define SA_ONSTACK 0x0001 /* take signal on signal stack */ #define SA_RESTART 0x0002 /* restart system call on signal return */ #define SA_RESETHAND 0x0004 /* reset to SIG_DFL when taking signal */ #define SA_NODEFER 0x0010 /* don't mask the signal we're delivering */ #define SA_NOCLDWAIT 0x0020 /* don't keep zombies around */ #define SA_SIGINFO 0x0040 /* signal handler with SA_SIGINFO args */ #ifdef COMPAT_SUNOS #define SA_USERTRAMP 0x0100 /* do not bounce off kernel's sigtramp */ #endif #define NSIG 32 /* number of old signals (counting 0) */ /* POSIX 1003.1b required values. */ #define SI_USER 0x10001 #define SI_QUEUE 0x10002 #define SI_TIMER 0x10003 #define SI_ASYNCIO 0x10004 #define SI_MESGQ 0x10005 /* Additional FreeBSD values. */ #define SI_UNDEFINED 0 typedef void __siginfohandler_t __P((int, struct __siginfo *, void *)); typedef __sighandler_t *sig_t; /* type of pointer to a signal function */ #ifdef _BSD_SIZE_T_ typedef _BSD_SIZE_T_ size_t; #undef _BSD_SIZE_T_ #endif /* * Structure used in sigaltstack call. */ typedef struct sigaltstack { char *ss_sp; /* signal stack base */ size_t ss_size; /* signal stack length */ int ss_flags; /* SS_DISABLE and/or SS_ONSTACK */ } stack_t; #define SS_ONSTACK 0x0001 /* take signal on alternate stack */ #define SS_DISABLE 0x0004 /* disable taking signals on alternate stack */ -#define MINSIGSTKSZ 8192 /* minimum allowable stack */ #define SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended stack size */ /* Have enough typedefs for this now. XXX */ #include /* * 4.3 compatibility: * Signal vector "template" used in sigvec call. */ struct sigvec { __sighandler_t *sv_handler; /* signal handler */ int sv_mask; /* signal mask to apply */ int sv_flags; /* see signal options below */ }; #define SV_ONSTACK SA_ONSTACK #define SV_INTERRUPT SA_RESTART /* same bit, opposite sense */ #define SV_RESETHAND SA_RESETHAND #define SV_NODEFER SA_NODEFER #define SV_NOCLDSTOP SA_NOCLDSTOP #define SV_SIGINFO SA_SIGINFO #define sv_onstack sv_flags /* isn't compatibility wonderful! */ /* * Structure used in sigstack call. */ struct sigstack { char *ss_sp; /* signal stack pointer */ int ss_onstack; /* current status */ }; /* * Macro for converting signal number to a mask suitable for * sigblock(). */ #define sigmask(m) (1 << ((m)-1)) #define BADSIG SIG_ERR #endif /* !_POSIX_SOURCE */ /* * Flags for sigprocmask: */ #define SIG_BLOCK 1 /* block specified signal set */ #define SIG_UNBLOCK 2 /* unblock specified signal set */ #define SIG_SETMASK 3 /* set specified signal set */ #endif /* !_ANSI_SOURCE */ /* * For historical reasons; programs expect signal's return value to be * defined by . */ __BEGIN_DECLS __sighandler_t *signal __P((int, __sighandler_t *)); __END_DECLS #endif /* !_SYS_SIGNAL_H_ */ Index: head/sys/sys/sysent.h =================================================================== --- head/sys/sys/sysent.h (revision 68519) +++ head/sys/sys/sysent.h (revision 68520) @@ -1,121 +1,122 @@ /*- * Copyright (c) 1982, 1988, 1991 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SYS_SYSENT_H_ #define _SYS_SYSENT_H_ struct proc; typedef int sy_call_t __P((struct proc *, void *)); struct sysent { /* system call table */ int sy_narg; /* number of arguments */ sy_call_t *sy_call; /* implementing function */ }; #define SYF_ARGMASK 0x0000FFFF #define SYF_MPSAFE 0x00010000 #define SCARG(p,k) ((p)->k) /* get arg from args pointer */ /* placeholder till we integrate rest of lite2 syscallargs changes XXX */ struct image_params; struct __sigset; struct trapframe; struct vnode; struct sysentvec { int sv_size; /* number of entries */ struct sysent *sv_table; /* pointer to sysent */ u_int sv_mask; /* optional mask to index */ int sv_sigsize; /* size of signal translation table */ int *sv_sigtbl; /* signal translation table */ int sv_errsize; /* size of errno translation table */ int *sv_errtbl; /* errno translation table */ int (*sv_transtrap) __P((int, int)); /* translate trap-to-signal mapping */ int (*sv_fixup) __P((register_t **, struct image_params *)); /* stack fixup function */ void (*sv_sendsig) __P((void (*)(int), int, struct __sigset *, u_long)); /* send signal */ char *sv_sigcode; /* start of sigtramp code */ int *sv_szsigcode; /* size of sigtramp code */ void (*sv_prepsyscall) __P((struct trapframe *, int *, u_int *, caddr_t *)); char *sv_name; /* name of binary type */ int (*sv_coredump) __P((struct proc *, struct vnode *, off_t)); /* function to dump core, or NULL */ int (*sv_imgact_try) __P((struct image_params *)); + int sv_minsigstksz; /* minimum signal stack size */ }; #ifdef _KERNEL extern struct sysentvec aout_sysvec; extern struct sysentvec elf_freebsd_sysvec; extern struct sysent sysent[]; #define NO_SYSCALL (-1) struct module; struct syscall_module_data { int (*chainevh)(struct module *, int, void *); /* next handler */ void *chainarg; /* arg for next event handler */ int *offset; /* offset into sysent */ struct sysent *new_sysent; /* new sysent */ struct sysent old_sysent; /* old sysent */ }; #define SYSCALL_MODULE(name, offset, new_sysent, evh, arg) \ static struct syscall_module_data name##_syscall_mod = { \ evh, arg, offset, new_sysent \ }; \ \ static moduledata_t name##_mod = { \ #name, \ syscall_module_handler, \ &name##_syscall_mod \ }; \ DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE) int syscall_register __P((int *offset, struct sysent *new_sysent, struct sysent *old_sysent)); int syscall_deregister __P((int *offset, struct sysent *old_sysent)); int syscall_module_handler __P((struct module *mod, int what, void *arg)); #endif /* _KERNEL */ #endif /* !_SYS_SYSENT_H_ */