Fri Sep 9 18:24:20 2022 UTC ()
Pull up following revision(s) (requested by christos in ticket #1760):

	sys/kern/kern_core.c: revision 1.36

Don't forget to free the cred we just held.
Thanks to Chris J-D (chris at accessvector dot net)

While here, de-duplicate the mutex exit sequence.


(martin)
diff -r1.24 -r1.24.10.1 src/sys/kern/kern_core.c

cvs diff -r1.24 -r1.24.10.1 src/sys/kern/kern_core.c (expand / switch to unified diff)

--- src/sys/kern/kern_core.c 2016/07/07 06:55:43 1.24
+++ src/sys/kern/kern_core.c 2022/09/09 18:24:20 1.24.10.1
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: kern_core.c,v 1.24 2016/07/07 06:55:43 msaitoh Exp $ */ 1/* $NetBSD: kern_core.c,v 1.24.10.1 2022/09/09 18:24:20 martin Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1982, 1986, 1989, 1991, 1993 4 * Copyright (c) 1982, 1986, 1989, 1991, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * (c) UNIX System Laboratories, Inc. 6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed 7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph 8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc. 10 * the permission of UNIX System Laboratories, Inc.
11 * 11 *
12 * Redistribution and use in source and binary forms, with or without 12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions 13 * modification, are permitted provided that the following conditions
14 * are met: 14 * are met:
@@ -27,27 +27,27 @@ @@ -27,27 +27,27 @@
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE. 34 * SUCH DAMAGE.
35 * 35 *
36 * @(#)kern_sig.c 8.14 (Berkeley) 5/14/95 36 * @(#)kern_sig.c 8.14 (Berkeley) 5/14/95
37 */ 37 */
38 38
39#include <sys/cdefs.h> 39#include <sys/cdefs.h>
40__KERNEL_RCSID(0, "$NetBSD: kern_core.c,v 1.24 2016/07/07 06:55:43 msaitoh Exp $"); 40__KERNEL_RCSID(0, "$NetBSD: kern_core.c,v 1.24.10.1 2022/09/09 18:24:20 martin Exp $");
41 41
42#include <sys/param.h> 42#include <sys/param.h>
43#include <sys/vnode.h> 43#include <sys/vnode.h>
44#include <sys/namei.h> 44#include <sys/namei.h>
45#include <sys/acct.h> 45#include <sys/acct.h>
46#include <sys/file.h> 46#include <sys/file.h>
47#include <sys/stat.h> 47#include <sys/stat.h>
48#include <sys/proc.h> 48#include <sys/proc.h>
49#include <sys/exec.h> 49#include <sys/exec.h>
50#include <sys/filedesc.h> 50#include <sys/filedesc.h>
51#include <sys/kauth.h> 51#include <sys/kauth.h>
52#include <sys/module.h> 52#include <sys/module.h>
53 53
@@ -85,104 +85,98 @@ coredump_modcmd(modcmd_t cmd, void *arg) @@ -85,104 +85,98 @@ coredump_modcmd(modcmd_t cmd, void *arg)
85 } 85 }
86} 86}
87 87
88/* 88/*
89 * Dump core, into a file named "progname.core" or "core" (depending on the 89 * Dump core, into a file named "progname.core" or "core" (depending on the
90 * value of shortcorename), unless the process was setuid/setgid. 90 * value of shortcorename), unless the process was setuid/setgid.
91 */ 91 */
92static int 92static int
93coredump(struct lwp *l, const char *pattern) 93coredump(struct lwp *l, const char *pattern)
94{ 94{
95 struct vnode *vp; 95 struct vnode *vp;
96 struct proc *p; 96 struct proc *p;
97 struct vmspace *vm; 97 struct vmspace *vm;
98 kauth_cred_t cred; 98 kauth_cred_t cred = NULL;
99 struct pathbuf *pb; 99 struct pathbuf *pb;
100 struct nameidata nd; 100 struct nameidata nd;
101 struct vattr vattr; 101 struct vattr vattr;
102 struct coredump_iostate io; 102 struct coredump_iostate io;
103 struct plimit *lim; 103 struct plimit *lim;
104 int error, error1; 104 int error, error1;
105 char *name, *lastslash; 105 char *name, *lastslash;
106 106
107 name = PNBUF_GET(); 107 name = PNBUF_GET();
108 108
109 p = l->l_proc; 109 p = l->l_proc;
110 vm = p->p_vmspace; 110 vm = p->p_vmspace;
111 111
112 mutex_enter(proc_lock); /* p_session */ 112 mutex_enter(proc_lock); /* p_session */
113 mutex_enter(p->p_lock); 113 mutex_enter(p->p_lock);
114 114
115 /* 115 /*
116 * Refuse to core if the data + stack + user size is larger than 116 * Refuse to core if the data + stack + user size is larger than
117 * the core dump limit. XXX THIS IS WRONG, because of mapped 117 * the core dump limit. XXX THIS IS WRONG, because of mapped
118 * data. 118 * data.
119 */ 119 */
120 if (USPACE + ctob(vm->vm_dsize + vm->vm_ssize) >= 120 if (USPACE + ctob(vm->vm_dsize + vm->vm_ssize) >=
121 p->p_rlimit[RLIMIT_CORE].rlim_cur) { 121 p->p_rlimit[RLIMIT_CORE].rlim_cur) {
122 error = EFBIG; /* better error code? */ 122 error = EFBIG; /* better error code? */
123 mutex_exit(p->p_lock); 123 goto release;
124 mutex_exit(proc_lock); 
125 goto done; 
126 } 124 }
127 125
128 /* 126 /*
129 * It may well not be curproc, so grab a reference to its current 127 * It may well not be curproc, so grab a reference to its current
130 * credentials. 128 * credentials.
131 */ 129 */
132 kauth_cred_hold(p->p_cred); 130 kauth_cred_hold(p->p_cred);
133 cred = p->p_cred; 131 cred = p->p_cred;
134 132
135 /* 133 /*
136 * Make sure the process has not set-id, to prevent data leaks, 134 * Make sure the process has not set-id, to prevent data leaks,
137 * unless it was specifically requested to allow set-id coredumps. 135 * unless it was specifically requested to allow set-id coredumps.
138 */ 136 */
139 if (p->p_flag & PK_SUGID) { 137 if (p->p_flag & PK_SUGID) {
140 if (!security_setidcore_dump) { 138 if (!security_setidcore_dump) {
141 error = EPERM; 139 error = EPERM;
142 mutex_exit(p->p_lock); 140 goto release;
143 mutex_exit(proc_lock); 
144 goto done; 
145 } 141 }
146 pattern = security_setidcore_path; 142 pattern = security_setidcore_path;
147 } 143 }
148 144
149 /* Lock, as p_limit and pl_corename might change. */ 145 /* Lock, as p_limit and pl_corename might change. */
150 lim = p->p_limit; 146 lim = p->p_limit;
151 mutex_enter(&lim->pl_lock); 147 mutex_enter(&lim->pl_lock);
152 if (pattern == NULL) { 148 if (pattern == NULL) {
153 pattern = lim->pl_corename; 149 pattern = lim->pl_corename;
154 } 150 }
155 error = coredump_buildname(p, name, pattern, MAXPATHLEN); 151 error = coredump_buildname(p, name, pattern, MAXPATHLEN);
156 mutex_exit(&lim->pl_lock); 152 mutex_exit(&lim->pl_lock);
157 153
158 if (error) { 154 if (error)
159 mutex_exit(p->p_lock); 155 goto release;
160 mutex_exit(proc_lock); 
161 goto done; 
162 } 
163 156
164 /* 157 /*
165 * On a simple filename, see if the filesystem allow us to write 158 * On a simple filename, see if the filesystem allow us to write
166 * core dumps there. 159 * core dumps there.
167 */ 160 */
168 lastslash = strrchr(name, '/'); 161 lastslash = strrchr(name, '/');
169 if (!lastslash) { 162 if (!lastslash) {
170 vp = p->p_cwdi->cwdi_cdir; 163 vp = p->p_cwdi->cwdi_cdir;
171 if (vp->v_mount == NULL || 164 if (vp->v_mount == NULL ||
172 (vp->v_mount->mnt_flag & MNT_NOCOREDUMP) != 0) 165 (vp->v_mount->mnt_flag & MNT_NOCOREDUMP) != 0)
173 error = EPERM; 166 error = EPERM;
174 } 167 }
175 168
 169release:
176 mutex_exit(p->p_lock); 170 mutex_exit(p->p_lock);
177 mutex_exit(proc_lock); 171 mutex_exit(proc_lock);
178 if (error) 172 if (error)
179 goto done; 173 goto done;
180 174
181 /* 175 /*
182 * On a complex filename, see if the filesystem allow us to write 176 * On a complex filename, see if the filesystem allow us to write
183 * core dumps there. 177 * core dumps there.
184 * 178 *
185 * XXX: We should have an API that avoids double lookups 179 * XXX: We should have an API that avoids double lookups
186 */ 180 */
187 if (lastslash) { 181 if (lastslash) {
188 char c[2]; 182 char c[2];
@@ -250,26 +244,28 @@ coredump(struct lwp *l, const char *patt @@ -250,26 +244,28 @@ coredump(struct lwp *l, const char *patt
250 io.io_lwp = l; 244 io.io_lwp = l;
251 io.io_vp = vp; 245 io.io_vp = vp;
252 io.io_cred = cred; 246 io.io_cred = cred;
253 io.io_offset = 0; 247 io.io_offset = 0;
254 248
255 /* Now dump the actual core file. */ 249 /* Now dump the actual core file. */
256 error = (*p->p_execsw->es_coredump)(l, &io); 250 error = (*p->p_execsw->es_coredump)(l, &io);
257 out: 251 out:
258 VOP_UNLOCK(vp); 252 VOP_UNLOCK(vp);
259 error1 = vn_close(vp, FWRITE, cred); 253 error1 = vn_close(vp, FWRITE, cred);
260 if (error == 0) 254 if (error == 0)
261 error = error1; 255 error = error1;
262done: 256done:
 257 if (cred != NULL)
 258 kauth_cred_free(cred);
263 if (name != NULL) 259 if (name != NULL)
264 PNBUF_PUT(name); 260 PNBUF_PUT(name);
265 return error; 261 return error;
266} 262}
267 263
268static int 264static int
269coredump_buildname(struct proc *p, char *dst, const char *src, size_t len) 265coredump_buildname(struct proc *p, char *dst, const char *src, size_t len)
270{ 266{
271 const char *s; 267 const char *s;
272 char *d, *end; 268 char *d, *end;
273 int i; 269 int i;
274 270
275 KASSERT(mutex_owned(proc_lock)); 271 KASSERT(mutex_owned(proc_lock));