diff --git a/sys/amd64/linux32/linux.h b/sys/amd64/linux32/linux.h index 0acdd68104f3..2354864f22a0 100644 --- a/sys/amd64/linux32/linux.h +++ b/sys/amd64/linux32/linux.h @@ -86,6 +86,8 @@ typedef l_long l_suseconds_t; typedef l_long l_time_t; typedef l_uint l_uid_t; typedef l_ushort l_uid16_t; +typedef l_int l_timer_t; +typedef l_int l_mqd_t; typedef struct { l_int val[2]; @@ -399,10 +401,10 @@ struct l_ucontext { #define LINUX_SI_MAX_SIZE 128 #define LINUX_SI_PAD_SIZE ((LINUX_SI_MAX_SIZE/sizeof(l_int)) - 3) -union l_sigval { +typedef union l_sigval { l_int sival_int; l_uintptr_t sival_ptr; -}; +} l_sigval_t; typedef struct l_siginfo { l_int lsi_signo; @@ -413,23 +415,26 @@ typedef struct l_siginfo { struct { l_pid_t _pid; - l_uid16_t _uid; + l_uid_t _uid; } __packed _kill; struct { - l_uint _timer1; - l_uint _timer2; + l_timer_t _tid; + l_int _overrun; + char _pad[sizeof(l_uid_t) - sizeof(l_int)]; + l_sigval_t _sigval; + l_int _sys_private; } __packed _timer; struct { l_pid_t _pid; /* sender's pid */ - l_uid16_t _uid; /* sender's uid */ - union l_sigval _sigval; + l_uid_t _uid; /* sender's uid */ + l_sigval_t _sigval; } __packed _rt; struct { l_pid_t _pid; /* which child */ - l_uid16_t _uid; /* sender's uid */ + l_uid_t _uid; /* sender's uid */ l_int _status; /* exit code */ l_clock_t _utime; l_clock_t _stime; @@ -440,7 +445,7 @@ typedef struct l_siginfo { } __packed _sigfault; struct { - l_int _band; /* POLL_IN,POLL_OUT,POLL_MSG */ + l_long _band; /* POLL_IN,POLL_OUT,POLL_MSG */ l_int _fd; } __packed _sigpoll; } _sifields; @@ -448,6 +453,9 @@ typedef struct l_siginfo { #define lsi_pid _sifields._kill._pid #define lsi_uid _sifields._kill._uid +#define lsi_tid _sifields._timer._tid +#define lsi_overrun _sifields._timer._overrun +#define lsi_sys_private _sifields._timer._sys_private #define lsi_status _sifields._sigchld._status #define lsi_utime _sifields._sigchld._utime #define lsi_stime _sifields._sigchld._stime @@ -860,9 +868,6 @@ struct l_user_desc { #define LINUX_CLOCK_REALTIME_HR 4 #define LINUX_CLOCK_MONOTONIC_HR 5 -typedef int l_timer_t; -typedef int l_mqd_t; - #define LINUX_CLONE_VM 0x00000100 #define LINUX_CLONE_FS 0x00000200 #define LINUX_CLONE_FILES 0x00000400 diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c index 6a7aac71927a..e2337007ef5d 100644 --- a/sys/amd64/linux32/linux32_sysvec.c +++ b/sys/amd64/linux32/linux32_sysvec.c @@ -334,9 +334,7 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) frame.sf_ucontext = PTROUT(&fp->sf_sc); /* Fill in POSIX parts */ - frame.sf_si.lsi_signo = sig; - frame.sf_si.lsi_code = code; - frame.sf_si.lsi_addr = PTROUT(ksi->ksi_addr); + ksiginfo_to_lsiginfo(ksi, &frame.sf_si, sig); /* * Build the signal context to be used by sigreturn. diff --git a/sys/compat/linux/linux_signal.c b/sys/compat/linux/linux_signal.c index d40d9d7a8c98..9bbc268131ef 100644 --- a/sys/compat/linux/linux_signal.c +++ b/sys/compat/linux/linux_signal.c @@ -39,6 +39,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + #include "opt_compat.h" #ifdef COMPAT_LINUX32 @@ -535,45 +537,75 @@ linux_kill(struct thread *td, struct linux_kill_args *args) return (kill(td, &tmp)); } +static int +linux_do_tkill(struct thread *td, l_int tgid, l_int pid, l_int signum) +{ + struct proc *proc = td->td_proc; + struct linux_emuldata *em; + struct proc *p; + ksiginfo_t ksi; + int error; + + AUDIT_ARG(signum, signum); + AUDIT_ARG(pid, pid); + + /* + * Allow signal 0 as a means to check for privileges + */ + if (!LINUX_SIG_VALID(signum) && signum != 0) + return (EINVAL); + + if (signum > 0 && signum <= LINUX_SIGTBLSZ) + signum = linux_to_bsd_signal[_SIG_IDX(signum)]; + + if ((p = pfind(pid)) == NULL) { + if ((p = zpfind(pid)) == NULL) + return (ESRCH); + } + + AUDIT_ARG(process, p); + error = p_cansignal(td, p, signum); + if (error) + goto out; + + error = ESRCH; + em = em_find(p, EMUL_DONTLOCK); + + if (em == NULL) { +#ifdef DEBUG + printf("emuldata not found in do_tkill.\n"); +#endif + goto out; + } + if (tgid > 0 && em->shared->group_pid != tgid) + goto out; + + ksiginfo_init(&ksi); + ksi.ksi_signo = signum; + ksi.ksi_code = LINUX_SI_TKILL; + ksi.ksi_errno = 0; + ksi.ksi_pid = proc->p_pid; + ksi.ksi_uid = proc->p_ucred->cr_ruid; + + error = tdsignal(p, NULL, ksi.ksi_signo, &ksi); + +out: + PROC_UNLOCK(p); + return (error); +} + int linux_tgkill(struct thread *td, struct linux_tgkill_args *args) { - struct linux_emuldata *em; - struct linux_kill_args ka; - struct proc *p; #ifdef DEBUG if (ldebug(tgkill)) printf(ARGS(tgkill, "%d, %d, %d"), args->tgid, args->pid, args->sig); #endif + if (args->pid <= 0 || args->tgid <=0) + return (EINVAL); - ka.pid = args->pid; - ka.signum = args->sig; - - if (args->tgid == -1) - return linux_kill(td, &ka); - - if ((p = pfind(args->pid)) == NULL) - return ESRCH; - - if (p->p_sysent != &elf_linux_sysvec) - return ESRCH; - - PROC_UNLOCK(p); - - em = em_find(p, EMUL_DONTLOCK); - - if (em == NULL) { -#ifdef DEBUG - printf("emuldata not found in tgkill.\n"); -#endif - return ESRCH; - } - - if (em->shared->group_pid != args->tgid) - return ESRCH; - - return linux_kill(td, &ka); + return (linux_do_tkill(td, args->tgid, args->pid, args->sig)); } int @@ -583,6 +615,39 @@ linux_tkill(struct thread *td, struct linux_tkill_args *args) if (ldebug(tkill)) printf(ARGS(tkill, "%i, %i"), args->tid, args->sig); #endif + if (args->tid <= 0) + return (EINVAL); - return (linux_kill(td, (struct linux_kill_args *) args)); + return (linux_do_tkill(td, 0, args->tid, args->sig)); +} + +void +ksiginfo_to_lsiginfo(ksiginfo_t *ksi, l_siginfo_t *lsi, l_int sig) +{ + + lsi->lsi_signo = sig; + lsi->lsi_code = ksi->ksi_code; + + switch (sig) { + case LINUX_SIGPOLL: + /* XXX si_fd? */ + lsi->lsi_band = ksi->ksi_band; + break; + case LINUX_SIGCHLD: + lsi->lsi_pid = ksi->ksi_pid; + lsi->lsi_uid = ksi->ksi_uid; + lsi->lsi_status = ksi->ksi_status; + break; + case LINUX_SIGBUS: + case LINUX_SIGILL: + case LINUX_SIGFPE: + case LINUX_SIGSEGV: + lsi->lsi_addr = PTROUT(ksi->ksi_addr); + break; + default: + /* XXX SI_TIMER etc... */ + lsi->lsi_pid = ksi->ksi_pid; + lsi->lsi_uid = ksi->ksi_uid; + break; + } } diff --git a/sys/compat/linux/linux_signal.h b/sys/compat/linux/linux_signal.h index 5f6d5bdd45d2..ba780e9937d1 100644 --- a/sys/compat/linux/linux_signal.h +++ b/sys/compat/linux/linux_signal.h @@ -31,9 +31,12 @@ #ifndef _LINUX_SIGNAL_H_ #define _LINUX_SIGNAL_H_ +#define LINUX_SI_TKILL -6; + void linux_to_bsd_sigset(l_sigset_t *, sigset_t *); void bsd_to_linux_sigset(sigset_t *, l_sigset_t *); int linux_do_sigaction(struct thread *, int, l_sigaction_t *, l_sigaction_t *); +void ksiginfo_to_lsiginfo(ksiginfo_t *ksi, l_siginfo_t *lsi, l_int sig); #define LINUX_SIG_VALID(sig) ((sig) <= LINUX_NSIG && (sig) > 0) diff --git a/sys/i386/linux/linux.h b/sys/i386/linux/linux.h index 4f2dbe96ea89..6b11e841e537 100644 --- a/sys/i386/linux/linux.h +++ b/sys/i386/linux/linux.h @@ -80,6 +80,8 @@ typedef l_long l_suseconds_t; typedef l_long l_time_t; typedef l_uint l_uid_t; typedef l_ushort l_uid16_t; +typedef l_int l_timer_t; +typedef l_int l_mqd_t; typedef struct { l_int val[2]; @@ -374,6 +376,11 @@ struct l_ucontext { #define LINUX_SI_MAX_SIZE 128 #define LINUX_SI_PAD_SIZE ((LINUX_SI_MAX_SIZE/sizeof(l_int)) - 3) +typedef union l_sigval { + l_int sival_int; + l_uintptr_t sival_ptr; +} l_sigval_t; + typedef struct l_siginfo { l_int lsi_signo; l_int lsi_errno; @@ -383,34 +390,37 @@ typedef struct l_siginfo { struct { l_pid_t _pid; - l_uid16_t _uid; + l_uid_t _uid; } _kill; struct { - l_uint _timer1; - l_uint _timer2; + l_timer_t _tid; + l_int _overrun; + char _pad[sizeof(l_uid_t) - sizeof(l_int)]; + l_sigval_t _sigval; + l_int _sys_private; } _timer; struct { l_pid_t _pid; /* sender's pid */ - l_uid16_t _uid; /* sender's uid */ - union sigval _sigval; + l_uid_t _uid; /* sender's uid */ + l_sigval_t _sigval; } _rt; struct { l_pid_t _pid; /* which child */ - l_uid16_t _uid; /* sender's uid */ + l_uid_t _uid; /* sender's uid */ l_int _status; /* exit code */ l_clock_t _utime; l_clock_t _stime; } _sigchld; struct { - void *_addr; /* Faulting insn/memory ref. */ + l_uintptr_t _addr; /* Faulting insn/memory ref. */ } _sigfault; struct { - l_int _band; /* POLL_IN,POLL_OUT,POLL_MSG */ + l_long _band; /* POLL_IN,POLL_OUT,POLL_MSG */ l_int _fd; } _sigpoll; } _sifields; @@ -418,6 +428,9 @@ typedef struct l_siginfo { #define lsi_pid _sifields._kill._pid #define lsi_uid _sifields._kill._uid +#define lsi_tid _sifields._timer._tid +#define lsi_overrun _sifields._timer._overrun +#define lsi_sys_private _sifields._timer._sys_private #define lsi_status _sifields._sigchld._status #define lsi_utime _sifields._sigchld._utime #define lsi_stime _sifields._sigchld._stime @@ -825,9 +838,6 @@ struct l_desc_struct { #define LINUX_CLOCK_REALTIME_HR 4 #define LINUX_CLOCK_MONOTONIC_HR 5 -typedef int l_timer_t; -typedef int l_mqd_t; - #define LINUX_CLONE_VM 0x00000100 #define LINUX_CLONE_FS 0x00000200 #define LINUX_CLONE_FILES 0x00000400 diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c index 91f943df930a..a3acfc9fe6b4 100644 --- a/sys/i386/linux/linux_sysvec.c +++ b/sys/i386/linux/linux_sysvec.c @@ -323,9 +323,7 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) frame.sf_ucontext = &fp->sf_sc; /* Fill in POSIX parts */ - frame.sf_si.lsi_signo = sig; - frame.sf_si.lsi_code = code; - frame.sf_si.lsi_addr = ksi->ksi_addr; + ksiginfo_to_lsiginfo(ksi, &frame.sf_si, sig); /* * Build the signal context to be used by sigreturn.