Module Name: src Committed By: rmind Date: Wed Dec 30 23:31:56 UTC 2009
Modified Files: src/sys/kern: kern_sig.c Log Message: sigactsunshare(): set reference count in a case of new sigacts allocation. Bug (e.g. memory leak) can happen when using clone(2) call. To generate a diff of this commit: cvs rdiff -u -r1.301 -r1.302 src/sys/kern/kern_sig.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/kern_sig.c diff -u src/sys/kern/kern_sig.c:1.301 src/sys/kern/kern_sig.c:1.302 --- src/sys/kern/kern_sig.c:1.301 Sun Dec 20 04:49:09 2009 +++ src/sys/kern/kern_sig.c Wed Dec 30 23:31:56 2009 @@ -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 @@ 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 @@ 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); }