sigactsunshare(): set reference count in a case of new sigacts allocation.

Bug (e.g. memory leak) can happen when using clone(2) call.
This commit is contained in:
rmind 2009-12-30 23:31:56 +00:00
parent 2faaca9342
commit ffb9a7ee3c
1 changed files with 17 additions and 21 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_sig.c,v 1.301 2009/12/20 04:49:09 rmind Exp $ */
/* $NetBSD: kern_sig.c,v 1.302 2009/12/30 23:31:56 rmind Exp $ */
/*-
* Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.301 2009/12/20 04:49:09 rmind Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.302 2009/12/30 23:31:56 rmind Exp $");
#include "opt_ptrace.h"
#include "opt_compat_sunos.h"
@ -230,24 +230,19 @@ sigacts_poolpage_free(struct pool *pp, void *v)
struct sigacts *
sigactsinit(struct proc *pp, int share)
{
struct sigacts *ps, *ps2;
struct sigacts *ps = pp->p_sigacts, *ps2;
ps = pp->p_sigacts;
if (share) {
if (__predict_false(share)) {
atomic_inc_uint(&ps->sa_refcnt);
ps2 = ps;
} else {
ps2 = pool_cache_get(sigacts_cache, PR_WAITOK);
/* XXXAD get rid of this */
mutex_init(&ps2->sa_mutex, MUTEX_DEFAULT, IPL_SCHED);
mutex_enter(&ps->sa_mutex);
memcpy(&ps2->sa_sigdesc, ps->sa_sigdesc,
sizeof(ps2->sa_sigdesc));
mutex_exit(&ps->sa_mutex);
ps2->sa_refcnt = 1;
return ps;
}
ps2 = pool_cache_get(sigacts_cache, PR_WAITOK);
mutex_init(&ps2->sa_mutex, MUTEX_DEFAULT, IPL_SCHED);
ps2->sa_refcnt = 1;
mutex_enter(&ps->sa_mutex);
memcpy(ps2->sa_sigdesc, ps->sa_sigdesc, sizeof(ps2->sa_sigdesc));
mutex_exit(&ps->sa_mutex);
return ps2;
}
@ -259,15 +254,16 @@ sigactsinit(struct proc *pp, int share)
void
sigactsunshare(struct proc *p)
{
struct sigacts *ps, *oldps;
struct sigacts *ps, *oldps = p->p_sigacts;
oldps = p->p_sigacts;
if (oldps->sa_refcnt == 1)
if (__predict_true(oldps->sa_refcnt == 1))
return;
ps = pool_cache_get(sigacts_cache, PR_WAITOK);
/* XXXAD get rid of this */
mutex_init(&ps->sa_mutex, MUTEX_DEFAULT, IPL_SCHED);
memset(&ps->sa_sigdesc, 0, sizeof(ps->sa_sigdesc));
memset(ps->sa_sigdesc, 0, sizeof(ps->sa_sigdesc));
ps->sa_refcnt = 1;
p->p_sigacts = ps;
sigactsfree(oldps);
}