Index: kern/kern_sig.c
===================================================================
--- kern/kern_sig.c	(revision 180003)
+++ kern/kern_sig.c	(working copy)
@@ -48,6 +48,7 @@
 #include <sys/acct.h>
 #include <sys/condvar.h>
 #include <sys/event.h>
+#include <sys/eventhandler.h>
 #include <sys/fcntl.h>
 #include <sys/kernel.h>
 #include <sys/ktr.h>
@@ -84,6 +85,8 @@
 
 #define	ONSIG	32		/* NSIG for osig* syscalls.  XXX. */
 
+int (*linux_signal_handler)(struct proc *, int) = NULL;
+
 SDT_PROVIDER_DECLARE(proc);
 SDT_PROBE_DEFINE(proc, kernel, , signal_send);
 SDT_PROBE_ARGTYPE(proc, kernel, , signal_send, 0, "struct thread *");
@@ -1951,6 +1954,20 @@
 int
 tdsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
 {
+	/* XXX: Linux signals need special handling. */
+	if (linux_signal_handler != NULL) {
+		int linux = (*linux_signal_handler)(p, sig);
+
+		if (__predicate_false(linux))
+			return (0);
+	}
+
+	return (tdsignal1(p, td, sig, ksi));
+}
+
+int
+tdsignal1(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
+{
 	sig_t action;
 	sigqueue_t *sigqueue;
 	int prop;
Index: compat/linux/linux_signal.h
===================================================================
--- compat/linux/linux_signal.h	(revision 180003)
+++ compat/linux/linux_signal.h	(working copy)
@@ -34,7 +34,10 @@
 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 *);
+int linux_proc_signal(struct proc *p, int);
 
+extern int (*linux_signal_handler)(struct proc *, int);
+
 #define LINUX_SIG_VALID(sig)	((sig) <= LINUX_NSIG && (sig) > 0)
 
 #endif /* _LINUX_SIGNAL_H_ */
Index: compat/linux/linux_signal.c
===================================================================
--- compat/linux/linux_signal.c	(revision 180003)
+++ compat/linux/linux_signal.c	(working copy)
@@ -535,6 +535,33 @@
 	return (kill(td, &tmp));
 }
 
+static int
+linux_kill1(struct thread *td, struct linux_kill_args *args)
+{
+	struct proc *pk;
+	int signum;
+	int error = ESRCH;
+
+	/*
+	 * Allow signal 0 as a means to check for privileges
+	 */
+	if (!LINUX_SIG_VALID(args->signum) && args->signum != 0)
+		return EINVAL;
+
+	if (args->signum > 0 && args->signum <= LINUX_SIGTBLSZ)
+		signum = linux_to_bsd_signal[_SIG_IDX(args->signum)];
+	else
+		signum = args->signum;
+
+	pk = pfind(args->pid);
+	if (pk || (pk = zpfind(args->pid))) {
+		if ((error = p_cansignal(FIRST_THREAD_IN_PROC(td->td_proc), pk, signum)))
+			error = tdsignal1(pk, NULL, signum, NULL);
+		PROC_UNLOCK(pk);
+	}
+
+	return (error);
+}
 int
 linux_tgkill(struct thread *td, struct linux_tgkill_args *args)
 {
@@ -573,7 +600,7 @@
 	if (em->shared->group_pid != args->tgid)
 	   	return ESRCH;
 
-	return linux_kill(td, &ka);
+	return linux_kill1(td, &ka);
 }
 
 int
@@ -584,5 +611,46 @@
 		printf(ARGS(tkill, "%i, %i"), args->tid, args->sig);
 #endif
 
-	return (linux_kill(td, (struct linux_kill_args *) args));
+	return (linux_kill1(td, (struct linux_kill_args *) args));
 }
