tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Unused SI_LWP si_code definition ?



On Wed, Oct 15, 2008 at 05:42:30PM +0200, Nicolas Joly wrote:
> 
> While looking into existing si_code values, i discovered SI_LWP
> definition (src/sys/sys/siginfo.h). According to the corresponding
> comment it should be set by _lwp_kill(2), but it SI_USER is set
> instead ... So this value is currently unused.
> 
> For compat linux NPTL emulation, i do need this functionality, where 2
> syscalls tkill and tgkill set up si_code to SI_TKILL. This value is
> needed by a handler in libpthread to switch a bit, allowing threads to
> be properly cancelled.

Attached a preliminary patch (native to linux si_code conversion need
some more work), which fix some pthread cancellation problems/hangs
under amd64 NPTL compat linux emulation.

-- 
Nicolas Joly

Biological Software and Databanks.
Institut Pasteur, Paris.
Index: sys/compat/linux/arch/amd64/linux_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/compat/linux/arch/amd64/linux_machdep.c,v
retrieving revision 1.32
diff -u -p -r1.32 linux_machdep.c
--- sys/compat/linux/arch/amd64/linux_machdep.c 18 Sep 2008 15:57:04 -0000      
1.32
+++ sys/compat/linux/arch/amd64/linux_machdep.c 15 Oct 2008 21:59:17 -0000
@@ -230,7 +230,8 @@ linux_sendsig(const ksiginfo_t *ksi, con
         */
        sigframe.info.lsi_signo = native_to_linux_signo[sig];
        sigframe.info.lsi_errno = native_to_linux_errno[ksi->ksi_errno];
-       sigframe.info.lsi_code = ksi->ksi_code;
+       sigframe.info.lsi_code =
+           (ksi->ksi_code == SI_LWP) ? LINUX_SI_TKILL : ksi->ksi_code;
 
        /* XXX This is a rought conversion, taken from i386 code */
        switch (sigframe.info.lsi_signo) {
Index: sys/compat/linux/common/linux_siginfo.h
===================================================================
RCS file: /cvsroot/src/sys/compat/linux/common/linux_siginfo.h,v
retrieving revision 1.11
diff -u -p -r1.11 linux_siginfo.h
--- sys/compat/linux/common/linux_siginfo.h     28 Apr 2008 20:23:44 -0000      
1.11
+++ sys/compat/linux/common/linux_siginfo.h     15 Oct 2008 21:59:17 -0000
@@ -48,6 +48,16 @@
 #include <compat/linux/arch/amd64/linux_siginfo.h>
 #endif
 
+/* si_code values */
+#define        LINUX_SI_USER           0
+#define        LINUX_SI_QUEUE          -1
+#define        LINUX_SI_TIMER          -2
+#define        LINUX_SI_MESGQ          -3
+#define        LINUX_SI_ASYNCIO        -4
+#define        LINUX_SI_SIGIO          -5
+#define        LINUX_SI_TKILL          -6
+#define        LINUX_SI_DETHREAD       -7
+
 /* From linux/include/asm-generic/siginfo.h */
 #define LINUX_CLD_EXITED       1
 #define LINUX_CLD_KILLED       2
Index: sys/compat/linux/common/linux_signal.c
===================================================================
RCS file: /cvsroot/src/sys/compat/linux/common/linux_signal.c,v
retrieving revision 1.63
diff -u -p -r1.63 linux_signal.c
--- sys/compat/linux/common/linux_signal.c      30 Jul 2008 16:05:26 -0000      
1.63
+++ sys/compat/linux/common/linux_signal.c      15 Oct 2008 21:59:17 -0000
@@ -604,6 +604,45 @@ linux_sys_sigaltstack(struct lwp *l, con
 #endif /* LINUX_SS_ONSTACK */
 
 #ifdef LINUX_NPTL
+static int
+linux_do_tkill(struct lwp *l, int tgid, int tid, int signum)
+{
+       struct proc *p;
+       int error;
+       ksiginfo_t ksi;
+       struct linux_emuldata *led;
+
+       if (signum < 0 || signum >= LINUX__NSIG)
+               return EINVAL;
+       signum = linux_to_native_signo[signum];
+
+       KSI_INIT(&ksi);
+       ksi.ksi_signo = signum;
+       ksi.ksi_code = SI_LWP;
+       ksi.ksi_pid = l->l_proc->p_pid;
+       ksi.ksi_uid = kauth_cred_geteuid(l->l_cred);
+
+       mutex_enter(proc_lock);
+       if ((p = p_find(tid, PFIND_LOCKED)) == NULL) {
+               mutex_exit(proc_lock);
+               return ESRCH;
+       }
+       led = p->p_emuldata;
+       if (tgid > 0 && led->s->group_pid != tgid) {
+               mutex_exit(proc_lock);
+               return ESRCH;
+       }
+       mutex_enter(p->p_lock);
+       error = kauth_authorize_process(l->l_cred,
+           KAUTH_PROCESS_SIGNAL, p, KAUTH_ARG(signum), NULL, NULL);
+       if (!error && signum)
+               kpsignal2(p, &ksi);
+       mutex_exit(p->p_lock);
+       mutex_exit(proc_lock);
+
+       return error;
+}
+
 int
 linux_sys_tkill(struct lwp *l, const struct linux_sys_tkill_args *uap, 
register_t *retval)
 {
@@ -611,13 +650,11 @@ linux_sys_tkill(struct lwp *l, const str
                syscallarg(int) tid;
                syscallarg(int) sig;
        } */
-       struct linux_sys_kill_args cup;
 
-       /* We use the PID as the TID ... */
-       SCARG(&cup, pid) = SCARG(uap, tid);
-       SCARG(&cup, signum) = SCARG(uap, sig);
+       if (SCARG(uap, tid) <= 0)
+               return EINVAL;
 
-       return linux_sys_kill(l, &cup, retval);
+       return linux_do_tkill(l, 0, SCARG(uap, tid), SCARG(uap, sig));
 }
 
 int
@@ -628,31 +665,10 @@ linux_sys_tgkill(struct lwp *l, const st
                syscallarg(int) tid;
                syscallarg(int) sig;
        } */
-       struct linux_sys_kill_args cup;
-       struct linux_emuldata *led;
-       struct proc *p;
 
-       SCARG(&cup, pid) = SCARG(uap, tid);
-       SCARG(&cup, signum) = SCARG(uap, sig);
-
-       if (SCARG(uap, tgid) == -1)
-               return linux_sys_kill(l, &cup, retval);
-
-       /* We use the PID as the TID, but make sure the group ID is right */
-       /* XXX racy */
-       mutex_enter(proc_lock);
-       if ((p = p_find(SCARG(uap, tid), PFIND_LOCKED)) == NULL ||
-           p->p_emul != &emul_linux) {
-               mutex_exit(proc_lock);
-               return ESRCH;
-       }
-       led = p->p_emuldata;
-       if (led->s->group_pid != SCARG(uap, tgid)) {
-               mutex_exit(proc_lock);
-               return ESRCH;
-       }
-       mutex_exit(proc_lock);
+       if (SCARG(uap, tid) <= 0 || SCARG(uap, tgid) <= 0)
+               return EINVAL;
 
-       return linux_sys_kill(l, &cup, retval);
+       return linux_do_tkill(l, SCARG(uap, tgid), SCARG(uap, tid), SCARG(uap, 
sig));
 }
 #endif /* LINUX_NPTL */


Home | Main Index | Thread Index | Old Index