Wed Apr 27 06:22:11 2011 UTC ()
Simplify previous: the original code was mostly correct but relied on
"register_t" being signed.


(martin)
diff -r1.112 -r1.113 src/sys/kern/kern_prot.c

cvs diff -r1.112 -r1.113 src/sys/kern/kern_prot.c (switch to unified diff)

--- src/sys/kern/kern_prot.c 2011/04/26 19:58:12 1.112
+++ src/sys/kern/kern_prot.c 2011/04/27 06:22:11 1.113
@@ -1,629 +1,627 @@ @@ -1,629 +1,627 @@
1/* $NetBSD: kern_prot.c,v 1.112 2011/04/26 19:58:12 martin Exp $ */ 1/* $NetBSD: kern_prot.c,v 1.113 2011/04/27 06:22:11 martin Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993 4 * Copyright (c) 1982, 1986, 1989, 1990, 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:
15 * 1. Redistributions of source code must retain the above copyright 15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer. 16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright 17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the 18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution. 19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors 20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software 21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission. 22 * without specific prior written permission.
23 * 23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
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_prot.c 8.9 (Berkeley) 2/14/95 36 * @(#)kern_prot.c 8.9 (Berkeley) 2/14/95
37 */ 37 */
38 38
39/* 39/*
40 * System calls related to processes and protection 40 * System calls related to processes and protection
41 */ 41 */
42 42
43#include <sys/cdefs.h> 43#include <sys/cdefs.h>
44__KERNEL_RCSID(0, "$NetBSD: kern_prot.c,v 1.112 2011/04/26 19:58:12 martin Exp $"); 44__KERNEL_RCSID(0, "$NetBSD: kern_prot.c,v 1.113 2011/04/27 06:22:11 martin Exp $");
45 45
46#include "opt_compat_43.h" 46#include "opt_compat_43.h"
47 47
48#include <sys/param.h> 48#include <sys/param.h>
49#include <sys/acct.h> 49#include <sys/acct.h>
50#include <sys/systm.h> 50#include <sys/systm.h>
51#include <sys/ucred.h> 51#include <sys/ucred.h>
52#include <sys/proc.h> 52#include <sys/proc.h>
53#include <sys/timeb.h> 53#include <sys/timeb.h>
54#include <sys/times.h> 54#include <sys/times.h>
55#include <sys/pool.h> 55#include <sys/pool.h>
56#include <sys/prot.h> 56#include <sys/prot.h>
57#include <sys/syslog.h> 57#include <sys/syslog.h>
58#include <sys/uidinfo.h> 58#include <sys/uidinfo.h>
59#include <sys/kauth.h> 59#include <sys/kauth.h>
60 60
61#include <sys/mount.h> 61#include <sys/mount.h>
62#include <sys/syscallargs.h> 62#include <sys/syscallargs.h>
63 63
64int sys_getpid(struct lwp *, const void *, register_t *); 64int sys_getpid(struct lwp *, const void *, register_t *);
65int sys_getpid_with_ppid(struct lwp *, const void *, register_t *); 65int sys_getpid_with_ppid(struct lwp *, const void *, register_t *);
66int sys_getuid(struct lwp *, const void *, register_t *); 66int sys_getuid(struct lwp *, const void *, register_t *);
67int sys_getuid_with_euid(struct lwp *, const void *, register_t *); 67int sys_getuid_with_euid(struct lwp *, const void *, register_t *);
68int sys_getgid(struct lwp *, const void *, register_t *); 68int sys_getgid(struct lwp *, const void *, register_t *);
69int sys_getgid_with_egid(struct lwp *, const void *, register_t *); 69int sys_getgid_with_egid(struct lwp *, const void *, register_t *);
70 70
71/* ARGSUSED */ 71/* ARGSUSED */
72int 72int
73sys_getpid(struct lwp *l, const void *v, register_t *retval) 73sys_getpid(struct lwp *l, const void *v, register_t *retval)
74{ 74{
75 struct proc *p = l->l_proc; 75 struct proc *p = l->l_proc;
76 76
77 *retval = p->p_pid; 77 *retval = p->p_pid;
78 return (0); 78 return (0);
79} 79}
80 80
81/* ARGSUSED */ 81/* ARGSUSED */
82int 82int
83sys_getpid_with_ppid(struct lwp *l, const void *v, register_t *retval) 83sys_getpid_with_ppid(struct lwp *l, const void *v, register_t *retval)
84{ 84{
85 struct proc *p = l->l_proc; 85 struct proc *p = l->l_proc;
86 86
87 retval[0] = p->p_pid; 87 retval[0] = p->p_pid;
88 retval[1] = p->p_ppid; 88 retval[1] = p->p_ppid;
89 return (0); 89 return (0);
90} 90}
91 91
92/* ARGSUSED */ 92/* ARGSUSED */
93int 93int
94sys_getppid(struct lwp *l, const void *v, register_t *retval) 94sys_getppid(struct lwp *l, const void *v, register_t *retval)
95{ 95{
96 struct proc *p = l->l_proc; 96 struct proc *p = l->l_proc;
97 97
98 *retval = p->p_ppid; 98 *retval = p->p_ppid;
99 return (0); 99 return (0);
100} 100}
101 101
102/* Get process group ID; note that POSIX getpgrp takes no parameter */ 102/* Get process group ID; note that POSIX getpgrp takes no parameter */
103int 103int
104sys_getpgrp(struct lwp *l, const void *v, register_t *retval) 104sys_getpgrp(struct lwp *l, const void *v, register_t *retval)
105{ 105{
106 struct proc *p = l->l_proc; 106 struct proc *p = l->l_proc;
107 107
108 mutex_enter(proc_lock); 108 mutex_enter(proc_lock);
109 *retval = p->p_pgrp->pg_id; 109 *retval = p->p_pgrp->pg_id;
110 mutex_exit(proc_lock); 110 mutex_exit(proc_lock);
111 return (0); 111 return (0);
112} 112}
113 113
114/* 114/*
115 * Return the process group ID of the session leader (session ID) 115 * Return the process group ID of the session leader (session ID)
116 * for the specified process. 116 * for the specified process.
117 */ 117 */
118int 118int
119sys_getsid(struct lwp *l, const struct sys_getsid_args *uap, register_t *retval) 119sys_getsid(struct lwp *l, const struct sys_getsid_args *uap, register_t *retval)
120{ 120{
121 /* { 121 /* {
122 syscalldarg(pid_t) pid; 122 syscalldarg(pid_t) pid;
123 } */ 123 } */
124 pid_t pid = SCARG(uap, pid); 124 pid_t pid = SCARG(uap, pid);
125 struct proc *p; 125 struct proc *p;
126 int error = 0; 126 int error = 0;
127 127
128 mutex_enter(proc_lock); 128 mutex_enter(proc_lock);
129 if (pid == 0) 129 if (pid == 0)
130 *retval = l->l_proc->p_session->s_sid; 130 *retval = l->l_proc->p_session->s_sid;
131 else if ((p = proc_find(pid)) != NULL) 131 else if ((p = proc_find(pid)) != NULL)
132 *retval = p->p_session->s_sid; 132 *retval = p->p_session->s_sid;
133 else 133 else
134 error = ESRCH; 134 error = ESRCH;
135 mutex_exit(proc_lock); 135 mutex_exit(proc_lock);
136 136
137 return error; 137 return error;
138} 138}
139 139
140int 140int
141sys_getpgid(struct lwp *l, const struct sys_getpgid_args *uap, register_t *retval) 141sys_getpgid(struct lwp *l, const struct sys_getpgid_args *uap, register_t *retval)
142{ 142{
143 /* { 143 /* {
144 syscallarg(pid_t) pid; 144 syscallarg(pid_t) pid;
145 } */ 145 } */
146 pid_t pid = SCARG(uap, pid); 146 pid_t pid = SCARG(uap, pid);
147 struct proc *p; 147 struct proc *p;
148 int error = 0; 148 int error = 0;
149 149
150 mutex_enter(proc_lock); 150 mutex_enter(proc_lock);
151 if (pid == 0) 151 if (pid == 0)
152 *retval = l->l_proc->p_pgid; 152 *retval = l->l_proc->p_pgid;
153 else if ((p = proc_find(pid)) != NULL) 153 else if ((p = proc_find(pid)) != NULL)
154 *retval = p->p_pgid; 154 *retval = p->p_pgid;
155 else 155 else
156 error = ESRCH; 156 error = ESRCH;
157 mutex_exit(proc_lock); 157 mutex_exit(proc_lock);
158 158
159 return error; 159 return error;
160} 160}
161 161
162/* ARGSUSED */ 162/* ARGSUSED */
163int 163int
164sys_getuid(struct lwp *l, const void *v, register_t *retval) 164sys_getuid(struct lwp *l, const void *v, register_t *retval)
165{ 165{
166 166
167 *retval = kauth_cred_getuid(l->l_cred); 167 *retval = kauth_cred_getuid(l->l_cred);
168 return (0); 168 return (0);
169} 169}
170 170
171/* ARGSUSED */ 171/* ARGSUSED */
172int 172int
173sys_getuid_with_euid(struct lwp *l, const void *v, register_t *retval) 173sys_getuid_with_euid(struct lwp *l, const void *v, register_t *retval)
174{ 174{
175 175
176 retval[0] = kauth_cred_getuid(l->l_cred); 176 retval[0] = kauth_cred_getuid(l->l_cred);
177 retval[1] = kauth_cred_geteuid(l->l_cred); 177 retval[1] = kauth_cred_geteuid(l->l_cred);
178 return (0); 178 return (0);
179} 179}
180 180
181/* ARGSUSED */ 181/* ARGSUSED */
182int 182int
183sys_geteuid(struct lwp *l, const void *v, register_t *retval) 183sys_geteuid(struct lwp *l, const void *v, register_t *retval)
184{ 184{
185 185
186 *retval = kauth_cred_geteuid(l->l_cred); 186 *retval = kauth_cred_geteuid(l->l_cred);
187 return (0); 187 return (0);
188} 188}
189 189
190/* ARGSUSED */ 190/* ARGSUSED */
191int 191int
192sys_getgid(struct lwp *l, const void *v, register_t *retval) 192sys_getgid(struct lwp *l, const void *v, register_t *retval)
193{ 193{
194 194
195 *retval = kauth_cred_getgid(l->l_cred); 195 *retval = kauth_cred_getgid(l->l_cred);
196 return (0); 196 return (0);
197} 197}
198 198
199/* ARGSUSED */ 199/* ARGSUSED */
200int 200int
201sys_getgid_with_egid(struct lwp *l, const void *v, register_t *retval) 201sys_getgid_with_egid(struct lwp *l, const void *v, register_t *retval)
202{ 202{
203 203
204 retval[0] = kauth_cred_getgid(l->l_cred); 204 retval[0] = kauth_cred_getgid(l->l_cred);
205 retval[1] = kauth_cred_getegid(l->l_cred); 205 retval[1] = kauth_cred_getegid(l->l_cred);
206 return (0); 206 return (0);
207} 207}
208 208
209/* 209/*
210 * Get effective group ID. The "egid" is groups[0], and could be obtained 210 * Get effective group ID. The "egid" is groups[0], and could be obtained
211 * via getgroups. This syscall exists because it is somewhat painful to do 211 * via getgroups. This syscall exists because it is somewhat painful to do
212 * correctly in a library function. 212 * correctly in a library function.
213 */ 213 */
214/* ARGSUSED */ 214/* ARGSUSED */
215int 215int
216sys_getegid(struct lwp *l, const void *v, register_t *retval) 216sys_getegid(struct lwp *l, const void *v, register_t *retval)
217{ 217{
218 218
219 *retval = kauth_cred_getegid(l->l_cred); 219 *retval = kauth_cred_getegid(l->l_cred);
220 return (0); 220 return (0);
221} 221}
222 222
223int 223int
224sys_getgroups(struct lwp *l, const struct sys_getgroups_args *uap, register_t *retval) 224sys_getgroups(struct lwp *l, const struct sys_getgroups_args *uap, register_t *retval)
225{ 225{
226 /* { 226 /* {
227 syscallarg(int) gidsetsize; 227 syscallarg(int) gidsetsize;
228 syscallarg(gid_t *) gidset; 228 syscallarg(gid_t *) gidset;
229 } */ 229 } */
230 230
231 *retval = kauth_cred_ngroups(l->l_cred); 231 *retval = kauth_cred_ngroups(l->l_cred);
232 if (SCARG(uap, gidsetsize) == 0) 232 if (SCARG(uap, gidsetsize) == 0)
233 return 0; 233 return 0;
234 if (SCARG(uap, gidsetsize) < 0) 234 if (SCARG(uap, gidsetsize) < (int)*retval)
235 return EINVAL; 
236 if (SCARG(uap, gidsetsize) < *retval) 
237 return EINVAL; 235 return EINVAL;
238 236
239 return kauth_cred_getgroups(l->l_cred, SCARG(uap, gidset), *retval, 237 return kauth_cred_getgroups(l->l_cred, SCARG(uap, gidset), *retval,
240 UIO_USERSPACE); 238 UIO_USERSPACE);
241} 239}
242 240
243int 241int
244sys_setsid(struct lwp *l, const void *v, register_t *retval) 242sys_setsid(struct lwp *l, const void *v, register_t *retval)
245{ 243{
246 struct proc *p = l->l_proc; 244 struct proc *p = l->l_proc;
247 int error; 245 int error;
248 246
249 error = proc_enterpgrp(p, p->p_pid, p->p_pid, true); 247 error = proc_enterpgrp(p, p->p_pid, p->p_pid, true);
250 *retval = p->p_pid; 248 *retval = p->p_pid;
251 return (error); 249 return (error);
252} 250}
253 251
254 252
255/* 253/*
256 * set process group (setpgid/old setpgrp) 254 * set process group (setpgid/old setpgrp)
257 * 255 *
258 * caller does setpgid(targpid, targpgid) 256 * caller does setpgid(targpid, targpgid)
259 * 257 *
260 * pgid must be in valid range (EINVAL) 258 * pgid must be in valid range (EINVAL)
261 * pid must be caller or child of caller (ESRCH) 259 * pid must be caller or child of caller (ESRCH)
262 * if a child 260 * if a child
263 * pid must be in same session (EPERM) 261 * pid must be in same session (EPERM)
264 * pid can't have done an exec (EACCES) 262 * pid can't have done an exec (EACCES)
265 * if pgid != pid 263 * if pgid != pid
266 * there must exist some pid in same session having pgid (EPERM) 264 * there must exist some pid in same session having pgid (EPERM)
267 * pid must not be session leader (EPERM) 265 * pid must not be session leader (EPERM)
268 * 266 *
269 * Permission checks now in proc_enterpgrp() 267 * Permission checks now in proc_enterpgrp()
270 */ 268 */
271int 269int
272sys_setpgid(struct lwp *l, const struct sys_setpgid_args *uap, 270sys_setpgid(struct lwp *l, const struct sys_setpgid_args *uap,
273 register_t *retval) 271 register_t *retval)
274{ 272{
275 /* { 273 /* {
276 syscallarg(int) pid; 274 syscallarg(int) pid;
277 syscallarg(int) pgid; 275 syscallarg(int) pgid;
278 } */ 276 } */
279 struct proc *p = l->l_proc; 277 struct proc *p = l->l_proc;
280 pid_t targp, pgid; 278 pid_t targp, pgid;
281 279
282 if (SCARG(uap, pgid) < 0) 280 if (SCARG(uap, pgid) < 0)
283 return EINVAL; 281 return EINVAL;
284 if ((targp = SCARG(uap, pid)) == 0) 282 if ((targp = SCARG(uap, pid)) == 0)
285 targp = p->p_pid; 283 targp = p->p_pid;
286 if ((pgid = SCARG(uap, pgid)) == 0) 284 if ((pgid = SCARG(uap, pgid)) == 0)
287 pgid = targp; 285 pgid = targp;
288 286
289 return proc_enterpgrp(p, targp, pgid, false); 287 return proc_enterpgrp(p, targp, pgid, false);
290} 288}
291 289
292/* 290/*
293 * Set real, effective and saved uids to the requested values. 291 * Set real, effective and saved uids to the requested values.
294 * non-root callers can only ever change uids to values that match 292 * non-root callers can only ever change uids to values that match
295 * one of the processes current uid values. 293 * one of the processes current uid values.
296 * This is further restricted by the flags argument. 294 * This is further restricted by the flags argument.
297 */ 295 */
298 296
299int 297int
300do_setresuid(struct lwp *l, uid_t r, uid_t e, uid_t sv, u_int flags) 298do_setresuid(struct lwp *l, uid_t r, uid_t e, uid_t sv, u_int flags)
301{ 299{
302 struct proc *p = l->l_proc; 300 struct proc *p = l->l_proc;
303 kauth_cred_t cred, ncred; 301 kauth_cred_t cred, ncred;
304 302
305 ncred = kauth_cred_alloc(); 303 ncred = kauth_cred_alloc();
306 304
307 /* Get a write lock on the process credential. */ 305 /* Get a write lock on the process credential. */
308 proc_crmod_enter(); 306 proc_crmod_enter();
309 cred = p->p_cred; 307 cred = p->p_cred;
310 308
311 /* 309 /*
312 * Check that the new value is one of the allowed existing values, 310 * Check that the new value is one of the allowed existing values,
313 * or that we have root privilege. 311 * or that we have root privilege.
314 */ 312 */
315 if ((r != -1 313 if ((r != -1
316 && !((flags & ID_R_EQ_R) && r == kauth_cred_getuid(cred)) 314 && !((flags & ID_R_EQ_R) && r == kauth_cred_getuid(cred))
317 && !((flags & ID_R_EQ_E) && r == kauth_cred_geteuid(cred)) 315 && !((flags & ID_R_EQ_E) && r == kauth_cred_geteuid(cred))
318 && !((flags & ID_R_EQ_S) && r == kauth_cred_getsvuid(cred))) || 316 && !((flags & ID_R_EQ_S) && r == kauth_cred_getsvuid(cred))) ||
319 (e != -1 317 (e != -1
320 && !((flags & ID_E_EQ_R) && e == kauth_cred_getuid(cred)) 318 && !((flags & ID_E_EQ_R) && e == kauth_cred_getuid(cred))
321 && !((flags & ID_E_EQ_E) && e == kauth_cred_geteuid(cred)) 319 && !((flags & ID_E_EQ_E) && e == kauth_cred_geteuid(cred))
322 && !((flags & ID_E_EQ_S) && e == kauth_cred_getsvuid(cred))) || 320 && !((flags & ID_E_EQ_S) && e == kauth_cred_getsvuid(cred))) ||
323 (sv != -1 321 (sv != -1
324 && !((flags & ID_S_EQ_R) && sv == kauth_cred_getuid(cred)) 322 && !((flags & ID_S_EQ_R) && sv == kauth_cred_getuid(cred))
325 && !((flags & ID_S_EQ_E) && sv == kauth_cred_geteuid(cred)) 323 && !((flags & ID_S_EQ_E) && sv == kauth_cred_geteuid(cred))
326 && !((flags & ID_S_EQ_S) && sv == kauth_cred_getsvuid(cred)))) { 324 && !((flags & ID_S_EQ_S) && sv == kauth_cred_getsvuid(cred)))) {
327 int error; 325 int error;
328 326
329 error = kauth_authorize_process(cred, KAUTH_PROCESS_SETID, 327 error = kauth_authorize_process(cred, KAUTH_PROCESS_SETID,
330 p, NULL, NULL, NULL); 328 p, NULL, NULL, NULL);
331 if (error != 0) { 329 if (error != 0) {
332 proc_crmod_leave(cred, ncred, false); 330 proc_crmod_leave(cred, ncred, false);
333 return error; 331 return error;
334 } 332 }
335 } 333 }
336 334
337 /* If nothing has changed, short circuit the request */ 335 /* If nothing has changed, short circuit the request */
338 if ((r == -1 || r == kauth_cred_getuid(cred)) 336 if ((r == -1 || r == kauth_cred_getuid(cred))
339 && (e == -1 || e == kauth_cred_geteuid(cred)) 337 && (e == -1 || e == kauth_cred_geteuid(cred))
340 && (sv == -1 || sv == kauth_cred_getsvuid(cred))) { 338 && (sv == -1 || sv == kauth_cred_getsvuid(cred))) {
341 proc_crmod_leave(cred, ncred, false); 339 proc_crmod_leave(cred, ncred, false);
342 return 0; 340 return 0;
343 } 341 }
344 342
345 kauth_cred_clone(cred, ncred); 343 kauth_cred_clone(cred, ncred);
346 344
347 if (r != -1 && r != kauth_cred_getuid(ncred)) { 345 if (r != -1 && r != kauth_cred_getuid(ncred)) {
348 /* Update count of processes for this user */ 346 /* Update count of processes for this user */
349 (void)chgproccnt(kauth_cred_getuid(ncred), -1); 347 (void)chgproccnt(kauth_cred_getuid(ncred), -1);
350 (void)chgproccnt(r, 1); 348 (void)chgproccnt(r, 1);
351 kauth_cred_setuid(ncred, r); 349 kauth_cred_setuid(ncred, r);
352 } 350 }
353 if (sv != -1) 351 if (sv != -1)
354 kauth_cred_setsvuid(ncred, sv); 352 kauth_cred_setsvuid(ncred, sv);
355 if (e != -1) 353 if (e != -1)
356 kauth_cred_seteuid(ncred, e); 354 kauth_cred_seteuid(ncred, e);
357 355
358 /* Broadcast our credentials to the process and other LWPs. */ 356 /* Broadcast our credentials to the process and other LWPs. */
359 proc_crmod_leave(ncred, cred, true); 357 proc_crmod_leave(ncred, cred, true);
360 358
361 return 0; 359 return 0;
362} 360}
363 361
364/* 362/*
365 * Set real, effective and saved gids to the requested values. 363 * Set real, effective and saved gids to the requested values.
366 * non-root callers can only ever change gids to values that match 364 * non-root callers can only ever change gids to values that match
367 * one of the processes current gid values. 365 * one of the processes current gid values.
368 * This is further restricted by the flags argument. 366 * This is further restricted by the flags argument.
369 */ 367 */
370 368
371int 369int
372do_setresgid(struct lwp *l, gid_t r, gid_t e, gid_t sv, u_int flags) 370do_setresgid(struct lwp *l, gid_t r, gid_t e, gid_t sv, u_int flags)
373{ 371{
374 struct proc *p = l->l_proc; 372 struct proc *p = l->l_proc;
375 kauth_cred_t cred, ncred; 373 kauth_cred_t cred, ncred;
376 374
377 ncred = kauth_cred_alloc(); 375 ncred = kauth_cred_alloc();
378 376
379 /* Get a write lock on the process credential. */ 377 /* Get a write lock on the process credential. */
380 proc_crmod_enter(); 378 proc_crmod_enter();
381 cred = p->p_cred; 379 cred = p->p_cred;
382 380
383 /* 381 /*
384 * check new value is one of the allowed existing values. 382 * check new value is one of the allowed existing values.
385 * otherwise, check if we have root privilege. 383 * otherwise, check if we have root privilege.
386 */ 384 */
387 if ((r != -1 385 if ((r != -1
388 && !((flags & ID_R_EQ_R) && r == kauth_cred_getgid(cred)) 386 && !((flags & ID_R_EQ_R) && r == kauth_cred_getgid(cred))
389 && !((flags & ID_R_EQ_E) && r == kauth_cred_getegid(cred)) 387 && !((flags & ID_R_EQ_E) && r == kauth_cred_getegid(cred))
390 && !((flags & ID_R_EQ_S) && r == kauth_cred_getsvgid(cred))) || 388 && !((flags & ID_R_EQ_S) && r == kauth_cred_getsvgid(cred))) ||
391 (e != -1 389 (e != -1
392 && !((flags & ID_E_EQ_R) && e == kauth_cred_getgid(cred)) 390 && !((flags & ID_E_EQ_R) && e == kauth_cred_getgid(cred))
393 && !((flags & ID_E_EQ_E) && e == kauth_cred_getegid(cred)) 391 && !((flags & ID_E_EQ_E) && e == kauth_cred_getegid(cred))
394 && !((flags & ID_E_EQ_S) && e == kauth_cred_getsvgid(cred))) || 392 && !((flags & ID_E_EQ_S) && e == kauth_cred_getsvgid(cred))) ||
395 (sv != -1 393 (sv != -1
396 && !((flags & ID_S_EQ_R) && sv == kauth_cred_getgid(cred)) 394 && !((flags & ID_S_EQ_R) && sv == kauth_cred_getgid(cred))
397 && !((flags & ID_S_EQ_E) && sv == kauth_cred_getegid(cred)) 395 && !((flags & ID_S_EQ_E) && sv == kauth_cred_getegid(cred))
398 && !((flags & ID_S_EQ_S) && sv == kauth_cred_getsvgid(cred)))) { 396 && !((flags & ID_S_EQ_S) && sv == kauth_cred_getsvgid(cred)))) {
399 int error; 397 int error;
400 398
401 error = kauth_authorize_process(cred, KAUTH_PROCESS_SETID, 399 error = kauth_authorize_process(cred, KAUTH_PROCESS_SETID,
402 p, NULL, NULL, NULL); 400 p, NULL, NULL, NULL);
403 if (error != 0) { 401 if (error != 0) {
404 proc_crmod_leave(cred, ncred, false); 402 proc_crmod_leave(cred, ncred, false);
405 return error; 403 return error;
406 } 404 }
407 } 405 }
408 406
409 /* If nothing has changed, short circuit the request */ 407 /* If nothing has changed, short circuit the request */
410 if ((r == -1 || r == kauth_cred_getgid(cred)) 408 if ((r == -1 || r == kauth_cred_getgid(cred))
411 && (e == -1 || e == kauth_cred_getegid(cred)) 409 && (e == -1 || e == kauth_cred_getegid(cred))
412 && (sv == -1 || sv == kauth_cred_getsvgid(cred))) { 410 && (sv == -1 || sv == kauth_cred_getsvgid(cred))) {
413 proc_crmod_leave(cred, ncred, false); 411 proc_crmod_leave(cred, ncred, false);
414 return 0; 412 return 0;
415 } 413 }
416 414
417 kauth_cred_clone(cred, ncred); 415 kauth_cred_clone(cred, ncred);
418 416
419 if (r != -1) 417 if (r != -1)
420 kauth_cred_setgid(ncred, r); 418 kauth_cred_setgid(ncred, r);
421 if (sv != -1) 419 if (sv != -1)
422 kauth_cred_setsvgid(ncred, sv); 420 kauth_cred_setsvgid(ncred, sv);
423 if (e != -1) 421 if (e != -1)
424 kauth_cred_setegid(ncred, e); 422 kauth_cred_setegid(ncred, e);
425 423
426 /* Broadcast our credentials to the process and other LWPs. */ 424 /* Broadcast our credentials to the process and other LWPs. */
427 proc_crmod_leave(ncred, cred, true); 425 proc_crmod_leave(ncred, cred, true);
428 426
429 return 0; 427 return 0;
430} 428}
431 429
432/* ARGSUSED */ 430/* ARGSUSED */
433int 431int
434sys_setuid(struct lwp *l, const struct sys_setuid_args *uap, register_t *retval) 432sys_setuid(struct lwp *l, const struct sys_setuid_args *uap, register_t *retval)
435{ 433{
436 /* { 434 /* {
437 syscallarg(uid_t) uid; 435 syscallarg(uid_t) uid;
438 } */ 436 } */
439 uid_t uid = SCARG(uap, uid); 437 uid_t uid = SCARG(uap, uid);
440 438
441 return do_setresuid(l, uid, uid, uid, 439 return do_setresuid(l, uid, uid, uid,
442 ID_R_EQ_R | ID_E_EQ_R | ID_S_EQ_R); 440 ID_R_EQ_R | ID_E_EQ_R | ID_S_EQ_R);
443} 441}
444 442
445/* ARGSUSED */ 443/* ARGSUSED */
446int 444int
447sys_seteuid(struct lwp *l, const struct sys_seteuid_args *uap, register_t *retval) 445sys_seteuid(struct lwp *l, const struct sys_seteuid_args *uap, register_t *retval)
448{ 446{
449 /* { 447 /* {
450 syscallarg(uid_t) euid; 448 syscallarg(uid_t) euid;
451 } */ 449 } */
452 450
453 return do_setresuid(l, -1, SCARG(uap, euid), -1, ID_E_EQ_R | ID_E_EQ_S); 451 return do_setresuid(l, -1, SCARG(uap, euid), -1, ID_E_EQ_R | ID_E_EQ_S);
454} 452}
455 453
456int 454int
457sys_setreuid(struct lwp *l, const struct sys_setreuid_args *uap, register_t *retval) 455sys_setreuid(struct lwp *l, const struct sys_setreuid_args *uap, register_t *retval)
458{ 456{
459 /* { 457 /* {
460 syscallarg(uid_t) ruid; 458 syscallarg(uid_t) ruid;
461 syscallarg(uid_t) euid; 459 syscallarg(uid_t) euid;
462 } */ 460 } */
463 kauth_cred_t cred = l->l_cred; 461 kauth_cred_t cred = l->l_cred;
464 uid_t ruid, euid, svuid; 462 uid_t ruid, euid, svuid;
465 463
466 ruid = SCARG(uap, ruid); 464 ruid = SCARG(uap, ruid);
467 euid = SCARG(uap, euid); 465 euid = SCARG(uap, euid);
468 466
469 if (ruid == -1) 467 if (ruid == -1)
470 ruid = kauth_cred_getuid(cred); 468 ruid = kauth_cred_getuid(cred);
471 if (euid == -1) 469 if (euid == -1)
472 euid = kauth_cred_geteuid(cred); 470 euid = kauth_cred_geteuid(cred);
473 471
474 /* Saved uid is set to the new euid if the ruid changed */ 472 /* Saved uid is set to the new euid if the ruid changed */
475 svuid = (ruid == kauth_cred_getuid(cred)) ? -1 : euid; 473 svuid = (ruid == kauth_cred_getuid(cred)) ? -1 : euid;
476 474
477 return do_setresuid(l, ruid, euid, svuid, 475 return do_setresuid(l, ruid, euid, svuid,
478 ID_R_EQ_R | ID_R_EQ_E | 476 ID_R_EQ_R | ID_R_EQ_E |
479 ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S | 477 ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S |
480 ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S); 478 ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S);
481} 479}
482 480
483/* ARGSUSED */ 481/* ARGSUSED */
484int 482int
485sys_setgid(struct lwp *l, const struct sys_setgid_args *uap, register_t *retval) 483sys_setgid(struct lwp *l, const struct sys_setgid_args *uap, register_t *retval)
486{ 484{
487 /* { 485 /* {
488 syscallarg(gid_t) gid; 486 syscallarg(gid_t) gid;
489 } */ 487 } */
490 gid_t gid = SCARG(uap, gid); 488 gid_t gid = SCARG(uap, gid);
491 489
492 return do_setresgid(l, gid, gid, gid, 490 return do_setresgid(l, gid, gid, gid,
493 ID_R_EQ_R | ID_E_EQ_R | ID_S_EQ_R); 491 ID_R_EQ_R | ID_E_EQ_R | ID_S_EQ_R);
494} 492}
495 493
496/* ARGSUSED */ 494/* ARGSUSED */
497int 495int
498sys_setegid(struct lwp *l, const struct sys_setegid_args *uap, register_t *retval) 496sys_setegid(struct lwp *l, const struct sys_setegid_args *uap, register_t *retval)
499{ 497{
500 /* { 498 /* {
501 syscallarg(gid_t) egid; 499 syscallarg(gid_t) egid;
502 } */ 500 } */
503 501
504 return do_setresgid(l, -1, SCARG(uap, egid), -1, ID_E_EQ_R | ID_E_EQ_S); 502 return do_setresgid(l, -1, SCARG(uap, egid), -1, ID_E_EQ_R | ID_E_EQ_S);
505} 503}
506 504
507int 505int
508sys_setregid(struct lwp *l, const struct sys_setregid_args *uap, register_t *retval) 506sys_setregid(struct lwp *l, const struct sys_setregid_args *uap, register_t *retval)
509{ 507{
510 /* { 508 /* {
511 syscallarg(gid_t) rgid; 509 syscallarg(gid_t) rgid;
512 syscallarg(gid_t) egid; 510 syscallarg(gid_t) egid;
513 } */ 511 } */
514 kauth_cred_t cred = l->l_cred; 512 kauth_cred_t cred = l->l_cred;
515 gid_t rgid, egid, svgid; 513 gid_t rgid, egid, svgid;
516 514
517 rgid = SCARG(uap, rgid); 515 rgid = SCARG(uap, rgid);
518 egid = SCARG(uap, egid); 516 egid = SCARG(uap, egid);
519 517
520 if (rgid == -1) 518 if (rgid == -1)
521 rgid = kauth_cred_getgid(cred); 519 rgid = kauth_cred_getgid(cred);
522 if (egid == -1) 520 if (egid == -1)
523 egid = kauth_cred_getegid(cred); 521 egid = kauth_cred_getegid(cred);
524 522
525 /* Saved gid is set to the new egid if the rgid changed */ 523 /* Saved gid is set to the new egid if the rgid changed */
526 svgid = rgid == kauth_cred_getgid(cred) ? -1 : egid; 524 svgid = rgid == kauth_cred_getgid(cred) ? -1 : egid;
527 525
528 return do_setresgid(l, rgid, egid, svgid, 526 return do_setresgid(l, rgid, egid, svgid,
529 ID_R_EQ_R | ID_R_EQ_E | 527 ID_R_EQ_R | ID_R_EQ_E |
530 ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S | 528 ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S |
531 ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S); 529 ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S);
532} 530}
533 531
534int 532int
535sys_issetugid(struct lwp *l, const void *v, register_t *retval) 533sys_issetugid(struct lwp *l, const void *v, register_t *retval)
536{ 534{
537 struct proc *p = l->l_proc; 535 struct proc *p = l->l_proc;
538 536
539 /* 537 /*
540 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, 538 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
541 * we use PK_SUGID because we consider changing the owners as 539 * we use PK_SUGID because we consider changing the owners as
542 * "tainting" as well. 540 * "tainting" as well.
543 * This is significant for procs that start as root and "become" 541 * This is significant for procs that start as root and "become"
544 * a user without an exec - programs cannot know *everything* 542 * a user without an exec - programs cannot know *everything*
545 * that libc *might* have put in their data segment. 543 * that libc *might* have put in their data segment.
546 */ 544 */
547 *retval = (p->p_flag & PK_SUGID) != 0; 545 *retval = (p->p_flag & PK_SUGID) != 0;
548 return (0); 546 return (0);
549} 547}
550 548
551/* ARGSUSED */ 549/* ARGSUSED */
552int 550int
553sys_setgroups(struct lwp *l, const struct sys_setgroups_args *uap, register_t *retval) 551sys_setgroups(struct lwp *l, const struct sys_setgroups_args *uap, register_t *retval)
554{ 552{
555 /* { 553 /* {
556 syscallarg(int) gidsetsize; 554 syscallarg(int) gidsetsize;
557 syscallarg(const gid_t *) gidset; 555 syscallarg(const gid_t *) gidset;
558 } */ 556 } */
559 kauth_cred_t ncred; 557 kauth_cred_t ncred;
560 int error; 558 int error;
561 559
562 ncred = kauth_cred_alloc(); 560 ncred = kauth_cred_alloc();
563 error = kauth_cred_setgroups(ncred, SCARG(uap, gidset), 561 error = kauth_cred_setgroups(ncred, SCARG(uap, gidset),
564 SCARG(uap, gidsetsize), -1, UIO_USERSPACE); 562 SCARG(uap, gidsetsize), -1, UIO_USERSPACE);
565 if (error != 0) { 563 if (error != 0) {
566 kauth_cred_free(ncred); 564 kauth_cred_free(ncred);
567 return error; 565 return error;
568 } 566 }
569 567
570 return kauth_proc_setgroups(l, ncred); 568 return kauth_proc_setgroups(l, ncred);
571} 569}
572 570
573/* 571/*
574 * Get login name, if available. 572 * Get login name, if available.
575 */ 573 */
576/* ARGSUSED */ 574/* ARGSUSED */
577int 575int
578sys___getlogin(struct lwp *l, const struct sys___getlogin_args *uap, register_t *retval) 576sys___getlogin(struct lwp *l, const struct sys___getlogin_args *uap, register_t *retval)
579{ 577{
580 /* { 578 /* {
581 syscallarg(char *) namebuf; 579 syscallarg(char *) namebuf;
582 syscallarg(size_t) namelen; 580 syscallarg(size_t) namelen;
583 } */ 581 } */
584 struct proc *p = l->l_proc; 582 struct proc *p = l->l_proc;
585 char login[sizeof(p->p_session->s_login)]; 583 char login[sizeof(p->p_session->s_login)];
586 int namelen = SCARG(uap, namelen); 584 int namelen = SCARG(uap, namelen);
587 585
588 if (namelen > sizeof(login)) 586 if (namelen > sizeof(login))
589 namelen = sizeof(login); 587 namelen = sizeof(login);
590 mutex_enter(proc_lock); 588 mutex_enter(proc_lock);
591 memcpy(login, p->p_session->s_login, namelen); 589 memcpy(login, p->p_session->s_login, namelen);
592 mutex_exit(proc_lock); 590 mutex_exit(proc_lock);
593 return (copyout(login, (void *)SCARG(uap, namebuf), namelen)); 591 return (copyout(login, (void *)SCARG(uap, namebuf), namelen));
594} 592}
595 593
596/* 594/*
597 * Set login name. 595 * Set login name.
598 */ 596 */
599/* ARGSUSED */ 597/* ARGSUSED */
600int 598int
601sys___setlogin(struct lwp *l, const struct sys___setlogin_args *uap, register_t *retval) 599sys___setlogin(struct lwp *l, const struct sys___setlogin_args *uap, register_t *retval)
602{ 600{
603 /* { 601 /* {
604 syscallarg(const char *) namebuf; 602 syscallarg(const char *) namebuf;
605 } */ 603 } */
606 struct proc *p = l->l_proc; 604 struct proc *p = l->l_proc;
607 struct session *sp; 605 struct session *sp;
608 char newname[sizeof sp->s_login + 1]; 606 char newname[sizeof sp->s_login + 1];
609 int error; 607 int error;
610 608
611 if ((error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_SETID, 609 if ((error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_SETID,
612 p, NULL, NULL, NULL)) != 0) 610 p, NULL, NULL, NULL)) != 0)
613 return (error); 611 return (error);
614 error = copyinstr(SCARG(uap, namebuf), &newname, sizeof newname, NULL); 612 error = copyinstr(SCARG(uap, namebuf), &newname, sizeof newname, NULL);
615 if (error != 0) 613 if (error != 0)
616 return (error == ENAMETOOLONG ? EINVAL : error); 614 return (error == ENAMETOOLONG ? EINVAL : error);
617 615
618 mutex_enter(proc_lock); 616 mutex_enter(proc_lock);
619 sp = p->p_session; 617 sp = p->p_session;
620 if (sp->s_flags & S_LOGIN_SET && p->p_pid != sp->s_sid && 618 if (sp->s_flags & S_LOGIN_SET && p->p_pid != sp->s_sid &&
621 strncmp(newname, sp->s_login, sizeof sp->s_login) != 0) 619 strncmp(newname, sp->s_login, sizeof sp->s_login) != 0)
622 log(LOG_WARNING, "%s (pid %d) changing logname from " 620 log(LOG_WARNING, "%s (pid %d) changing logname from "
623 "%.*s to %s\n", p->p_comm, p->p_pid, 621 "%.*s to %s\n", p->p_comm, p->p_pid,
624 (int)sizeof sp->s_login, sp->s_login, newname); 622 (int)sizeof sp->s_login, sp->s_login, newname);
625 sp->s_flags |= S_LOGIN_SET; 623 sp->s_flags |= S_LOGIN_SET;
626 strncpy(sp->s_login, newname, sizeof sp->s_login); 624 strncpy(sp->s_login, newname, sizeof sp->s_login);
627 mutex_exit(proc_lock); 625 mutex_exit(proc_lock);
628 return (0); 626 return (0);
629} 627}