+
+/*
+ * XXX: locking - what if some thread/process disappears in the middle of this? 
+ * should I hold proctree_lock or something? or is holding the proc lock sufficient
+ * in this case? please review
+ */
+int
+linux_proc_signal(struct proc *p, int signal)
+{
+	int *tmp = NULL;
+	struct linux_emuldata *em, *tem;
+	struct proc *pk;
+	int error = 0, i = 0;
+
+	if (__predict_true(p->p_sysent != &elf_linux_sysvec))
+		return (0);
+
+	em = em_find(p, EMUL_DONTLOCK);
+
+	EMUL_SHARED_RLOCK(&emul_shared_lock);	
+	LIST_FOREACH(tem, &em->shared->threads, threads) {
+		tmp = realloc(tmp, (i+1) * sizeof(int), M_TEMP, M_WAITOK);
+		tmp[i] = tem->pid;
+		i++;
+	}
+	EMUL_SHARED_RUNLOCK(&emul_shared_lock);	
+
+	for (; i >= 0; i--) {
+		pk = pfind(tmp[i]);
+		if (pk || (pk = zpfind(tmp[i]))) {
+	   		/* try to accumulate the error */
+			if (p_cansignal(FIRST_THREAD_IN_PROC(p), pk, signal))
+   				error |= tdsignal1(pk, NULL, signal, NULL);
+			PROC_UNLOCK(pk);
+		}
+	}
+
+	free(tmp, M_TEMP);
+
+	return (1);
+}
Index: i386/linux/linux_sysvec.c
===================================================================
--- i386/linux/linux_sysvec.c	(revision 180003)
+++ i386/linux/linux_sysvec.c	(working copy)
@@ -929,6 +929,7 @@
 			      NULL, 1000);
 			linux_exec_tag = EVENTHANDLER_REGISTER(process_exec, linux_proc_exec,
 			      NULL, 1000);
+			linux_signal_handler = linux_proc_signal;
 			if (bootverbose)
 				printf("Linux ELF exec handler installed\n");
 		} else
@@ -956,6 +957,7 @@
 			EVENTHANDLER_DEREGISTER(process_exit, linux_exit_tag);
 			EVENTHANDLER_DEREGISTER(schedtail, linux_schedtail_tag);
 			EVENTHANDLER_DEREGISTER(process_exec, linux_exec_tag);
+			linux_signal_handler = NULL;
 			if (bootverbose)
 				printf("Linux ELF exec handler removed\n");
 		} else
Index: amd64/linux32/linux32_sysvec.c
===================================================================
--- amd64/linux32/linux32_sysvec.c	(revision 180003)
+++ amd64/linux32/linux32_sysvec.c	(working copy)
@@ -1088,6 +1088,7 @@
 			      NULL, 1000);
 			linux_exec_tag = EVENTHANDLER_REGISTER(process_exec, linux_proc_exec,
 			      NULL, 1000);
+			linux_signal_handler = linux_proc_signal;
 			if (bootverbose)
 				printf("Linux ELF exec handler installed\n");
 		} else
@@ -1115,6 +1116,7 @@
 			EVENTHANDLER_DEREGISTER(process_exit, linux_exit_tag);
 			EVENTHANDLER_DEREGISTER(schedtail, linux_schedtail_tag);
 			EVENTHANDLER_DEREGISTER(process_exec, linux_exec_tag);
+			linux_signal_handler = NULL;
 			if (bootverbose)
 				printf("Linux ELF exec handler removed\n");
 		} else
Index: sys/signalvar.h
===================================================================
--- sys/signalvar.h	(revision 180003)
+++ sys/signalvar.h	(working copy)
@@ -334,6 +334,8 @@
 void	signotify(struct thread *td);
 int	tdsignal(struct proc *p, struct thread *td, int sig,
 	    ksiginfo_t *ksi);
+int	tdsignal1(struct proc *p, struct thread *td, int sig,
+	    ksiginfo_t *ksi);
 void	trapsignal(struct thread *td, ksiginfo_t *);
 int	ptracestop(struct thread *td, int sig);
 ksiginfo_t * ksiginfo_alloc(int);
