PR kern/36183 problem with ptrace and multithreaded processes

Fix the crashy test case that Thor provided.
This commit is contained in:
ad 2009-02-04 21:17:39 +00:00
parent bbaefad73d
commit 3c32363107
3 changed files with 63 additions and 21 deletions

View File

@ -1,7 +1,7 @@
/* $NetBSD: kern_lwp.c,v 1.126 2008/10/28 22:11:36 wrstuden Exp $ */ /* $NetBSD: kern_lwp.c,v 1.127 2009/02/04 21:17:39 ad Exp $ */
/*- /*-
* Copyright (c) 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc. * Copyright (c) 2001, 2006, 2007, 2008, 2009 The NetBSD Foundation, Inc.
* All rights reserved. * All rights reserved.
* *
* This code is derived from software contributed to The NetBSD Foundation * This code is derived from software contributed to The NetBSD Foundation
@ -206,7 +206,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.126 2008/10/28 22:11:36 wrstuden Exp $"); __KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.127 2009/02/04 21:17:39 ad Exp $");
#include "opt_ddb.h" #include "opt_ddb.h"
#include "opt_lockdebug.h" #include "opt_lockdebug.h"
@ -1388,6 +1388,47 @@ lwp_drainrefs(struct lwp *l)
cv_wait(&p->p_lwpcv, p->p_lock); cv_wait(&p->p_lwpcv, p->p_lock);
} }
/*
* Return true if the specified LWP is 'alive'. Only p->p_lock need
* be held.
*/
bool
lwp_alive(lwp_t *l)
{
KASSERT(mutex_owned(l->l_proc->p_lock));
switch (l->l_stat) {
case LSSLEEP:
case LSRUN:
case LSONPROC:
case LSSTOP:
case LSSUSPENDED:
return true;
default:
return false;
}
}
/*
* Return first live LWP in the process.
*/
lwp_t *
lwp_find_first(proc_t *p)
{
lwp_t *l;
KASSERT(mutex_owned(p->p_lock));
LIST_FOREACH(l, &p->p_lwps, l_sibling) {
if (lwp_alive(l)) {
return l;
}
}
return NULL;
}
/* /*
* lwp_specific_key_create -- * lwp_specific_key_create --
* Create a key for subsystem lwp-specific data. * Create a key for subsystem lwp-specific data.

View File

@ -1,9 +1,12 @@
/* $NetBSD: sys_process.c,v 1.145 2009/01/22 14:38:35 yamt Exp $ */ /* $NetBSD: sys_process.c,v 1.146 2009/02/04 21:17:39 ad Exp $ */
/*- /*-
* Copyright (c) 2008 The NetBSD Foundation, Inc. * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
* All rights reserved. * All rights reserved.
* *
* This code is derived from software contributed to The NetBSD Foundation
* by Andrew Doran.
*
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
@ -115,7 +118,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sys_process.c,v 1.145 2009/01/22 14:38:35 yamt Exp $"); __KERNEL_RCSID(0, "$NetBSD: sys_process.c,v 1.146 2009/02/04 21:17:39 ad Exp $");
#include "opt_ptrace.h" #include "opt_ptrace.h"
#include "opt_ktrace.h" #include "opt_ktrace.h"
@ -337,10 +340,16 @@ sys_ptrace(struct lwp *l, const struct sys_ptrace_args *uap, register_t *retval)
break; break;
} }
if (error == 0) if (error == 0) {
error = kauth_authorize_process(l->l_cred, error = kauth_authorize_process(l->l_cred,
KAUTH_PROCESS_PTRACE, t, KAUTH_ARG(req), KAUTH_PROCESS_PTRACE, t, KAUTH_ARG(req),
NULL, NULL); NULL, NULL);
}
if (error == 0) {
lt = lwp_find_first(t);
if (lt == NULL)
error = ESRCH;
}
if (error != 0) { if (error != 0) {
mutex_exit(proc_lock); mutex_exit(proc_lock);
@ -351,16 +360,6 @@ sys_ptrace(struct lwp *l, const struct sys_ptrace_args *uap, register_t *retval)
/* Do single-step fixup if needed. */ /* Do single-step fixup if needed. */
FIX_SSTEP(t); FIX_SSTEP(t);
/*
* XXX NJWLWP
*
* The entire ptrace interface needs work to be useful to a
* process with multiple LWPs. For the moment, we'll kluge
* this; memory access will be fine, but register access will
* be weird.
*/
lt = LIST_FIRST(&t->p_lwps);
KASSERT(lt != NULL); KASSERT(lt != NULL);
lwp_addref(lt); lwp_addref(lt);
@ -641,7 +640,7 @@ sys_ptrace(struct lwp *l, const struct sys_ptrace_args *uap, register_t *retval)
lwp_delref(lt); lwp_delref(lt);
mutex_enter(t->p_lock); mutex_enter(t->p_lock);
if (tmp == 0) if (tmp == 0)
lt = LIST_FIRST(&t->p_lwps); lt = lwp_find_first(t);
else { else {
lt = lwp_find(t, tmp); lt = lwp_find(t, tmp);
if (lt == NULL) { if (lt == NULL) {
@ -651,7 +650,7 @@ sys_ptrace(struct lwp *l, const struct sys_ptrace_args *uap, register_t *retval)
} }
lt = LIST_NEXT(lt, l_sibling); lt = LIST_NEXT(lt, l_sibling);
} }
while (lt != NULL && lt->l_stat == LSZOMB) while (lt != NULL && !lwp_alive(lt))
lt = LIST_NEXT(lt, l_sibling); lt = LIST_NEXT(lt, l_sibling);
pl.pl_lwpid = 0; pl.pl_lwpid = 0;
pl.pl_event = 0; pl.pl_event = 0;

View File

@ -1,7 +1,7 @@
/* $NetBSD: lwp.h,v 1.116 2009/01/11 02:45:55 christos Exp $ */ /* $NetBSD: lwp.h,v 1.117 2009/02/04 21:17:39 ad Exp $ */
/*- /*-
* Copyright (c) 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc. * Copyright (c) 2001, 2006, 2007, 2008, 2009 The NetBSD Foundation, Inc.
* All rights reserved. * All rights reserved.
* *
* This code is derived from software contributed to The NetBSD Foundation * This code is derived from software contributed to The NetBSD Foundation
@ -282,6 +282,8 @@ int lwp_trylock(lwp_t *);
void lwp_addref(lwp_t *); void lwp_addref(lwp_t *);
void lwp_delref(lwp_t *); void lwp_delref(lwp_t *);
void lwp_drainrefs(lwp_t *); void lwp_drainrefs(lwp_t *);
bool lwp_alive(lwp_t *);
lwp_t *lwp_find_first(proc_t *);
/* Flags for _lwp_wait1 */ /* Flags for _lwp_wait1 */
#define LWPWAIT_EXITCONTROL 0x00000001 #define LWPWAIT_EXITCONTROL 0x00000001