PR kern/36183 problem with ptrace and multithreaded processes
Fix the crashy test case that Thor provided.
This commit is contained in:
parent
bbaefad73d
commit
3c32363107
@ -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.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
@ -206,7 +206,7 @@
|
||||
*/
|
||||
|
||||
#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_lockdebug.h"
|
||||
@ -1388,6 +1388,47 @@ lwp_drainrefs(struct lwp *l)
|
||||
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 --
|
||||
* Create a key for subsystem lwp-specific data.
|
||||
|
@ -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.
|
||||
*
|
||||
* 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
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
@ -115,7 +118,7 @@
|
||||
*/
|
||||
|
||||
#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_ktrace.h"
|
||||
@ -337,10 +340,16 @@ sys_ptrace(struct lwp *l, const struct sys_ptrace_args *uap, register_t *retval)
|
||||
break;
|
||||
}
|
||||
|
||||
if (error == 0)
|
||||
if (error == 0) {
|
||||
error = kauth_authorize_process(l->l_cred,
|
||||
KAUTH_PROCESS_PTRACE, t, KAUTH_ARG(req),
|
||||
NULL, NULL);
|
||||
}
|
||||
if (error == 0) {
|
||||
lt = lwp_find_first(t);
|
||||
if (lt == NULL)
|
||||
error = ESRCH;
|
||||
}
|
||||
|
||||
if (error != 0) {
|
||||
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. */
|
||||
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);
|
||||
lwp_addref(lt);
|
||||
|
||||
@ -641,7 +640,7 @@ sys_ptrace(struct lwp *l, const struct sys_ptrace_args *uap, register_t *retval)
|
||||
lwp_delref(lt);
|
||||
mutex_enter(t->p_lock);
|
||||
if (tmp == 0)
|
||||
lt = LIST_FIRST(&t->p_lwps);
|
||||
lt = lwp_find_first(t);
|
||||
else {
|
||||
lt = lwp_find(t, tmp);
|
||||
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);
|
||||
}
|
||||
while (lt != NULL && lt->l_stat == LSZOMB)
|
||||
while (lt != NULL && !lwp_alive(lt))
|
||||
lt = LIST_NEXT(lt, l_sibling);
|
||||
pl.pl_lwpid = 0;
|
||||
pl.pl_event = 0;
|
||||
|
@ -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.
|
||||
*
|
||||
* 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_delref(lwp_t *);
|
||||
void lwp_drainrefs(lwp_t *);
|
||||
bool lwp_alive(lwp_t *);
|
||||
lwp_t *lwp_find_first(proc_t *);
|
||||
|
||||
/* Flags for _lwp_wait1 */
|
||||
#define LWPWAIT_EXITCONTROL 0x00000001
|
||||
|
Loading…
Reference in New Issue
Block a user