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. * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@ -66,7 +66,7 @@
*/ */
#include <sys/cdefs.h> #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_ptrace.h"
#include "opt_compat_sunos.h" #include "opt_compat_sunos.h"
@ -230,24 +230,19 @@ sigacts_poolpage_free(struct pool *pp, void *v)
struct sigacts * struct sigacts *
sigactsinit(struct proc *pp, int share) sigactsinit(struct proc *pp, int share)
{ {
struct sigacts *ps, *ps2; struct sigacts *ps = pp->p_sigacts, *ps2;
ps = pp->p_sigacts; if (__predict_false(share)) {
if (share) {
atomic_inc_uint(&ps->sa_refcnt); atomic_inc_uint(&ps->sa_refcnt);
ps2 = ps; return 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;
} }
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; return ps2;
} }
@ -259,15 +254,16 @@ sigactsinit(struct proc *pp, int share)
void void
sigactsunshare(struct proc *p) sigactsunshare(struct proc *p)
{ {
struct sigacts *ps, *oldps; struct sigacts *ps, *oldps = p->p_sigacts;
oldps = p->p_sigacts; if (__predict_true(oldps->sa_refcnt == 1))
if (oldps->sa_refcnt == 1)
return; return;
ps = pool_cache_get(sigacts_cache, PR_WAITOK); ps = pool_cache_get(sigacts_cache, PR_WAITOK);
/* XXXAD get rid of this */
mutex_init(&ps->sa_mutex, MUTEX_DEFAULT, IPL_SCHED); 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; p->p_sigacts = ps;
sigactsfree(oldps); sigactsfree(oldps);
} }