From ffb9a7ee3c4e01f8fc72f95a6c23bd5eb445091e Mon Sep 17 00:00:00 2001 From: rmind Date: Wed, 30 Dec 2009 23:31:56 +0000 Subject: [PATCH] sigactsunshare(): set reference count in a case of new sigacts allocation. Bug (e.g. memory leak) can happen when using clone(2) call. --- sys/kern/kern_sig.c | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 1af4b7bcd3bd..6811fcf77852 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -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 -__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); }