DF-0103 / fix.diff
diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -363,10 +363,16 @@ lwkt_gettoken(&pg->pg_token); LIST_FOREACH(p, &pg->pg_members, p_pglist) { PHOLD(p); - if (descend) + if (descend) { ret |= ktrsetchildren(td, p, ops, facs, tracenode); - else + } else { + /* hold target token around p_tracenode mutation + * (ktrops is otherwise unlocked vs concurrent + * ktrace on the same pid -> double-free) */ + lwkt_gettoken(&p->p_token); ret |= ktrops(td, p, ops, facs, tracenode); + lwkt_reltoken(&p->p_token); + } PRELE(p); } lwkt_reltoken(&pg->pg_token); @@ -380,10 +386,14 @@ error = ESRCH; goto done; } - if (descend) + if (descend) { ret |= ktrsetchildren(td, p, ops, facs, tracenode); - else + } else { + /* hold target token around p_tracenode mutation */ + lwkt_gettoken(&p->p_token); ret |= ktrops(td, p, ops, facs, tracenode); + lwkt_reltoken(&p->p_token); + } PRELE(p); } if (!ret) |