1/*- 2 * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993 3 * The Regents of the University of California. 4 * (c) UNIX System Laboratories, Inc. 5 * Copyright (c) 2000-2001 Robert N. M. Watson. 6 * All rights reserved. 7 * 8 * All or some portions of this file are derived from material licensed 9 * to the University of California by American Telephone and Telegraph 10 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 11 * the permission of UNIX System Laboratories, Inc. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * @(#)kern_prot.c 8.6 (Berkeley) 1/21/94 38 */ 39 40/* 41 * System calls related to processes and protection 42 */ 43 44#include <sys/cdefs.h>
| 1/*- 2 * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993 3 * The Regents of the University of California. 4 * (c) UNIX System Laboratories, Inc. 5 * Copyright (c) 2000-2001 Robert N. M. Watson. 6 * All rights reserved. 7 * 8 * All or some portions of this file are derived from material licensed 9 * to the University of California by American Telephone and Telegraph 10 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 11 * the permission of UNIX System Laboratories, Inc. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * @(#)kern_prot.c 8.6 (Berkeley) 1/21/94 38 */ 39 40/* 41 * System calls related to processes and protection 42 */ 43 44#include <sys/cdefs.h>
|
45__FBSDID("$FreeBSD: head/sys/kern/kern_prot.c 193511 2009-06-05 14:55:22Z rwatson $");
| 45__FBSDID("$FreeBSD: head/sys/kern/kern_prot.c 194498 2009-06-19 17:10:35Z brooks $");
|
46 47#include "opt_compat.h" 48#include "opt_inet.h" 49#include "opt_inet6.h" 50 51#include <sys/param.h> 52#include <sys/systm.h> 53#include <sys/acct.h> 54#include <sys/kdb.h> 55#include <sys/kernel.h> 56#include <sys/lock.h> 57#include <sys/malloc.h> 58#include <sys/mutex.h> 59#include <sys/refcount.h> 60#include <sys/sx.h> 61#include <sys/priv.h> 62#include <sys/proc.h> 63#include <sys/sysproto.h> 64#include <sys/jail.h> 65#include <sys/pioctl.h> 66#include <sys/resourcevar.h> 67#include <sys/socket.h> 68#include <sys/socketvar.h> 69#include <sys/syscallsubr.h> 70#include <sys/sysctl.h> 71#include <sys/vimage.h> 72 73#if defined(INET) || defined(INET6) 74#include <netinet/in.h> 75#include <netinet/in_pcb.h> 76#endif 77 78#include <security/audit/audit.h> 79#include <security/mac/mac_framework.h> 80 81static MALLOC_DEFINE(M_CRED, "cred", "credentials"); 82 83SYSCTL_NODE(_security, OID_AUTO, bsd, CTLFLAG_RW, 0, "BSD security policy"); 84
| 46 47#include "opt_compat.h" 48#include "opt_inet.h" 49#include "opt_inet6.h" 50 51#include <sys/param.h> 52#include <sys/systm.h> 53#include <sys/acct.h> 54#include <sys/kdb.h> 55#include <sys/kernel.h> 56#include <sys/lock.h> 57#include <sys/malloc.h> 58#include <sys/mutex.h> 59#include <sys/refcount.h> 60#include <sys/sx.h> 61#include <sys/priv.h> 62#include <sys/proc.h> 63#include <sys/sysproto.h> 64#include <sys/jail.h> 65#include <sys/pioctl.h> 66#include <sys/resourcevar.h> 67#include <sys/socket.h> 68#include <sys/socketvar.h> 69#include <sys/syscallsubr.h> 70#include <sys/sysctl.h> 71#include <sys/vimage.h> 72 73#if defined(INET) || defined(INET6) 74#include <netinet/in.h> 75#include <netinet/in_pcb.h> 76#endif 77 78#include <security/audit/audit.h> 79#include <security/mac/mac_framework.h> 80 81static MALLOC_DEFINE(M_CRED, "cred", "credentials"); 82 83SYSCTL_NODE(_security, OID_AUTO, bsd, CTLFLAG_RW, 0, "BSD security policy"); 84
|
| 85static void crextend(struct ucred *cr, int n); 86static void crsetgroups_locked(struct ucred *cr, int ngrp, 87 gid_t *groups); 88 89
|
85#ifndef _SYS_SYSPROTO_H_ 86struct getpid_args { 87 int dummy; 88}; 89#endif 90/* ARGSUSED */ 91int 92getpid(struct thread *td, struct getpid_args *uap) 93{ 94 struct proc *p = td->td_proc; 95 96 td->td_retval[0] = p->p_pid; 97#if defined(COMPAT_43) 98 PROC_LOCK(p); 99 td->td_retval[1] = p->p_pptr->p_pid; 100 PROC_UNLOCK(p); 101#endif 102 return (0); 103} 104 105#ifndef _SYS_SYSPROTO_H_ 106struct getppid_args { 107 int dummy; 108}; 109#endif 110/* ARGSUSED */ 111int 112getppid(struct thread *td, struct getppid_args *uap) 113{ 114 struct proc *p = td->td_proc; 115 116 PROC_LOCK(p); 117 td->td_retval[0] = p->p_pptr->p_pid; 118 PROC_UNLOCK(p); 119 return (0); 120} 121 122/* 123 * Get process group ID; note that POSIX getpgrp takes no parameter. 124 */ 125#ifndef _SYS_SYSPROTO_H_ 126struct getpgrp_args { 127 int dummy; 128}; 129#endif 130int 131getpgrp(struct thread *td, struct getpgrp_args *uap) 132{ 133 struct proc *p = td->td_proc; 134 135 PROC_LOCK(p); 136 td->td_retval[0] = p->p_pgrp->pg_id; 137 PROC_UNLOCK(p); 138 return (0); 139} 140 141/* Get an arbitary pid's process group id */ 142#ifndef _SYS_SYSPROTO_H_ 143struct getpgid_args { 144 pid_t pid; 145}; 146#endif 147int 148getpgid(struct thread *td, struct getpgid_args *uap) 149{ 150 struct proc *p; 151 int error; 152 153 if (uap->pid == 0) { 154 p = td->td_proc; 155 PROC_LOCK(p); 156 } else { 157 p = pfind(uap->pid); 158 if (p == NULL) 159 return (ESRCH); 160 error = p_cansee(td, p); 161 if (error) { 162 PROC_UNLOCK(p); 163 return (error); 164 } 165 } 166 td->td_retval[0] = p->p_pgrp->pg_id; 167 PROC_UNLOCK(p); 168 return (0); 169} 170 171/* 172 * Get an arbitary pid's session id. 173 */ 174#ifndef _SYS_SYSPROTO_H_ 175struct getsid_args { 176 pid_t pid; 177}; 178#endif 179int 180getsid(struct thread *td, struct getsid_args *uap) 181{ 182 struct proc *p; 183 int error; 184 185 if (uap->pid == 0) { 186 p = td->td_proc; 187 PROC_LOCK(p); 188 } else { 189 p = pfind(uap->pid); 190 if (p == NULL) 191 return (ESRCH); 192 error = p_cansee(td, p); 193 if (error) { 194 PROC_UNLOCK(p); 195 return (error); 196 } 197 } 198 td->td_retval[0] = p->p_session->s_sid; 199 PROC_UNLOCK(p); 200 return (0); 201} 202 203#ifndef _SYS_SYSPROTO_H_ 204struct getuid_args { 205 int dummy; 206}; 207#endif 208/* ARGSUSED */ 209int 210getuid(struct thread *td, struct getuid_args *uap) 211{ 212 213 td->td_retval[0] = td->td_ucred->cr_ruid; 214#if defined(COMPAT_43) 215 td->td_retval[1] = td->td_ucred->cr_uid; 216#endif 217 return (0); 218} 219 220#ifndef _SYS_SYSPROTO_H_ 221struct geteuid_args { 222 int dummy; 223}; 224#endif 225/* ARGSUSED */ 226int 227geteuid(struct thread *td, struct geteuid_args *uap) 228{ 229 230 td->td_retval[0] = td->td_ucred->cr_uid; 231 return (0); 232} 233 234#ifndef _SYS_SYSPROTO_H_ 235struct getgid_args { 236 int dummy; 237}; 238#endif 239/* ARGSUSED */ 240int 241getgid(struct thread *td, struct getgid_args *uap) 242{ 243 244 td->td_retval[0] = td->td_ucred->cr_rgid; 245#if defined(COMPAT_43) 246 td->td_retval[1] = td->td_ucred->cr_groups[0]; 247#endif 248 return (0); 249} 250 251/* 252 * Get effective group ID. The "egid" is groups[0], and could be obtained 253 * via getgroups. This syscall exists because it is somewhat painful to do 254 * correctly in a library function. 255 */ 256#ifndef _SYS_SYSPROTO_H_ 257struct getegid_args { 258 int dummy; 259}; 260#endif 261/* ARGSUSED */ 262int 263getegid(struct thread *td, struct getegid_args *uap) 264{ 265 266 td->td_retval[0] = td->td_ucred->cr_groups[0]; 267 return (0); 268} 269 270#ifndef _SYS_SYSPROTO_H_ 271struct getgroups_args { 272 u_int gidsetsize; 273 gid_t *gidset; 274}; 275#endif 276int 277getgroups(struct thread *td, register struct getgroups_args *uap) 278{
| 90#ifndef _SYS_SYSPROTO_H_ 91struct getpid_args { 92 int dummy; 93}; 94#endif 95/* ARGSUSED */ 96int 97getpid(struct thread *td, struct getpid_args *uap) 98{ 99 struct proc *p = td->td_proc; 100 101 td->td_retval[0] = p->p_pid; 102#if defined(COMPAT_43) 103 PROC_LOCK(p); 104 td->td_retval[1] = p->p_pptr->p_pid; 105 PROC_UNLOCK(p); 106#endif 107 return (0); 108} 109 110#ifndef _SYS_SYSPROTO_H_ 111struct getppid_args { 112 int dummy; 113}; 114#endif 115/* ARGSUSED */ 116int 117getppid(struct thread *td, struct getppid_args *uap) 118{ 119 struct proc *p = td->td_proc; 120 121 PROC_LOCK(p); 122 td->td_retval[0] = p->p_pptr->p_pid; 123 PROC_UNLOCK(p); 124 return (0); 125} 126 127/* 128 * Get process group ID; note that POSIX getpgrp takes no parameter. 129 */ 130#ifndef _SYS_SYSPROTO_H_ 131struct getpgrp_args { 132 int dummy; 133}; 134#endif 135int 136getpgrp(struct thread *td, struct getpgrp_args *uap) 137{ 138 struct proc *p = td->td_proc; 139 140 PROC_LOCK(p); 141 td->td_retval[0] = p->p_pgrp->pg_id; 142 PROC_UNLOCK(p); 143 return (0); 144} 145 146/* Get an arbitary pid's process group id */ 147#ifndef _SYS_SYSPROTO_H_ 148struct getpgid_args { 149 pid_t pid; 150}; 151#endif 152int 153getpgid(struct thread *td, struct getpgid_args *uap) 154{ 155 struct proc *p; 156 int error; 157 158 if (uap->pid == 0) { 159 p = td->td_proc; 160 PROC_LOCK(p); 161 } else { 162 p = pfind(uap->pid); 163 if (p == NULL) 164 return (ESRCH); 165 error = p_cansee(td, p); 166 if (error) { 167 PROC_UNLOCK(p); 168 return (error); 169 } 170 } 171 td->td_retval[0] = p->p_pgrp->pg_id; 172 PROC_UNLOCK(p); 173 return (0); 174} 175 176/* 177 * Get an arbitary pid's session id. 178 */ 179#ifndef _SYS_SYSPROTO_H_ 180struct getsid_args { 181 pid_t pid; 182}; 183#endif 184int 185getsid(struct thread *td, struct getsid_args *uap) 186{ 187 struct proc *p; 188 int error; 189 190 if (uap->pid == 0) { 191 p = td->td_proc; 192 PROC_LOCK(p); 193 } else { 194 p = pfind(uap->pid); 195 if (p == NULL) 196 return (ESRCH); 197 error = p_cansee(td, p); 198 if (error) { 199 PROC_UNLOCK(p); 200 return (error); 201 } 202 } 203 td->td_retval[0] = p->p_session->s_sid; 204 PROC_UNLOCK(p); 205 return (0); 206} 207 208#ifndef _SYS_SYSPROTO_H_ 209struct getuid_args { 210 int dummy; 211}; 212#endif 213/* ARGSUSED */ 214int 215getuid(struct thread *td, struct getuid_args *uap) 216{ 217 218 td->td_retval[0] = td->td_ucred->cr_ruid; 219#if defined(COMPAT_43) 220 td->td_retval[1] = td->td_ucred->cr_uid; 221#endif 222 return (0); 223} 224 225#ifndef _SYS_SYSPROTO_H_ 226struct geteuid_args { 227 int dummy; 228}; 229#endif 230/* ARGSUSED */ 231int 232geteuid(struct thread *td, struct geteuid_args *uap) 233{ 234 235 td->td_retval[0] = td->td_ucred->cr_uid; 236 return (0); 237} 238 239#ifndef _SYS_SYSPROTO_H_ 240struct getgid_args { 241 int dummy; 242}; 243#endif 244/* ARGSUSED */ 245int 246getgid(struct thread *td, struct getgid_args *uap) 247{ 248 249 td->td_retval[0] = td->td_ucred->cr_rgid; 250#if defined(COMPAT_43) 251 td->td_retval[1] = td->td_ucred->cr_groups[0]; 252#endif 253 return (0); 254} 255 256/* 257 * Get effective group ID. The "egid" is groups[0], and could be obtained 258 * via getgroups. This syscall exists because it is somewhat painful to do 259 * correctly in a library function. 260 */ 261#ifndef _SYS_SYSPROTO_H_ 262struct getegid_args { 263 int dummy; 264}; 265#endif 266/* ARGSUSED */ 267int 268getegid(struct thread *td, struct getegid_args *uap) 269{ 270 271 td->td_retval[0] = td->td_ucred->cr_groups[0]; 272 return (0); 273} 274 275#ifndef _SYS_SYSPROTO_H_ 276struct getgroups_args { 277 u_int gidsetsize; 278 gid_t *gidset; 279}; 280#endif 281int 282getgroups(struct thread *td, register struct getgroups_args *uap) 283{
|
279 gid_t groups[NGROUPS];
| 284 gid_t *groups;
|
280 u_int ngrp; 281 int error; 282 283 ngrp = MIN(uap->gidsetsize, NGROUPS);
| 285 u_int ngrp; 286 int error; 287 288 ngrp = MIN(uap->gidsetsize, NGROUPS);
|
| 289 groups = malloc(ngrp * sizeof(*groups), M_TEMP, M_WAITOK);
|
284 error = kern_getgroups(td, &ngrp, groups); 285 if (error)
| 290 error = kern_getgroups(td, &ngrp, groups); 291 if (error)
|
286 return (error);
| 292 goto out;
|
287 if (uap->gidsetsize > 0) 288 error = copyout(groups, uap->gidset, ngrp * sizeof(gid_t)); 289 if (error == 0) 290 td->td_retval[0] = ngrp;
| 293 if (uap->gidsetsize > 0) 294 error = copyout(groups, uap->gidset, ngrp * sizeof(gid_t)); 295 if (error == 0) 296 td->td_retval[0] = ngrp;
|
| 297out: 298 free(groups, M_TEMP);
|
291 return (error); 292} 293 294int 295kern_getgroups(struct thread *td, u_int *ngrp, gid_t *groups) 296{ 297 struct ucred *cred; 298 299 cred = td->td_ucred; 300 if (*ngrp == 0) { 301 *ngrp = cred->cr_ngroups; 302 return (0); 303 } 304 if (*ngrp < cred->cr_ngroups) 305 return (EINVAL); 306 *ngrp = cred->cr_ngroups; 307 bcopy(cred->cr_groups, groups, *ngrp * sizeof(gid_t)); 308 return (0); 309} 310 311#ifndef _SYS_SYSPROTO_H_ 312struct setsid_args { 313 int dummy; 314}; 315#endif 316/* ARGSUSED */ 317int 318setsid(register struct thread *td, struct setsid_args *uap) 319{ 320 struct pgrp *pgrp; 321 int error; 322 struct proc *p = td->td_proc; 323 struct pgrp *newpgrp; 324 struct session *newsess; 325 326 error = 0; 327 pgrp = NULL; 328 329 newpgrp = malloc(sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO); 330 newsess = malloc(sizeof(struct session), M_SESSION, M_WAITOK | M_ZERO); 331 332 sx_xlock(&proctree_lock); 333 334 if (p->p_pgid == p->p_pid || (pgrp = pgfind(p->p_pid)) != NULL) { 335 if (pgrp != NULL) 336 PGRP_UNLOCK(pgrp); 337 error = EPERM; 338 } else { 339 (void)enterpgrp(p, p->p_pid, newpgrp, newsess); 340 td->td_retval[0] = p->p_pid; 341 newpgrp = NULL; 342 newsess = NULL; 343 } 344 345 sx_xunlock(&proctree_lock); 346 347 if (newpgrp != NULL) 348 free(newpgrp, M_PGRP); 349 if (newsess != NULL) 350 free(newsess, M_SESSION); 351 352 return (error); 353} 354 355/* 356 * set process group (setpgid/old setpgrp) 357 * 358 * caller does setpgid(targpid, targpgid) 359 * 360 * pid must be caller or child of caller (ESRCH) 361 * if a child 362 * pid must be in same session (EPERM) 363 * pid can't have done an exec (EACCES) 364 * if pgid != pid 365 * there must exist some pid in same session having pgid (EPERM) 366 * pid must not be session leader (EPERM) 367 */ 368#ifndef _SYS_SYSPROTO_H_ 369struct setpgid_args { 370 int pid; /* target process id */ 371 int pgid; /* target pgrp id */ 372}; 373#endif 374/* ARGSUSED */ 375int 376setpgid(struct thread *td, register struct setpgid_args *uap) 377{ 378 struct proc *curp = td->td_proc; 379 register struct proc *targp; /* target process */ 380 register struct pgrp *pgrp; /* target pgrp */ 381 int error; 382 struct pgrp *newpgrp; 383 384 if (uap->pgid < 0) 385 return (EINVAL); 386 387 error = 0; 388 389 newpgrp = malloc(sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO); 390 391 sx_xlock(&proctree_lock); 392 if (uap->pid != 0 && uap->pid != curp->p_pid) { 393 if ((targp = pfind(uap->pid)) == NULL) { 394 error = ESRCH; 395 goto done; 396 } 397 if (!inferior(targp)) { 398 PROC_UNLOCK(targp); 399 error = ESRCH; 400 goto done; 401 } 402 if ((error = p_cansee(td, targp))) { 403 PROC_UNLOCK(targp); 404 goto done; 405 } 406 if (targp->p_pgrp == NULL || 407 targp->p_session != curp->p_session) { 408 PROC_UNLOCK(targp); 409 error = EPERM; 410 goto done; 411 } 412 if (targp->p_flag & P_EXEC) { 413 PROC_UNLOCK(targp); 414 error = EACCES; 415 goto done; 416 } 417 PROC_UNLOCK(targp); 418 } else 419 targp = curp; 420 if (SESS_LEADER(targp)) { 421 error = EPERM; 422 goto done; 423 } 424 if (uap->pgid == 0) 425 uap->pgid = targp->p_pid; 426 if ((pgrp = pgfind(uap->pgid)) == NULL) { 427 if (uap->pgid == targp->p_pid) { 428 error = enterpgrp(targp, uap->pgid, newpgrp, 429 NULL); 430 if (error == 0) 431 newpgrp = NULL; 432 } else 433 error = EPERM; 434 } else { 435 if (pgrp == targp->p_pgrp) { 436 PGRP_UNLOCK(pgrp); 437 goto done; 438 } 439 if (pgrp->pg_id != targp->p_pid && 440 pgrp->pg_session != curp->p_session) { 441 PGRP_UNLOCK(pgrp); 442 error = EPERM; 443 goto done; 444 } 445 PGRP_UNLOCK(pgrp); 446 error = enterthispgrp(targp, pgrp); 447 } 448done: 449 sx_xunlock(&proctree_lock); 450 KASSERT((error == 0) || (newpgrp != NULL), 451 ("setpgid failed and newpgrp is NULL")); 452 if (newpgrp != NULL) 453 free(newpgrp, M_PGRP); 454 return (error); 455} 456 457/* 458 * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD 459 * compatible. It says that setting the uid/gid to euid/egid is a special 460 * case of "appropriate privilege". Once the rules are expanded out, this 461 * basically means that setuid(nnn) sets all three id's, in all permitted 462 * cases unless _POSIX_SAVED_IDS is enabled. In that case, setuid(getuid()) 463 * does not set the saved id - this is dangerous for traditional BSD 464 * programs. For this reason, we *really* do not want to set 465 * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2. 466 */ 467#define POSIX_APPENDIX_B_4_2_2 468 469#ifndef _SYS_SYSPROTO_H_ 470struct setuid_args { 471 uid_t uid; 472}; 473#endif 474/* ARGSUSED */ 475int 476setuid(struct thread *td, struct setuid_args *uap) 477{ 478 struct proc *p = td->td_proc; 479 struct ucred *newcred, *oldcred; 480 uid_t uid; 481 struct uidinfo *uip; 482 int error; 483 484 uid = uap->uid; 485 AUDIT_ARG(uid, uid); 486 newcred = crget(); 487 uip = uifind(uid); 488 PROC_LOCK(p);
| 299 return (error); 300} 301 302int 303kern_getgroups(struct thread *td, u_int *ngrp, gid_t *groups) 304{ 305 struct ucred *cred; 306 307 cred = td->td_ucred; 308 if (*ngrp == 0) { 309 *ngrp = cred->cr_ngroups; 310 return (0); 311 } 312 if (*ngrp < cred->cr_ngroups) 313 return (EINVAL); 314 *ngrp = cred->cr_ngroups; 315 bcopy(cred->cr_groups, groups, *ngrp * sizeof(gid_t)); 316 return (0); 317} 318 319#ifndef _SYS_SYSPROTO_H_ 320struct setsid_args { 321 int dummy; 322}; 323#endif 324/* ARGSUSED */ 325int 326setsid(register struct thread *td, struct setsid_args *uap) 327{ 328 struct pgrp *pgrp; 329 int error; 330 struct proc *p = td->td_proc; 331 struct pgrp *newpgrp; 332 struct session *newsess; 333 334 error = 0; 335 pgrp = NULL; 336 337 newpgrp = malloc(sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO); 338 newsess = malloc(sizeof(struct session), M_SESSION, M_WAITOK | M_ZERO); 339 340 sx_xlock(&proctree_lock); 341 342 if (p->p_pgid == p->p_pid || (pgrp = pgfind(p->p_pid)) != NULL) { 343 if (pgrp != NULL) 344 PGRP_UNLOCK(pgrp); 345 error = EPERM; 346 } else { 347 (void)enterpgrp(p, p->p_pid, newpgrp, newsess); 348 td->td_retval[0] = p->p_pid; 349 newpgrp = NULL; 350 newsess = NULL; 351 } 352 353 sx_xunlock(&proctree_lock); 354 355 if (newpgrp != NULL) 356 free(newpgrp, M_PGRP); 357 if (newsess != NULL) 358 free(newsess, M_SESSION); 359 360 return (error); 361} 362 363/* 364 * set process group (setpgid/old setpgrp) 365 * 366 * caller does setpgid(targpid, targpgid) 367 * 368 * pid must be caller or child of caller (ESRCH) 369 * if a child 370 * pid must be in same session (EPERM) 371 * pid can't have done an exec (EACCES) 372 * if pgid != pid 373 * there must exist some pid in same session having pgid (EPERM) 374 * pid must not be session leader (EPERM) 375 */ 376#ifndef _SYS_SYSPROTO_H_ 377struct setpgid_args { 378 int pid; /* target process id */ 379 int pgid; /* target pgrp id */ 380}; 381#endif 382/* ARGSUSED */ 383int 384setpgid(struct thread *td, register struct setpgid_args *uap) 385{ 386 struct proc *curp = td->td_proc; 387 register struct proc *targp; /* target process */ 388 register struct pgrp *pgrp; /* target pgrp */ 389 int error; 390 struct pgrp *newpgrp; 391 392 if (uap->pgid < 0) 393 return (EINVAL); 394 395 error = 0; 396 397 newpgrp = malloc(sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO); 398 399 sx_xlock(&proctree_lock); 400 if (uap->pid != 0 && uap->pid != curp->p_pid) { 401 if ((targp = pfind(uap->pid)) == NULL) { 402 error = ESRCH; 403 goto done; 404 } 405 if (!inferior(targp)) { 406 PROC_UNLOCK(targp); 407 error = ESRCH; 408 goto done; 409 } 410 if ((error = p_cansee(td, targp))) { 411 PROC_UNLOCK(targp); 412 goto done; 413 } 414 if (targp->p_pgrp == NULL || 415 targp->p_session != curp->p_session) { 416 PROC_UNLOCK(targp); 417 error = EPERM; 418 goto done; 419 } 420 if (targp->p_flag & P_EXEC) { 421 PROC_UNLOCK(targp); 422 error = EACCES; 423 goto done; 424 } 425 PROC_UNLOCK(targp); 426 } else 427 targp = curp; 428 if (SESS_LEADER(targp)) { 429 error = EPERM; 430 goto done; 431 } 432 if (uap->pgid == 0) 433 uap->pgid = targp->p_pid; 434 if ((pgrp = pgfind(uap->pgid)) == NULL) { 435 if (uap->pgid == targp->p_pid) { 436 error = enterpgrp(targp, uap->pgid, newpgrp, 437 NULL); 438 if (error == 0) 439 newpgrp = NULL; 440 } else 441 error = EPERM; 442 } else { 443 if (pgrp == targp->p_pgrp) { 444 PGRP_UNLOCK(pgrp); 445 goto done; 446 } 447 if (pgrp->pg_id != targp->p_pid && 448 pgrp->pg_session != curp->p_session) { 449 PGRP_UNLOCK(pgrp); 450 error = EPERM; 451 goto done; 452 } 453 PGRP_UNLOCK(pgrp); 454 error = enterthispgrp(targp, pgrp); 455 } 456done: 457 sx_xunlock(&proctree_lock); 458 KASSERT((error == 0) || (newpgrp != NULL), 459 ("setpgid failed and newpgrp is NULL")); 460 if (newpgrp != NULL) 461 free(newpgrp, M_PGRP); 462 return (error); 463} 464 465/* 466 * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD 467 * compatible. It says that setting the uid/gid to euid/egid is a special 468 * case of "appropriate privilege". Once the rules are expanded out, this 469 * basically means that setuid(nnn) sets all three id's, in all permitted 470 * cases unless _POSIX_SAVED_IDS is enabled. In that case, setuid(getuid()) 471 * does not set the saved id - this is dangerous for traditional BSD 472 * programs. For this reason, we *really* do not want to set 473 * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2. 474 */ 475#define POSIX_APPENDIX_B_4_2_2 476 477#ifndef _SYS_SYSPROTO_H_ 478struct setuid_args { 479 uid_t uid; 480}; 481#endif 482/* ARGSUSED */ 483int 484setuid(struct thread *td, struct setuid_args *uap) 485{ 486 struct proc *p = td->td_proc; 487 struct ucred *newcred, *oldcred; 488 uid_t uid; 489 struct uidinfo *uip; 490 int error; 491 492 uid = uap->uid; 493 AUDIT_ARG(uid, uid); 494 newcred = crget(); 495 uip = uifind(uid); 496 PROC_LOCK(p);
|
489 oldcred = p->p_ucred;
| 497 /* 498 * Copy credentials so other references do not see our changes. 499 */ 500 oldcred = crcopysafe(p, newcred);
|
490 491#ifdef MAC 492 error = mac_cred_check_setuid(oldcred, uid); 493 if (error) 494 goto fail; 495#endif 496 497 /* 498 * See if we have "permission" by POSIX 1003.1 rules. 499 * 500 * Note that setuid(geteuid()) is a special case of 501 * "appropriate privileges" in appendix B.4.2.2. We need 502 * to use this clause to be compatible with traditional BSD 503 * semantics. Basically, it means that "setuid(xx)" sets all 504 * three id's (assuming you have privs). 505 * 506 * Notes on the logic. We do things in three steps. 507 * 1: We determine if the euid is going to change, and do EPERM 508 * right away. We unconditionally change the euid later if this 509 * test is satisfied, simplifying that part of the logic. 510 * 2: We determine if the real and/or saved uids are going to 511 * change. Determined by compile options. 512 * 3: Change euid last. (after tests in #2 for "appropriate privs") 513 */ 514 if (uid != oldcred->cr_ruid && /* allow setuid(getuid()) */ 515#ifdef _POSIX_SAVED_IDS 516 uid != oldcred->cr_svuid && /* allow setuid(saved gid) */ 517#endif 518#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 519 uid != oldcred->cr_uid && /* allow setuid(geteuid()) */ 520#endif 521 (error = priv_check_cred(oldcred, PRIV_CRED_SETUID, 0)) != 0) 522 goto fail; 523
| 501 502#ifdef MAC 503 error = mac_cred_check_setuid(oldcred, uid); 504 if (error) 505 goto fail; 506#endif 507 508 /* 509 * See if we have "permission" by POSIX 1003.1 rules. 510 * 511 * Note that setuid(geteuid()) is a special case of 512 * "appropriate privileges" in appendix B.4.2.2. We need 513 * to use this clause to be compatible with traditional BSD 514 * semantics. Basically, it means that "setuid(xx)" sets all 515 * three id's (assuming you have privs). 516 * 517 * Notes on the logic. We do things in three steps. 518 * 1: We determine if the euid is going to change, and do EPERM 519 * right away. We unconditionally change the euid later if this 520 * test is satisfied, simplifying that part of the logic. 521 * 2: We determine if the real and/or saved uids are going to 522 * change. Determined by compile options. 523 * 3: Change euid last. (after tests in #2 for "appropriate privs") 524 */ 525 if (uid != oldcred->cr_ruid && /* allow setuid(getuid()) */ 526#ifdef _POSIX_SAVED_IDS 527 uid != oldcred->cr_svuid && /* allow setuid(saved gid) */ 528#endif 529#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 530 uid != oldcred->cr_uid && /* allow setuid(geteuid()) */ 531#endif 532 (error = priv_check_cred(oldcred, PRIV_CRED_SETUID, 0)) != 0) 533 goto fail; 534
|
524 /* 525 * Copy credentials so other references do not see our changes. 526 */ 527 crcopy(newcred, oldcred);
| |
528#ifdef _POSIX_SAVED_IDS 529 /* 530 * Do we have "appropriate privileges" (are we root or uid == euid) 531 * If so, we are changing the real uid and/or saved uid. 532 */ 533 if ( 534#ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */ 535 uid == oldcred->cr_uid || 536#endif 537 /* We are using privs. */ 538 priv_check_cred(oldcred, PRIV_CRED_SETUID, 0) == 0) 539#endif 540 { 541 /* 542 * Set the real uid and transfer proc count to new user. 543 */ 544 if (uid != oldcred->cr_ruid) { 545 change_ruid(newcred, uip); 546 setsugid(p); 547 } 548 /* 549 * Set saved uid 550 * 551 * XXX always set saved uid even if not _POSIX_SAVED_IDS, as 552 * the security of seteuid() depends on it. B.4.2.2 says it 553 * is important that we should do this. 554 */ 555 if (uid != oldcred->cr_svuid) { 556 change_svuid(newcred, uid); 557 setsugid(p); 558 } 559 } 560 561 /* 562 * In all permitted cases, we are changing the euid. 563 */ 564 if (uid != oldcred->cr_uid) { 565 change_euid(newcred, uip); 566 setsugid(p); 567 } 568 p->p_ucred = newcred; 569 PROC_UNLOCK(p); 570 uifree(uip); 571 crfree(oldcred); 572 return (0); 573 574fail: 575 PROC_UNLOCK(p); 576 uifree(uip); 577 crfree(newcred); 578 return (error); 579} 580 581#ifndef _SYS_SYSPROTO_H_ 582struct seteuid_args { 583 uid_t euid; 584}; 585#endif 586/* ARGSUSED */ 587int 588seteuid(struct thread *td, struct seteuid_args *uap) 589{ 590 struct proc *p = td->td_proc; 591 struct ucred *newcred, *oldcred; 592 uid_t euid; 593 struct uidinfo *euip; 594 int error; 595 596 euid = uap->euid; 597 AUDIT_ARG(euid, euid); 598 newcred = crget(); 599 euip = uifind(euid); 600 PROC_LOCK(p);
| 535#ifdef _POSIX_SAVED_IDS 536 /* 537 * Do we have "appropriate privileges" (are we root or uid == euid) 538 * If so, we are changing the real uid and/or saved uid. 539 */ 540 if ( 541#ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */ 542 uid == oldcred->cr_uid || 543#endif 544 /* We are using privs. */ 545 priv_check_cred(oldcred, PRIV_CRED_SETUID, 0) == 0) 546#endif 547 { 548 /* 549 * Set the real uid and transfer proc count to new user. 550 */ 551 if (uid != oldcred->cr_ruid) { 552 change_ruid(newcred, uip); 553 setsugid(p); 554 } 555 /* 556 * Set saved uid 557 * 558 * XXX always set saved uid even if not _POSIX_SAVED_IDS, as 559 * the security of seteuid() depends on it. B.4.2.2 says it 560 * is important that we should do this. 561 */ 562 if (uid != oldcred->cr_svuid) { 563 change_svuid(newcred, uid); 564 setsugid(p); 565 } 566 } 567 568 /* 569 * In all permitted cases, we are changing the euid. 570 */ 571 if (uid != oldcred->cr_uid) { 572 change_euid(newcred, uip); 573 setsugid(p); 574 } 575 p->p_ucred = newcred; 576 PROC_UNLOCK(p); 577 uifree(uip); 578 crfree(oldcred); 579 return (0); 580 581fail: 582 PROC_UNLOCK(p); 583 uifree(uip); 584 crfree(newcred); 585 return (error); 586} 587 588#ifndef _SYS_SYSPROTO_H_ 589struct seteuid_args { 590 uid_t euid; 591}; 592#endif 593/* ARGSUSED */ 594int 595seteuid(struct thread *td, struct seteuid_args *uap) 596{ 597 struct proc *p = td->td_proc; 598 struct ucred *newcred, *oldcred; 599 uid_t euid; 600 struct uidinfo *euip; 601 int error; 602 603 euid = uap->euid; 604 AUDIT_ARG(euid, euid); 605 newcred = crget(); 606 euip = uifind(euid); 607 PROC_LOCK(p);
|
601 oldcred = p->p_ucred;
| 608 /* 609 * Copy credentials so other references do not see our changes. 610 */ 611 oldcred = crcopysafe(p, newcred);
|
602 603#ifdef MAC 604 error = mac_cred_check_seteuid(oldcred, euid); 605 if (error) 606 goto fail; 607#endif 608 609 if (euid != oldcred->cr_ruid && /* allow seteuid(getuid()) */ 610 euid != oldcred->cr_svuid && /* allow seteuid(saved uid) */ 611 (error = priv_check_cred(oldcred, PRIV_CRED_SETEUID, 0)) != 0) 612 goto fail; 613 614 /*
| 612 613#ifdef MAC 614 error = mac_cred_check_seteuid(oldcred, euid); 615 if (error) 616 goto fail; 617#endif 618 619 if (euid != oldcred->cr_ruid && /* allow seteuid(getuid()) */ 620 euid != oldcred->cr_svuid && /* allow seteuid(saved uid) */ 621 (error = priv_check_cred(oldcred, PRIV_CRED_SETEUID, 0)) != 0) 622 goto fail; 623 624 /*
|
615 * Everything's okay, do it. Copy credentials so other references do 616 * not see our changes.
| 625 * Everything's okay, do it.
|
617 */ 618 crcopy(newcred, oldcred); 619 if (oldcred->cr_uid != euid) { 620 change_euid(newcred, euip); 621 setsugid(p); 622 } 623 p->p_ucred = newcred; 624 PROC_UNLOCK(p); 625 uifree(euip); 626 crfree(oldcred); 627 return (0); 628 629fail: 630 PROC_UNLOCK(p); 631 uifree(euip); 632 crfree(newcred); 633 return (error); 634} 635 636#ifndef _SYS_SYSPROTO_H_ 637struct setgid_args { 638 gid_t gid; 639}; 640#endif 641/* ARGSUSED */ 642int 643setgid(struct thread *td, struct setgid_args *uap) 644{ 645 struct proc *p = td->td_proc; 646 struct ucred *newcred, *oldcred; 647 gid_t gid; 648 int error; 649 650 gid = uap->gid; 651 AUDIT_ARG(gid, gid); 652 newcred = crget(); 653 PROC_LOCK(p);
| 626 */ 627 crcopy(newcred, oldcred); 628 if (oldcred->cr_uid != euid) { 629 change_euid(newcred, euip); 630 setsugid(p); 631 } 632 p->p_ucred = newcred; 633 PROC_UNLOCK(p); 634 uifree(euip); 635 crfree(oldcred); 636 return (0); 637 638fail: 639 PROC_UNLOCK(p); 640 uifree(euip); 641 crfree(newcred); 642 return (error); 643} 644 645#ifndef _SYS_SYSPROTO_H_ 646struct setgid_args { 647 gid_t gid; 648}; 649#endif 650/* ARGSUSED */ 651int 652setgid(struct thread *td, struct setgid_args *uap) 653{ 654 struct proc *p = td->td_proc; 655 struct ucred *newcred, *oldcred; 656 gid_t gid; 657 int error; 658 659 gid = uap->gid; 660 AUDIT_ARG(gid, gid); 661 newcred = crget(); 662 PROC_LOCK(p);
|
654 oldcred = p->p_ucred;
| 663 oldcred = crcopysafe(p, newcred);
|
655 656#ifdef MAC 657 error = mac_cred_check_setgid(oldcred, gid); 658 if (error) 659 goto fail; 660#endif 661 662 /* 663 * See if we have "permission" by POSIX 1003.1 rules. 664 * 665 * Note that setgid(getegid()) is a special case of 666 * "appropriate privileges" in appendix B.4.2.2. We need 667 * to use this clause to be compatible with traditional BSD 668 * semantics. Basically, it means that "setgid(xx)" sets all 669 * three id's (assuming you have privs). 670 * 671 * For notes on the logic here, see setuid() above. 672 */ 673 if (gid != oldcred->cr_rgid && /* allow setgid(getgid()) */ 674#ifdef _POSIX_SAVED_IDS 675 gid != oldcred->cr_svgid && /* allow setgid(saved gid) */ 676#endif 677#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 678 gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */ 679#endif 680 (error = priv_check_cred(oldcred, PRIV_CRED_SETGID, 0)) != 0) 681 goto fail; 682
| 664 665#ifdef MAC 666 error = mac_cred_check_setgid(oldcred, gid); 667 if (error) 668 goto fail; 669#endif 670 671 /* 672 * See if we have "permission" by POSIX 1003.1 rules. 673 * 674 * Note that setgid(getegid()) is a special case of 675 * "appropriate privileges" in appendix B.4.2.2. We need 676 * to use this clause to be compatible with traditional BSD 677 * semantics. Basically, it means that "setgid(xx)" sets all 678 * three id's (assuming you have privs). 679 * 680 * For notes on the logic here, see setuid() above. 681 */ 682 if (gid != oldcred->cr_rgid && /* allow setgid(getgid()) */ 683#ifdef _POSIX_SAVED_IDS 684 gid != oldcred->cr_svgid && /* allow setgid(saved gid) */ 685#endif 686#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 687 gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */ 688#endif 689 (error = priv_check_cred(oldcred, PRIV_CRED_SETGID, 0)) != 0) 690 goto fail; 691
|
683 crcopy(newcred, oldcred);
| |
684#ifdef _POSIX_SAVED_IDS 685 /* 686 * Do we have "appropriate privileges" (are we root or gid == egid) 687 * If so, we are changing the real uid and saved gid. 688 */ 689 if ( 690#ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ 691 gid == oldcred->cr_groups[0] || 692#endif 693 /* We are using privs. */ 694 priv_check_cred(oldcred, PRIV_CRED_SETGID, 0) == 0) 695#endif 696 { 697 /* 698 * Set real gid 699 */ 700 if (oldcred->cr_rgid != gid) { 701 change_rgid(newcred, gid); 702 setsugid(p); 703 } 704 /* 705 * Set saved gid 706 * 707 * XXX always set saved gid even if not _POSIX_SAVED_IDS, as 708 * the security of setegid() depends on it. B.4.2.2 says it 709 * is important that we should do this. 710 */ 711 if (oldcred->cr_svgid != gid) { 712 change_svgid(newcred, gid); 713 setsugid(p); 714 } 715 } 716 /* 717 * In all cases permitted cases, we are changing the egid. 718 * Copy credentials so other references do not see our changes. 719 */ 720 if (oldcred->cr_groups[0] != gid) { 721 change_egid(newcred, gid); 722 setsugid(p); 723 } 724 p->p_ucred = newcred; 725 PROC_UNLOCK(p); 726 crfree(oldcred); 727 return (0); 728 729fail: 730 PROC_UNLOCK(p); 731 crfree(newcred); 732 return (error); 733} 734 735#ifndef _SYS_SYSPROTO_H_ 736struct setegid_args { 737 gid_t egid; 738}; 739#endif 740/* ARGSUSED */ 741int 742setegid(struct thread *td, struct setegid_args *uap) 743{ 744 struct proc *p = td->td_proc; 745 struct ucred *newcred, *oldcred; 746 gid_t egid; 747 int error; 748 749 egid = uap->egid; 750 AUDIT_ARG(egid, egid); 751 newcred = crget(); 752 PROC_LOCK(p);
| 692#ifdef _POSIX_SAVED_IDS 693 /* 694 * Do we have "appropriate privileges" (are we root or gid == egid) 695 * If so, we are changing the real uid and saved gid. 696 */ 697 if ( 698#ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ 699 gid == oldcred->cr_groups[0] || 700#endif 701 /* We are using privs. */ 702 priv_check_cred(oldcred, PRIV_CRED_SETGID, 0) == 0) 703#endif 704 { 705 /* 706 * Set real gid 707 */ 708 if (oldcred->cr_rgid != gid) { 709 change_rgid(newcred, gid); 710 setsugid(p); 711 } 712 /* 713 * Set saved gid 714 * 715 * XXX always set saved gid even if not _POSIX_SAVED_IDS, as 716 * the security of setegid() depends on it. B.4.2.2 says it 717 * is important that we should do this. 718 */ 719 if (oldcred->cr_svgid != gid) { 720 change_svgid(newcred, gid); 721 setsugid(p); 722 } 723 } 724 /* 725 * In all cases permitted cases, we are changing the egid. 726 * Copy credentials so other references do not see our changes. 727 */ 728 if (oldcred->cr_groups[0] != gid) { 729 change_egid(newcred, gid); 730 setsugid(p); 731 } 732 p->p_ucred = newcred; 733 PROC_UNLOCK(p); 734 crfree(oldcred); 735 return (0); 736 737fail: 738 PROC_UNLOCK(p); 739 crfree(newcred); 740 return (error); 741} 742 743#ifndef _SYS_SYSPROTO_H_ 744struct setegid_args { 745 gid_t egid; 746}; 747#endif 748/* ARGSUSED */ 749int 750setegid(struct thread *td, struct setegid_args *uap) 751{ 752 struct proc *p = td->td_proc; 753 struct ucred *newcred, *oldcred; 754 gid_t egid; 755 int error; 756 757 egid = uap->egid; 758 AUDIT_ARG(egid, egid); 759 newcred = crget(); 760 PROC_LOCK(p);
|
753 oldcred = p->p_ucred;
| 761 oldcred = crcopysafe(p, newcred);
|
754 755#ifdef MAC 756 error = mac_cred_check_setegid(oldcred, egid); 757 if (error) 758 goto fail; 759#endif 760 761 if (egid != oldcred->cr_rgid && /* allow setegid(getgid()) */ 762 egid != oldcred->cr_svgid && /* allow setegid(saved gid) */ 763 (error = priv_check_cred(oldcred, PRIV_CRED_SETEGID, 0)) != 0) 764 goto fail; 765
| 762 763#ifdef MAC 764 error = mac_cred_check_setegid(oldcred, egid); 765 if (error) 766 goto fail; 767#endif 768 769 if (egid != oldcred->cr_rgid && /* allow setegid(getgid()) */ 770 egid != oldcred->cr_svgid && /* allow setegid(saved gid) */ 771 (error = priv_check_cred(oldcred, PRIV_CRED_SETEGID, 0)) != 0) 772 goto fail; 773
|
766 crcopy(newcred, oldcred);
| |
767 if (oldcred->cr_groups[0] != egid) { 768 change_egid(newcred, egid); 769 setsugid(p); 770 } 771 p->p_ucred = newcred; 772 PROC_UNLOCK(p); 773 crfree(oldcred); 774 return (0); 775 776fail: 777 PROC_UNLOCK(p); 778 crfree(newcred); 779 return (error); 780} 781 782#ifndef _SYS_SYSPROTO_H_ 783struct setgroups_args { 784 u_int gidsetsize; 785 gid_t *gidset; 786}; 787#endif 788/* ARGSUSED */ 789int 790setgroups(struct thread *td, struct setgroups_args *uap) 791{
| 774 if (oldcred->cr_groups[0] != egid) { 775 change_egid(newcred, egid); 776 setsugid(p); 777 } 778 p->p_ucred = newcred; 779 PROC_UNLOCK(p); 780 crfree(oldcred); 781 return (0); 782 783fail: 784 PROC_UNLOCK(p); 785 crfree(newcred); 786 return (error); 787} 788 789#ifndef _SYS_SYSPROTO_H_ 790struct setgroups_args { 791 u_int gidsetsize; 792 gid_t *gidset; 793}; 794#endif 795/* ARGSUSED */ 796int 797setgroups(struct thread *td, struct setgroups_args *uap) 798{
|
792 gid_t groups[NGROUPS];
| 799 gid_t *groups = NULL;
|
793 int error; 794 795 if (uap->gidsetsize > NGROUPS) 796 return (EINVAL);
| 800 int error; 801 802 if (uap->gidsetsize > NGROUPS) 803 return (EINVAL);
|
| 804 groups = malloc(uap->gidsetsize * sizeof(gid_t), M_TEMP, M_WAITOK);
|
797 error = copyin(uap->gidset, groups, uap->gidsetsize * sizeof(gid_t)); 798 if (error)
| 805 error = copyin(uap->gidset, groups, uap->gidsetsize * sizeof(gid_t)); 806 if (error)
|
799 return (error); 800 return (kern_setgroups(td, uap->gidsetsize, groups));
| 807 goto out; 808 error = kern_setgroups(td, uap->gidsetsize, groups); 809out: 810 free(groups, M_TEMP); 811 return (error);
|
801} 802 803int 804kern_setgroups(struct thread *td, u_int ngrp, gid_t *groups) 805{ 806 struct proc *p = td->td_proc; 807 struct ucred *newcred, *oldcred; 808 int error; 809 810 if (ngrp > NGROUPS) 811 return (EINVAL); 812 AUDIT_ARG(groupset, groups, ngrp); 813 newcred = crget();
| 812} 813 814int 815kern_setgroups(struct thread *td, u_int ngrp, gid_t *groups) 816{ 817 struct proc *p = td->td_proc; 818 struct ucred *newcred, *oldcred; 819 int error; 820 821 if (ngrp > NGROUPS) 822 return (EINVAL); 823 AUDIT_ARG(groupset, groups, ngrp); 824 newcred = crget();
|
| 825 crextend(newcred, ngrp);
|
814 PROC_LOCK(p);
| 826 PROC_LOCK(p);
|
815 oldcred = p->p_ucred;
| 827 oldcred = crcopysafe(p, newcred);
|
816 817#ifdef MAC 818 error = mac_cred_check_setgroups(oldcred, ngrp, groups); 819 if (error) 820 goto fail; 821#endif 822 823 error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS, 0); 824 if (error) 825 goto fail; 826
| 828 829#ifdef MAC 830 error = mac_cred_check_setgroups(oldcred, ngrp, groups); 831 if (error) 832 goto fail; 833#endif 834 835 error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS, 0); 836 if (error) 837 goto fail; 838
|
827 /* 828 * XXX A little bit lazy here. We could test if anything has 829 * changed before crcopy() and setting P_SUGID. 830 */ 831 crcopy(newcred, oldcred);
| |
832 if (ngrp < 1) { 833 /* 834 * setgroups(0, NULL) is a legitimate way of clearing the 835 * groups vector on non-BSD systems (which generally do not 836 * have the egid in the groups[0]). We risk security holes 837 * when running non-BSD software if we do not do the same. 838 */ 839 newcred->cr_ngroups = 1; 840 } else {
| 839 if (ngrp < 1) { 840 /* 841 * setgroups(0, NULL) is a legitimate way of clearing the 842 * groups vector on non-BSD systems (which generally do not 843 * have the egid in the groups[0]). We risk security holes 844 * when running non-BSD software if we do not do the same. 845 */ 846 newcred->cr_ngroups = 1; 847 } else {
|
841 bcopy(groups, newcred->cr_groups, ngrp * sizeof(gid_t)); 842 newcred->cr_ngroups = ngrp;
| 848 crsetgroups_locked(newcred, ngrp, groups);
|
843 } 844 setsugid(p); 845 p->p_ucred = newcred; 846 PROC_UNLOCK(p); 847 crfree(oldcred); 848 return (0); 849 850fail: 851 PROC_UNLOCK(p); 852 crfree(newcred); 853 return (error); 854} 855 856#ifndef _SYS_SYSPROTO_H_ 857struct setreuid_args { 858 uid_t ruid; 859 uid_t euid; 860}; 861#endif 862/* ARGSUSED */ 863int 864setreuid(register struct thread *td, struct setreuid_args *uap) 865{ 866 struct proc *p = td->td_proc; 867 struct ucred *newcred, *oldcred; 868 uid_t euid, ruid; 869 struct uidinfo *euip, *ruip; 870 int error; 871 872 euid = uap->euid; 873 ruid = uap->ruid; 874 AUDIT_ARG(euid, euid); 875 AUDIT_ARG(ruid, ruid); 876 newcred = crget(); 877 euip = uifind(euid); 878 ruip = uifind(ruid); 879 PROC_LOCK(p);
| 849 } 850 setsugid(p); 851 p->p_ucred = newcred; 852 PROC_UNLOCK(p); 853 crfree(oldcred); 854 return (0); 855 856fail: 857 PROC_UNLOCK(p); 858 crfree(newcred); 859 return (error); 860} 861 862#ifndef _SYS_SYSPROTO_H_ 863struct setreuid_args { 864 uid_t ruid; 865 uid_t euid; 866}; 867#endif 868/* ARGSUSED */ 869int 870setreuid(register struct thread *td, struct setreuid_args *uap) 871{ 872 struct proc *p = td->td_proc; 873 struct ucred *newcred, *oldcred; 874 uid_t euid, ruid; 875 struct uidinfo *euip, *ruip; 876 int error; 877 878 euid = uap->euid; 879 ruid = uap->ruid; 880 AUDIT_ARG(euid, euid); 881 AUDIT_ARG(ruid, ruid); 882 newcred = crget(); 883 euip = uifind(euid); 884 ruip = uifind(ruid); 885 PROC_LOCK(p);
|
880 oldcred = p->p_ucred;
| 886 oldcred = crcopysafe(p, newcred);
|
881 882#ifdef MAC 883 error = mac_cred_check_setreuid(oldcred, ruid, euid); 884 if (error) 885 goto fail; 886#endif 887 888 if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && 889 ruid != oldcred->cr_svuid) || 890 (euid != (uid_t)-1 && euid != oldcred->cr_uid && 891 euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) && 892 (error = priv_check_cred(oldcred, PRIV_CRED_SETREUID, 0)) != 0) 893 goto fail; 894
| 887 888#ifdef MAC 889 error = mac_cred_check_setreuid(oldcred, ruid, euid); 890 if (error) 891 goto fail; 892#endif 893 894 if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && 895 ruid != oldcred->cr_svuid) || 896 (euid != (uid_t)-1 && euid != oldcred->cr_uid && 897 euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) && 898 (error = priv_check_cred(oldcred, PRIV_CRED_SETREUID, 0)) != 0) 899 goto fail; 900
|
895 crcopy(newcred, oldcred);
| |
896 if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { 897 change_euid(newcred, euip); 898 setsugid(p); 899 } 900 if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { 901 change_ruid(newcred, ruip); 902 setsugid(p); 903 } 904 if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) && 905 newcred->cr_svuid != newcred->cr_uid) { 906 change_svuid(newcred, newcred->cr_uid); 907 setsugid(p); 908 } 909 p->p_ucred = newcred; 910 PROC_UNLOCK(p); 911 uifree(ruip); 912 uifree(euip); 913 crfree(oldcred); 914 return (0); 915 916fail: 917 PROC_UNLOCK(p); 918 uifree(ruip); 919 uifree(euip); 920 crfree(newcred); 921 return (error); 922} 923 924#ifndef _SYS_SYSPROTO_H_ 925struct setregid_args { 926 gid_t rgid; 927 gid_t egid; 928}; 929#endif 930/* ARGSUSED */ 931int 932setregid(register struct thread *td, struct setregid_args *uap) 933{ 934 struct proc *p = td->td_proc; 935 struct ucred *newcred, *oldcred; 936 gid_t egid, rgid; 937 int error; 938 939 egid = uap->egid; 940 rgid = uap->rgid; 941 AUDIT_ARG(egid, egid); 942 AUDIT_ARG(rgid, rgid); 943 newcred = crget(); 944 PROC_LOCK(p);
| 901 if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { 902 change_euid(newcred, euip); 903 setsugid(p); 904 } 905 if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { 906 change_ruid(newcred, ruip); 907 setsugid(p); 908 } 909 if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) && 910 newcred->cr_svuid != newcred->cr_uid) { 911 change_svuid(newcred, newcred->cr_uid); 912 setsugid(p); 913 } 914 p->p_ucred = newcred; 915 PROC_UNLOCK(p); 916 uifree(ruip); 917 uifree(euip); 918 crfree(oldcred); 919 return (0); 920 921fail: 922 PROC_UNLOCK(p); 923 uifree(ruip); 924 uifree(euip); 925 crfree(newcred); 926 return (error); 927} 928 929#ifndef _SYS_SYSPROTO_H_ 930struct setregid_args { 931 gid_t rgid; 932 gid_t egid; 933}; 934#endif 935/* ARGSUSED */ 936int 937setregid(register struct thread *td, struct setregid_args *uap) 938{ 939 struct proc *p = td->td_proc; 940 struct ucred *newcred, *oldcred; 941 gid_t egid, rgid; 942 int error; 943 944 egid = uap->egid; 945 rgid = uap->rgid; 946 AUDIT_ARG(egid, egid); 947 AUDIT_ARG(rgid, rgid); 948 newcred = crget(); 949 PROC_LOCK(p);
|
945 oldcred = p->p_ucred;
| 950 oldcred = crcopysafe(p, newcred);
|
946 947#ifdef MAC 948 error = mac_cred_check_setregid(oldcred, rgid, egid); 949 if (error) 950 goto fail; 951#endif 952 953 if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && 954 rgid != oldcred->cr_svgid) || 955 (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] && 956 egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) && 957 (error = priv_check_cred(oldcred, PRIV_CRED_SETREGID, 0)) != 0) 958 goto fail; 959
| 951 952#ifdef MAC 953 error = mac_cred_check_setregid(oldcred, rgid, egid); 954 if (error) 955 goto fail; 956#endif 957 958 if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && 959 rgid != oldcred->cr_svgid) || 960 (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] && 961 egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) && 962 (error = priv_check_cred(oldcred, PRIV_CRED_SETREGID, 0)) != 0) 963 goto fail; 964
|
960 crcopy(newcred, oldcred);
| |
961 if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { 962 change_egid(newcred, egid); 963 setsugid(p); 964 } 965 if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { 966 change_rgid(newcred, rgid); 967 setsugid(p); 968 } 969 if ((rgid != (gid_t)-1 || newcred->cr_groups[0] != newcred->cr_rgid) && 970 newcred->cr_svgid != newcred->cr_groups[0]) { 971 change_svgid(newcred, newcred->cr_groups[0]); 972 setsugid(p); 973 } 974 p->p_ucred = newcred; 975 PROC_UNLOCK(p); 976 crfree(oldcred); 977 return (0); 978 979fail: 980 PROC_UNLOCK(p); 981 crfree(newcred); 982 return (error); 983} 984 985/* 986 * setresuid(ruid, euid, suid) is like setreuid except control over the saved 987 * uid is explicit. 988 */ 989#ifndef _SYS_SYSPROTO_H_ 990struct setresuid_args { 991 uid_t ruid; 992 uid_t euid; 993 uid_t suid; 994}; 995#endif 996/* ARGSUSED */ 997int 998setresuid(register struct thread *td, struct setresuid_args *uap) 999{ 1000 struct proc *p = td->td_proc; 1001 struct ucred *newcred, *oldcred; 1002 uid_t euid, ruid, suid; 1003 struct uidinfo *euip, *ruip; 1004 int error; 1005 1006 euid = uap->euid; 1007 ruid = uap->ruid; 1008 suid = uap->suid; 1009 AUDIT_ARG(euid, euid); 1010 AUDIT_ARG(ruid, ruid); 1011 AUDIT_ARG(suid, suid); 1012 newcred = crget(); 1013 euip = uifind(euid); 1014 ruip = uifind(ruid); 1015 PROC_LOCK(p);
| 965 if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { 966 change_egid(newcred, egid); 967 setsugid(p); 968 } 969 if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { 970 change_rgid(newcred, rgid); 971 setsugid(p); 972 } 973 if ((rgid != (gid_t)-1 || newcred->cr_groups[0] != newcred->cr_rgid) && 974 newcred->cr_svgid != newcred->cr_groups[0]) { 975 change_svgid(newcred, newcred->cr_groups[0]); 976 setsugid(p); 977 } 978 p->p_ucred = newcred; 979 PROC_UNLOCK(p); 980 crfree(oldcred); 981 return (0); 982 983fail: 984 PROC_UNLOCK(p); 985 crfree(newcred); 986 return (error); 987} 988 989/* 990 * setresuid(ruid, euid, suid) is like setreuid except control over the saved 991 * uid is explicit. 992 */ 993#ifndef _SYS_SYSPROTO_H_ 994struct setresuid_args { 995 uid_t ruid; 996 uid_t euid; 997 uid_t suid; 998}; 999#endif 1000/* ARGSUSED */ 1001int 1002setresuid(register struct thread *td, struct setresuid_args *uap) 1003{ 1004 struct proc *p = td->td_proc; 1005 struct ucred *newcred, *oldcred; 1006 uid_t euid, ruid, suid; 1007 struct uidinfo *euip, *ruip; 1008 int error; 1009 1010 euid = uap->euid; 1011 ruid = uap->ruid; 1012 suid = uap->suid; 1013 AUDIT_ARG(euid, euid); 1014 AUDIT_ARG(ruid, ruid); 1015 AUDIT_ARG(suid, suid); 1016 newcred = crget(); 1017 euip = uifind(euid); 1018 ruip = uifind(ruid); 1019 PROC_LOCK(p);
|
1016 oldcred = p->p_ucred;
| 1020 oldcred = crcopysafe(p, newcred);
|
1017 1018#ifdef MAC 1019 error = mac_cred_check_setresuid(oldcred, ruid, euid, suid); 1020 if (error) 1021 goto fail; 1022#endif 1023 1024 if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && 1025 ruid != oldcred->cr_svuid && 1026 ruid != oldcred->cr_uid) || 1027 (euid != (uid_t)-1 && euid != oldcred->cr_ruid && 1028 euid != oldcred->cr_svuid && 1029 euid != oldcred->cr_uid) || 1030 (suid != (uid_t)-1 && suid != oldcred->cr_ruid && 1031 suid != oldcred->cr_svuid && 1032 suid != oldcred->cr_uid)) && 1033 (error = priv_check_cred(oldcred, PRIV_CRED_SETRESUID, 0)) != 0) 1034 goto fail; 1035
| 1021 1022#ifdef MAC 1023 error = mac_cred_check_setresuid(oldcred, ruid, euid, suid); 1024 if (error) 1025 goto fail; 1026#endif 1027 1028 if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && 1029 ruid != oldcred->cr_svuid && 1030 ruid != oldcred->cr_uid) || 1031 (euid != (uid_t)-1 && euid != oldcred->cr_ruid && 1032 euid != oldcred->cr_svuid && 1033 euid != oldcred->cr_uid) || 1034 (suid != (uid_t)-1 && suid != oldcred->cr_ruid && 1035 suid != oldcred->cr_svuid && 1036 suid != oldcred->cr_uid)) && 1037 (error = priv_check_cred(oldcred, PRIV_CRED_SETRESUID, 0)) != 0) 1038 goto fail; 1039
|
1036 crcopy(newcred, oldcred);
| |
1037 if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { 1038 change_euid(newcred, euip); 1039 setsugid(p); 1040 } 1041 if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { 1042 change_ruid(newcred, ruip); 1043 setsugid(p); 1044 } 1045 if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) { 1046 change_svuid(newcred, suid); 1047 setsugid(p); 1048 } 1049 p->p_ucred = newcred; 1050 PROC_UNLOCK(p); 1051 uifree(ruip); 1052 uifree(euip); 1053 crfree(oldcred); 1054 return (0); 1055 1056fail: 1057 PROC_UNLOCK(p); 1058 uifree(ruip); 1059 uifree(euip); 1060 crfree(newcred); 1061 return (error); 1062 1063} 1064 1065/* 1066 * setresgid(rgid, egid, sgid) is like setregid except control over the saved 1067 * gid is explicit. 1068 */ 1069#ifndef _SYS_SYSPROTO_H_ 1070struct setresgid_args { 1071 gid_t rgid; 1072 gid_t egid; 1073 gid_t sgid; 1074}; 1075#endif 1076/* ARGSUSED */ 1077int 1078setresgid(register struct thread *td, struct setresgid_args *uap) 1079{ 1080 struct proc *p = td->td_proc; 1081 struct ucred *newcred, *oldcred; 1082 gid_t egid, rgid, sgid; 1083 int error; 1084 1085 egid = uap->egid; 1086 rgid = uap->rgid; 1087 sgid = uap->sgid; 1088 AUDIT_ARG(egid, egid); 1089 AUDIT_ARG(rgid, rgid); 1090 AUDIT_ARG(sgid, sgid); 1091 newcred = crget(); 1092 PROC_LOCK(p);
| 1040 if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { 1041 change_euid(newcred, euip); 1042 setsugid(p); 1043 } 1044 if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { 1045 change_ruid(newcred, ruip); 1046 setsugid(p); 1047 } 1048 if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) { 1049 change_svuid(newcred, suid); 1050 setsugid(p); 1051 } 1052 p->p_ucred = newcred; 1053 PROC_UNLOCK(p); 1054 uifree(ruip); 1055 uifree(euip); 1056 crfree(oldcred); 1057 return (0); 1058 1059fail: 1060 PROC_UNLOCK(p); 1061 uifree(ruip); 1062 uifree(euip); 1063 crfree(newcred); 1064 return (error); 1065 1066} 1067 1068/* 1069 * setresgid(rgid, egid, sgid) is like setregid except control over the saved 1070 * gid is explicit. 1071 */ 1072#ifndef _SYS_SYSPROTO_H_ 1073struct setresgid_args { 1074 gid_t rgid; 1075 gid_t egid; 1076 gid_t sgid; 1077}; 1078#endif 1079/* ARGSUSED */ 1080int 1081setresgid(register struct thread *td, struct setresgid_args *uap) 1082{ 1083 struct proc *p = td->td_proc; 1084 struct ucred *newcred, *oldcred; 1085 gid_t egid, rgid, sgid; 1086 int error; 1087 1088 egid = uap->egid; 1089 rgid = uap->rgid; 1090 sgid = uap->sgid; 1091 AUDIT_ARG(egid, egid); 1092 AUDIT_ARG(rgid, rgid); 1093 AUDIT_ARG(sgid, sgid); 1094 newcred = crget(); 1095 PROC_LOCK(p);
|
1093 oldcred = p->p_ucred;
| 1096 oldcred = crcopysafe(p, newcred);
|
1094 1095#ifdef MAC 1096 error = mac_cred_check_setresgid(oldcred, rgid, egid, sgid); 1097 if (error) 1098 goto fail; 1099#endif 1100 1101 if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && 1102 rgid != oldcred->cr_svgid && 1103 rgid != oldcred->cr_groups[0]) || 1104 (egid != (gid_t)-1 && egid != oldcred->cr_rgid && 1105 egid != oldcred->cr_svgid && 1106 egid != oldcred->cr_groups[0]) || 1107 (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid && 1108 sgid != oldcred->cr_svgid && 1109 sgid != oldcred->cr_groups[0])) && 1110 (error = priv_check_cred(oldcred, PRIV_CRED_SETRESGID, 0)) != 0) 1111 goto fail; 1112
| 1097 1098#ifdef MAC 1099 error = mac_cred_check_setresgid(oldcred, rgid, egid, sgid); 1100 if (error) 1101 goto fail; 1102#endif 1103 1104 if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && 1105 rgid != oldcred->cr_svgid && 1106 rgid != oldcred->cr_groups[0]) || 1107 (egid != (gid_t)-1 && egid != oldcred->cr_rgid && 1108 egid != oldcred->cr_svgid && 1109 egid != oldcred->cr_groups[0]) || 1110 (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid && 1111 sgid != oldcred->cr_svgid && 1112 sgid != oldcred->cr_groups[0])) && 1113 (error = priv_check_cred(oldcred, PRIV_CRED_SETRESGID, 0)) != 0) 1114 goto fail; 1115
|
1113 crcopy(newcred, oldcred);
| |
1114 if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { 1115 change_egid(newcred, egid); 1116 setsugid(p); 1117 } 1118 if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { 1119 change_rgid(newcred, rgid); 1120 setsugid(p); 1121 } 1122 if (sgid != (gid_t)-1 && oldcred->cr_svgid != sgid) { 1123 change_svgid(newcred, sgid); 1124 setsugid(p); 1125 } 1126 p->p_ucred = newcred; 1127 PROC_UNLOCK(p); 1128 crfree(oldcred); 1129 return (0); 1130 1131fail: 1132 PROC_UNLOCK(p); 1133 crfree(newcred); 1134 return (error); 1135} 1136 1137#ifndef _SYS_SYSPROTO_H_ 1138struct getresuid_args { 1139 uid_t *ruid; 1140 uid_t *euid; 1141 uid_t *suid; 1142}; 1143#endif 1144/* ARGSUSED */ 1145int 1146getresuid(register struct thread *td, struct getresuid_args *uap) 1147{ 1148 struct ucred *cred; 1149 int error1 = 0, error2 = 0, error3 = 0; 1150 1151 cred = td->td_ucred; 1152 if (uap->ruid) 1153 error1 = copyout(&cred->cr_ruid, 1154 uap->ruid, sizeof(cred->cr_ruid)); 1155 if (uap->euid) 1156 error2 = copyout(&cred->cr_uid, 1157 uap->euid, sizeof(cred->cr_uid)); 1158 if (uap->suid) 1159 error3 = copyout(&cred->cr_svuid, 1160 uap->suid, sizeof(cred->cr_svuid)); 1161 return (error1 ? error1 : error2 ? error2 : error3); 1162} 1163 1164#ifndef _SYS_SYSPROTO_H_ 1165struct getresgid_args { 1166 gid_t *rgid; 1167 gid_t *egid; 1168 gid_t *sgid; 1169}; 1170#endif 1171/* ARGSUSED */ 1172int 1173getresgid(register struct thread *td, struct getresgid_args *uap) 1174{ 1175 struct ucred *cred; 1176 int error1 = 0, error2 = 0, error3 = 0; 1177 1178 cred = td->td_ucred; 1179 if (uap->rgid) 1180 error1 = copyout(&cred->cr_rgid, 1181 uap->rgid, sizeof(cred->cr_rgid)); 1182 if (uap->egid) 1183 error2 = copyout(&cred->cr_groups[0], 1184 uap->egid, sizeof(cred->cr_groups[0])); 1185 if (uap->sgid) 1186 error3 = copyout(&cred->cr_svgid, 1187 uap->sgid, sizeof(cred->cr_svgid)); 1188 return (error1 ? error1 : error2 ? error2 : error3); 1189} 1190 1191#ifndef _SYS_SYSPROTO_H_ 1192struct issetugid_args { 1193 int dummy; 1194}; 1195#endif 1196/* ARGSUSED */ 1197int 1198issetugid(register struct thread *td, struct issetugid_args *uap) 1199{ 1200 struct proc *p = td->td_proc; 1201 1202 /* 1203 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, 1204 * we use P_SUGID because we consider changing the owners as 1205 * "tainting" as well. 1206 * This is significant for procs that start as root and "become" 1207 * a user without an exec - programs cannot know *everything* 1208 * that libc *might* have put in their data segment. 1209 */ 1210 PROC_LOCK(p); 1211 td->td_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0; 1212 PROC_UNLOCK(p); 1213 return (0); 1214} 1215 1216int 1217__setugid(struct thread *td, struct __setugid_args *uap) 1218{ 1219#ifdef REGRESSION 1220 struct proc *p; 1221 1222 p = td->td_proc; 1223 switch (uap->flag) { 1224 case 0: 1225 PROC_LOCK(p); 1226 p->p_flag &= ~P_SUGID; 1227 PROC_UNLOCK(p); 1228 return (0); 1229 case 1: 1230 PROC_LOCK(p); 1231 p->p_flag |= P_SUGID; 1232 PROC_UNLOCK(p); 1233 return (0); 1234 default: 1235 return (EINVAL); 1236 } 1237#else /* !REGRESSION */ 1238 1239 return (ENOSYS); 1240#endif /* REGRESSION */ 1241} 1242 1243/* 1244 * Check if gid is a member of the group set. 1245 */ 1246int 1247groupmember(gid_t gid, struct ucred *cred) 1248{ 1249 register gid_t *gp; 1250 gid_t *egp; 1251 1252 egp = &(cred->cr_groups[cred->cr_ngroups]); 1253 for (gp = cred->cr_groups; gp < egp; gp++) 1254 if (*gp == gid) 1255 return (1); 1256 return (0); 1257} 1258 1259/* 1260 * Test the active securelevel against a given level. securelevel_gt() 1261 * implements (securelevel > level). securelevel_ge() implements 1262 * (securelevel >= level). Note that the logic is inverted -- these 1263 * functions return EPERM on "success" and 0 on "failure". 1264 * 1265 * Due to care taken when setting the securelevel, we know that no jail will 1266 * be less secure that its parent (or the physical system), so it is sufficient 1267 * to test the current jail only. 1268 * 1269 * XXXRW: Possibly since this has to do with privilege, it should move to 1270 * kern_priv.c. 1271 */ 1272int 1273securelevel_gt(struct ucred *cr, int level) 1274{ 1275 1276 return (cr->cr_prison->pr_securelevel > level ? EPERM : 0); 1277} 1278 1279int 1280securelevel_ge(struct ucred *cr, int level) 1281{ 1282 1283 return (cr->cr_prison->pr_securelevel >= level ? EPERM : 0); 1284} 1285 1286/* 1287 * 'see_other_uids' determines whether or not visibility of processes 1288 * and sockets with credentials holding different real uids is possible 1289 * using a variety of system MIBs. 1290 * XXX: data declarations should be together near the beginning of the file. 1291 */ 1292static int see_other_uids = 1; 1293SYSCTL_INT(_security_bsd, OID_AUTO, see_other_uids, CTLFLAG_RW, 1294 &see_other_uids, 0, 1295 "Unprivileged processes may see subjects/objects with different real uid"); 1296 1297/*- 1298 * Determine if u1 "can see" the subject specified by u2, according to the 1299 * 'see_other_uids' policy. 1300 * Returns: 0 for permitted, ESRCH otherwise 1301 * Locks: none 1302 * References: *u1 and *u2 must not change during the call 1303 * u1 may equal u2, in which case only one reference is required 1304 */ 1305static int 1306cr_seeotheruids(struct ucred *u1, struct ucred *u2) 1307{ 1308 1309 if (!see_other_uids && u1->cr_ruid != u2->cr_ruid) { 1310 if (priv_check_cred(u1, PRIV_SEEOTHERUIDS, 0) != 0) 1311 return (ESRCH); 1312 } 1313 return (0); 1314} 1315 1316/* 1317 * 'see_other_gids' determines whether or not visibility of processes 1318 * and sockets with credentials holding different real gids is possible 1319 * using a variety of system MIBs. 1320 * XXX: data declarations should be together near the beginning of the file. 1321 */ 1322static int see_other_gids = 1; 1323SYSCTL_INT(_security_bsd, OID_AUTO, see_other_gids, CTLFLAG_RW, 1324 &see_other_gids, 0, 1325 "Unprivileged processes may see subjects/objects with different real gid"); 1326 1327/* 1328 * Determine if u1 can "see" the subject specified by u2, according to the 1329 * 'see_other_gids' policy. 1330 * Returns: 0 for permitted, ESRCH otherwise 1331 * Locks: none 1332 * References: *u1 and *u2 must not change during the call 1333 * u1 may equal u2, in which case only one reference is required 1334 */ 1335static int 1336cr_seeothergids(struct ucred *u1, struct ucred *u2) 1337{ 1338 int i, match; 1339 1340 if (!see_other_gids) { 1341 match = 0; 1342 for (i = 0; i < u1->cr_ngroups; i++) { 1343 if (groupmember(u1->cr_groups[i], u2)) 1344 match = 1; 1345 if (match) 1346 break; 1347 } 1348 if (!match) { 1349 if (priv_check_cred(u1, PRIV_SEEOTHERGIDS, 0) != 0) 1350 return (ESRCH); 1351 } 1352 } 1353 return (0); 1354} 1355 1356/*- 1357 * Determine if u1 "can see" the subject specified by u2. 1358 * Returns: 0 for permitted, an errno value otherwise 1359 * Locks: none 1360 * References: *u1 and *u2 must not change during the call 1361 * u1 may equal u2, in which case only one reference is required 1362 */ 1363int 1364cr_cansee(struct ucred *u1, struct ucred *u2) 1365{ 1366 int error; 1367 1368 if ((error = prison_check(u1, u2))) 1369 return (error); 1370#ifdef MAC 1371 if ((error = mac_cred_check_visible(u1, u2))) 1372 return (error); 1373#endif 1374 if ((error = cr_seeotheruids(u1, u2))) 1375 return (error); 1376 if ((error = cr_seeothergids(u1, u2))) 1377 return (error); 1378 return (0); 1379} 1380 1381/*- 1382 * Determine if td "can see" the subject specified by p. 1383 * Returns: 0 for permitted, an errno value otherwise 1384 * Locks: Sufficient locks to protect p->p_ucred must be held. td really 1385 * should be curthread. 1386 * References: td and p must be valid for the lifetime of the call 1387 */ 1388int 1389p_cansee(struct thread *td, struct proc *p) 1390{ 1391 1392 /* Wrap cr_cansee() for all functionality. */ 1393 KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1394 PROC_LOCK_ASSERT(p, MA_OWNED); 1395 return (cr_cansee(td->td_ucred, p->p_ucred)); 1396} 1397 1398/* 1399 * 'conservative_signals' prevents the delivery of a broad class of 1400 * signals by unprivileged processes to processes that have changed their 1401 * credentials since the last invocation of execve(). This can prevent 1402 * the leakage of cached information or retained privileges as a result 1403 * of a common class of signal-related vulnerabilities. However, this 1404 * may interfere with some applications that expect to be able to 1405 * deliver these signals to peer processes after having given up 1406 * privilege. 1407 */ 1408static int conservative_signals = 1; 1409SYSCTL_INT(_security_bsd, OID_AUTO, conservative_signals, CTLFLAG_RW, 1410 &conservative_signals, 0, "Unprivileged processes prevented from " 1411 "sending certain signals to processes whose credentials have changed"); 1412/*- 1413 * Determine whether cred may deliver the specified signal to proc. 1414 * Returns: 0 for permitted, an errno value otherwise. 1415 * Locks: A lock must be held for proc. 1416 * References: cred and proc must be valid for the lifetime of the call. 1417 */ 1418int 1419cr_cansignal(struct ucred *cred, struct proc *proc, int signum) 1420{ 1421 int error; 1422 1423 PROC_LOCK_ASSERT(proc, MA_OWNED); 1424 /* 1425 * Jail semantics limit the scope of signalling to proc in the 1426 * same jail as cred, if cred is in jail. 1427 */ 1428 error = prison_check(cred, proc->p_ucred); 1429 if (error) 1430 return (error); 1431#ifdef MAC 1432 if ((error = mac_proc_check_signal(cred, proc, signum))) 1433 return (error); 1434#endif 1435 if ((error = cr_seeotheruids(cred, proc->p_ucred))) 1436 return (error); 1437 if ((error = cr_seeothergids(cred, proc->p_ucred))) 1438 return (error); 1439 1440 /* 1441 * UNIX signal semantics depend on the status of the P_SUGID 1442 * bit on the target process. If the bit is set, then additional 1443 * restrictions are placed on the set of available signals. 1444 */ 1445 if (conservative_signals && (proc->p_flag & P_SUGID)) { 1446 switch (signum) { 1447 case 0: 1448 case SIGKILL: 1449 case SIGINT: 1450 case SIGTERM: 1451 case SIGALRM: 1452 case SIGSTOP: 1453 case SIGTTIN: 1454 case SIGTTOU: 1455 case SIGTSTP: 1456 case SIGHUP: 1457 case SIGUSR1: 1458 case SIGUSR2: 1459 /* 1460 * Generally, permit job and terminal control 1461 * signals. 1462 */ 1463 break; 1464 default: 1465 /* Not permitted without privilege. */ 1466 error = priv_check_cred(cred, PRIV_SIGNAL_SUGID, 0); 1467 if (error) 1468 return (error); 1469 } 1470 } 1471 1472 /* 1473 * Generally, the target credential's ruid or svuid must match the 1474 * subject credential's ruid or euid. 1475 */ 1476 if (cred->cr_ruid != proc->p_ucred->cr_ruid && 1477 cred->cr_ruid != proc->p_ucred->cr_svuid && 1478 cred->cr_uid != proc->p_ucred->cr_ruid && 1479 cred->cr_uid != proc->p_ucred->cr_svuid) { 1480 error = priv_check_cred(cred, PRIV_SIGNAL_DIFFCRED, 0); 1481 if (error) 1482 return (error); 1483 } 1484 1485 return (0); 1486} 1487 1488/*- 1489 * Determine whether td may deliver the specified signal to p. 1490 * Returns: 0 for permitted, an errno value otherwise 1491 * Locks: Sufficient locks to protect various components of td and p 1492 * must be held. td must be curthread, and a lock must be 1493 * held for p. 1494 * References: td and p must be valid for the lifetime of the call 1495 */ 1496int 1497p_cansignal(struct thread *td, struct proc *p, int signum) 1498{ 1499 1500 KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1501 PROC_LOCK_ASSERT(p, MA_OWNED); 1502 if (td->td_proc == p) 1503 return (0); 1504 1505 /* 1506 * UNIX signalling semantics require that processes in the same 1507 * session always be able to deliver SIGCONT to one another, 1508 * overriding the remaining protections. 1509 */ 1510 /* XXX: This will require an additional lock of some sort. */ 1511 if (signum == SIGCONT && td->td_proc->p_session == p->p_session) 1512 return (0); 1513 /* 1514 * Some compat layers use SIGTHR and higher signals for 1515 * communication between different kernel threads of the same 1516 * process, so that they expect that it's always possible to 1517 * deliver them, even for suid applications where cr_cansignal() can 1518 * deny such ability for security consideration. It should be 1519 * pretty safe to do since the only way to create two processes 1520 * with the same p_leader is via rfork(2). 1521 */ 1522 if (td->td_proc->p_leader != NULL && signum >= SIGTHR && 1523 signum < SIGTHR + 4 && td->td_proc->p_leader == p->p_leader) 1524 return (0); 1525 1526 return (cr_cansignal(td->td_ucred, p, signum)); 1527} 1528 1529/*- 1530 * Determine whether td may reschedule p. 1531 * Returns: 0 for permitted, an errno value otherwise 1532 * Locks: Sufficient locks to protect various components of td and p 1533 * must be held. td must be curthread, and a lock must 1534 * be held for p. 1535 * References: td and p must be valid for the lifetime of the call 1536 */ 1537int 1538p_cansched(struct thread *td, struct proc *p) 1539{ 1540 int error; 1541 1542 KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1543 PROC_LOCK_ASSERT(p, MA_OWNED); 1544 if (td->td_proc == p) 1545 return (0); 1546 if ((error = prison_check(td->td_ucred, p->p_ucred))) 1547 return (error); 1548#ifdef MAC 1549 if ((error = mac_proc_check_sched(td->td_ucred, p))) 1550 return (error); 1551#endif 1552 if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred))) 1553 return (error); 1554 if ((error = cr_seeothergids(td->td_ucred, p->p_ucred))) 1555 return (error); 1556 if (td->td_ucred->cr_ruid != p->p_ucred->cr_ruid && 1557 td->td_ucred->cr_uid != p->p_ucred->cr_ruid) { 1558 error = priv_check(td, PRIV_SCHED_DIFFCRED); 1559 if (error) 1560 return (error); 1561 } 1562 return (0); 1563} 1564 1565/* 1566 * The 'unprivileged_proc_debug' flag may be used to disable a variety of 1567 * unprivileged inter-process debugging services, including some procfs 1568 * functionality, ptrace(), and ktrace(). In the past, inter-process 1569 * debugging has been involved in a variety of security problems, and sites 1570 * not requiring the service might choose to disable it when hardening 1571 * systems. 1572 * 1573 * XXX: Should modifying and reading this variable require locking? 1574 * XXX: data declarations should be together near the beginning of the file. 1575 */ 1576static int unprivileged_proc_debug = 1; 1577SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_proc_debug, CTLFLAG_RW, 1578 &unprivileged_proc_debug, 0, 1579 "Unprivileged processes may use process debugging facilities"); 1580 1581/*- 1582 * Determine whether td may debug p. 1583 * Returns: 0 for permitted, an errno value otherwise 1584 * Locks: Sufficient locks to protect various components of td and p 1585 * must be held. td must be curthread, and a lock must 1586 * be held for p. 1587 * References: td and p must be valid for the lifetime of the call 1588 */ 1589int 1590p_candebug(struct thread *td, struct proc *p) 1591{ 1592 int credentialchanged, error, grpsubset, i, uidsubset; 1593 1594 KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1595 PROC_LOCK_ASSERT(p, MA_OWNED); 1596 if (!unprivileged_proc_debug) { 1597 error = priv_check(td, PRIV_DEBUG_UNPRIV); 1598 if (error) 1599 return (error); 1600 } 1601 if (td->td_proc == p) 1602 return (0); 1603 if ((error = prison_check(td->td_ucred, p->p_ucred))) 1604 return (error); 1605#ifdef MAC 1606 if ((error = mac_proc_check_debug(td->td_ucred, p))) 1607 return (error); 1608#endif 1609 if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred))) 1610 return (error); 1611 if ((error = cr_seeothergids(td->td_ucred, p->p_ucred))) 1612 return (error); 1613 1614 /* 1615 * Is p's group set a subset of td's effective group set? This 1616 * includes p's egid, group access list, rgid, and svgid. 1617 */ 1618 grpsubset = 1; 1619 for (i = 0; i < p->p_ucred->cr_ngroups; i++) { 1620 if (!groupmember(p->p_ucred->cr_groups[i], td->td_ucred)) { 1621 grpsubset = 0; 1622 break; 1623 } 1624 } 1625 grpsubset = grpsubset && 1626 groupmember(p->p_ucred->cr_rgid, td->td_ucred) && 1627 groupmember(p->p_ucred->cr_svgid, td->td_ucred); 1628 1629 /* 1630 * Are the uids present in p's credential equal to td's 1631 * effective uid? This includes p's euid, svuid, and ruid. 1632 */ 1633 uidsubset = (td->td_ucred->cr_uid == p->p_ucred->cr_uid && 1634 td->td_ucred->cr_uid == p->p_ucred->cr_svuid && 1635 td->td_ucred->cr_uid == p->p_ucred->cr_ruid); 1636 1637 /* 1638 * Has the credential of the process changed since the last exec()? 1639 */ 1640 credentialchanged = (p->p_flag & P_SUGID); 1641 1642 /* 1643 * If p's gids aren't a subset, or the uids aren't a subset, 1644 * or the credential has changed, require appropriate privilege 1645 * for td to debug p. 1646 */ 1647 if (!grpsubset || !uidsubset) { 1648 error = priv_check(td, PRIV_DEBUG_DIFFCRED); 1649 if (error) 1650 return (error); 1651 } 1652 1653 if (credentialchanged) { 1654 error = priv_check(td, PRIV_DEBUG_SUGID); 1655 if (error) 1656 return (error); 1657 } 1658 1659 /* Can't trace init when securelevel > 0. */ 1660 if (p == initproc) { 1661 error = securelevel_gt(td->td_ucred, 0); 1662 if (error) 1663 return (error); 1664 } 1665 1666 /* 1667 * Can't trace a process that's currently exec'ing. 1668 * 1669 * XXX: Note, this is not a security policy decision, it's a 1670 * basic correctness/functionality decision. Therefore, this check 1671 * should be moved to the caller's of p_candebug(). 1672 */ 1673 if ((p->p_flag & P_INEXEC) != 0) 1674 return (EBUSY); 1675 1676 return (0); 1677} 1678 1679/*- 1680 * Determine whether the subject represented by cred can "see" a socket. 1681 * Returns: 0 for permitted, ENOENT otherwise. 1682 */ 1683int 1684cr_canseesocket(struct ucred *cred, struct socket *so) 1685{ 1686 int error; 1687 1688 error = prison_check(cred, so->so_cred); 1689 if (error) 1690 return (ENOENT); 1691#ifdef MAC 1692 error = mac_socket_check_visible(cred, so); 1693 if (error) 1694 return (error); 1695#endif 1696 if (cr_seeotheruids(cred, so->so_cred)) 1697 return (ENOENT); 1698 if (cr_seeothergids(cred, so->so_cred)) 1699 return (ENOENT); 1700 1701 return (0); 1702} 1703 1704#if defined(INET) || defined(INET6) 1705/*- 1706 * Determine whether the subject represented by cred can "see" a socket. 1707 * Returns: 0 for permitted, ENOENT otherwise. 1708 */ 1709int 1710cr_canseeinpcb(struct ucred *cred, struct inpcb *inp) 1711{ 1712 int error; 1713 1714 error = prison_check(cred, inp->inp_cred); 1715 if (error) 1716 return (ENOENT); 1717#ifdef MAC 1718 INP_LOCK_ASSERT(inp); 1719 error = mac_inpcb_check_visible(cred, inp); 1720 if (error) 1721 return (error); 1722#endif 1723 if (cr_seeotheruids(cred, inp->inp_cred)) 1724 return (ENOENT); 1725 if (cr_seeothergids(cred, inp->inp_cred)) 1726 return (ENOENT); 1727 1728 return (0); 1729} 1730#endif 1731 1732/*- 1733 * Determine whether td can wait for the exit of p. 1734 * Returns: 0 for permitted, an errno value otherwise 1735 * Locks: Sufficient locks to protect various components of td and p 1736 * must be held. td must be curthread, and a lock must 1737 * be held for p. 1738 * References: td and p must be valid for the lifetime of the call 1739 1740 */ 1741int 1742p_canwait(struct thread *td, struct proc *p) 1743{ 1744 int error; 1745 1746 KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1747 PROC_LOCK_ASSERT(p, MA_OWNED); 1748 if ( 1749#ifdef VIMAGE /* XXX temporary until struct vimage goes away */ 1750 !vi_child_of(TD_TO_VIMAGE(td), P_TO_VIMAGE(p)) && 1751#endif 1752 (error = prison_check(td->td_ucred, p->p_ucred))) 1753 return (error); 1754#ifdef MAC 1755 if ((error = mac_proc_check_wait(td->td_ucred, p))) 1756 return (error); 1757#endif 1758#if 0 1759 /* XXXMAC: This could have odd effects on some shells. */ 1760 if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred))) 1761 return (error); 1762#endif 1763 1764 return (0); 1765} 1766 1767/* 1768 * Allocate a zeroed cred structure. 1769 */ 1770struct ucred * 1771crget(void) 1772{ 1773 register struct ucred *cr; 1774 1775 cr = malloc(sizeof(*cr), M_CRED, M_WAITOK | M_ZERO); 1776 refcount_init(&cr->cr_ref, 1); 1777#ifdef AUDIT 1778 audit_cred_init(cr); 1779#endif 1780#ifdef MAC 1781 mac_cred_init(cr); 1782#endif
| 1116 if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { 1117 change_egid(newcred, egid); 1118 setsugid(p); 1119 } 1120 if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { 1121 change_rgid(newcred, rgid); 1122 setsugid(p); 1123 } 1124 if (sgid != (gid_t)-1 && oldcred->cr_svgid != sgid) { 1125 change_svgid(newcred, sgid); 1126 setsugid(p); 1127 } 1128 p->p_ucred = newcred; 1129 PROC_UNLOCK(p); 1130 crfree(oldcred); 1131 return (0); 1132 1133fail: 1134 PROC_UNLOCK(p); 1135 crfree(newcred); 1136 return (error); 1137} 1138 1139#ifndef _SYS_SYSPROTO_H_ 1140struct getresuid_args { 1141 uid_t *ruid; 1142 uid_t *euid; 1143 uid_t *suid; 1144}; 1145#endif 1146/* ARGSUSED */ 1147int 1148getresuid(register struct thread *td, struct getresuid_args *uap) 1149{ 1150 struct ucred *cred; 1151 int error1 = 0, error2 = 0, error3 = 0; 1152 1153 cred = td->td_ucred; 1154 if (uap->ruid) 1155 error1 = copyout(&cred->cr_ruid, 1156 uap->ruid, sizeof(cred->cr_ruid)); 1157 if (uap->euid) 1158 error2 = copyout(&cred->cr_uid, 1159 uap->euid, sizeof(cred->cr_uid)); 1160 if (uap->suid) 1161 error3 = copyout(&cred->cr_svuid, 1162 uap->suid, sizeof(cred->cr_svuid)); 1163 return (error1 ? error1 : error2 ? error2 : error3); 1164} 1165 1166#ifndef _SYS_SYSPROTO_H_ 1167struct getresgid_args { 1168 gid_t *rgid; 1169 gid_t *egid; 1170 gid_t *sgid; 1171}; 1172#endif 1173/* ARGSUSED */ 1174int 1175getresgid(register struct thread *td, struct getresgid_args *uap) 1176{ 1177 struct ucred *cred; 1178 int error1 = 0, error2 = 0, error3 = 0; 1179 1180 cred = td->td_ucred; 1181 if (uap->rgid) 1182 error1 = copyout(&cred->cr_rgid, 1183 uap->rgid, sizeof(cred->cr_rgid)); 1184 if (uap->egid) 1185 error2 = copyout(&cred->cr_groups[0], 1186 uap->egid, sizeof(cred->cr_groups[0])); 1187 if (uap->sgid) 1188 error3 = copyout(&cred->cr_svgid, 1189 uap->sgid, sizeof(cred->cr_svgid)); 1190 return (error1 ? error1 : error2 ? error2 : error3); 1191} 1192 1193#ifndef _SYS_SYSPROTO_H_ 1194struct issetugid_args { 1195 int dummy; 1196}; 1197#endif 1198/* ARGSUSED */ 1199int 1200issetugid(register struct thread *td, struct issetugid_args *uap) 1201{ 1202 struct proc *p = td->td_proc; 1203 1204 /* 1205 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, 1206 * we use P_SUGID because we consider changing the owners as 1207 * "tainting" as well. 1208 * This is significant for procs that start as root and "become" 1209 * a user without an exec - programs cannot know *everything* 1210 * that libc *might* have put in their data segment. 1211 */ 1212 PROC_LOCK(p); 1213 td->td_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0; 1214 PROC_UNLOCK(p); 1215 return (0); 1216} 1217 1218int 1219__setugid(struct thread *td, struct __setugid_args *uap) 1220{ 1221#ifdef REGRESSION 1222 struct proc *p; 1223 1224 p = td->td_proc; 1225 switch (uap->flag) { 1226 case 0: 1227 PROC_LOCK(p); 1228 p->p_flag &= ~P_SUGID; 1229 PROC_UNLOCK(p); 1230 return (0); 1231 case 1: 1232 PROC_LOCK(p); 1233 p->p_flag |= P_SUGID; 1234 PROC_UNLOCK(p); 1235 return (0); 1236 default: 1237 return (EINVAL); 1238 } 1239#else /* !REGRESSION */ 1240 1241 return (ENOSYS); 1242#endif /* REGRESSION */ 1243} 1244 1245/* 1246 * Check if gid is a member of the group set. 1247 */ 1248int 1249groupmember(gid_t gid, struct ucred *cred) 1250{ 1251 register gid_t *gp; 1252 gid_t *egp; 1253 1254 egp = &(cred->cr_groups[cred->cr_ngroups]); 1255 for (gp = cred->cr_groups; gp < egp; gp++) 1256 if (*gp == gid) 1257 return (1); 1258 return (0); 1259} 1260 1261/* 1262 * Test the active securelevel against a given level. securelevel_gt() 1263 * implements (securelevel > level). securelevel_ge() implements 1264 * (securelevel >= level). Note that the logic is inverted -- these 1265 * functions return EPERM on "success" and 0 on "failure". 1266 * 1267 * Due to care taken when setting the securelevel, we know that no jail will 1268 * be less secure that its parent (or the physical system), so it is sufficient 1269 * to test the current jail only. 1270 * 1271 * XXXRW: Possibly since this has to do with privilege, it should move to 1272 * kern_priv.c. 1273 */ 1274int 1275securelevel_gt(struct ucred *cr, int level) 1276{ 1277 1278 return (cr->cr_prison->pr_securelevel > level ? EPERM : 0); 1279} 1280 1281int 1282securelevel_ge(struct ucred *cr, int level) 1283{ 1284 1285 return (cr->cr_prison->pr_securelevel >= level ? EPERM : 0); 1286} 1287 1288/* 1289 * 'see_other_uids' determines whether or not visibility of processes 1290 * and sockets with credentials holding different real uids is possible 1291 * using a variety of system MIBs. 1292 * XXX: data declarations should be together near the beginning of the file. 1293 */ 1294static int see_other_uids = 1; 1295SYSCTL_INT(_security_bsd, OID_AUTO, see_other_uids, CTLFLAG_RW, 1296 &see_other_uids, 0, 1297 "Unprivileged processes may see subjects/objects with different real uid"); 1298 1299/*- 1300 * Determine if u1 "can see" the subject specified by u2, according to the 1301 * 'see_other_uids' policy. 1302 * Returns: 0 for permitted, ESRCH otherwise 1303 * Locks: none 1304 * References: *u1 and *u2 must not change during the call 1305 * u1 may equal u2, in which case only one reference is required 1306 */ 1307static int 1308cr_seeotheruids(struct ucred *u1, struct ucred *u2) 1309{ 1310 1311 if (!see_other_uids && u1->cr_ruid != u2->cr_ruid) { 1312 if (priv_check_cred(u1, PRIV_SEEOTHERUIDS, 0) != 0) 1313 return (ESRCH); 1314 } 1315 return (0); 1316} 1317 1318/* 1319 * 'see_other_gids' determines whether or not visibility of processes 1320 * and sockets with credentials holding different real gids is possible 1321 * using a variety of system MIBs. 1322 * XXX: data declarations should be together near the beginning of the file. 1323 */ 1324static int see_other_gids = 1; 1325SYSCTL_INT(_security_bsd, OID_AUTO, see_other_gids, CTLFLAG_RW, 1326 &see_other_gids, 0, 1327 "Unprivileged processes may see subjects/objects with different real gid"); 1328 1329/* 1330 * Determine if u1 can "see" the subject specified by u2, according to the 1331 * 'see_other_gids' policy. 1332 * Returns: 0 for permitted, ESRCH otherwise 1333 * Locks: none 1334 * References: *u1 and *u2 must not change during the call 1335 * u1 may equal u2, in which case only one reference is required 1336 */ 1337static int 1338cr_seeothergids(struct ucred *u1, struct ucred *u2) 1339{ 1340 int i, match; 1341 1342 if (!see_other_gids) { 1343 match = 0; 1344 for (i = 0; i < u1->cr_ngroups; i++) { 1345 if (groupmember(u1->cr_groups[i], u2)) 1346 match = 1; 1347 if (match) 1348 break; 1349 } 1350 if (!match) { 1351 if (priv_check_cred(u1, PRIV_SEEOTHERGIDS, 0) != 0) 1352 return (ESRCH); 1353 } 1354 } 1355 return (0); 1356} 1357 1358/*- 1359 * Determine if u1 "can see" the subject specified by u2. 1360 * Returns: 0 for permitted, an errno value otherwise 1361 * Locks: none 1362 * References: *u1 and *u2 must not change during the call 1363 * u1 may equal u2, in which case only one reference is required 1364 */ 1365int 1366cr_cansee(struct ucred *u1, struct ucred *u2) 1367{ 1368 int error; 1369 1370 if ((error = prison_check(u1, u2))) 1371 return (error); 1372#ifdef MAC 1373 if ((error = mac_cred_check_visible(u1, u2))) 1374 return (error); 1375#endif 1376 if ((error = cr_seeotheruids(u1, u2))) 1377 return (error); 1378 if ((error = cr_seeothergids(u1, u2))) 1379 return (error); 1380 return (0); 1381} 1382 1383/*- 1384 * Determine if td "can see" the subject specified by p. 1385 * Returns: 0 for permitted, an errno value otherwise 1386 * Locks: Sufficient locks to protect p->p_ucred must be held. td really 1387 * should be curthread. 1388 * References: td and p must be valid for the lifetime of the call 1389 */ 1390int 1391p_cansee(struct thread *td, struct proc *p) 1392{ 1393 1394 /* Wrap cr_cansee() for all functionality. */ 1395 KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1396 PROC_LOCK_ASSERT(p, MA_OWNED); 1397 return (cr_cansee(td->td_ucred, p->p_ucred)); 1398} 1399 1400/* 1401 * 'conservative_signals' prevents the delivery of a broad class of 1402 * signals by unprivileged processes to processes that have changed their 1403 * credentials since the last invocation of execve(). This can prevent 1404 * the leakage of cached information or retained privileges as a result 1405 * of a common class of signal-related vulnerabilities. However, this 1406 * may interfere with some applications that expect to be able to 1407 * deliver these signals to peer processes after having given up 1408 * privilege. 1409 */ 1410static int conservative_signals = 1; 1411SYSCTL_INT(_security_bsd, OID_AUTO, conservative_signals, CTLFLAG_RW, 1412 &conservative_signals, 0, "Unprivileged processes prevented from " 1413 "sending certain signals to processes whose credentials have changed"); 1414/*- 1415 * Determine whether cred may deliver the specified signal to proc. 1416 * Returns: 0 for permitted, an errno value otherwise. 1417 * Locks: A lock must be held for proc. 1418 * References: cred and proc must be valid for the lifetime of the call. 1419 */ 1420int 1421cr_cansignal(struct ucred *cred, struct proc *proc, int signum) 1422{ 1423 int error; 1424 1425 PROC_LOCK_ASSERT(proc, MA_OWNED); 1426 /* 1427 * Jail semantics limit the scope of signalling to proc in the 1428 * same jail as cred, if cred is in jail. 1429 */ 1430 error = prison_check(cred, proc->p_ucred); 1431 if (error) 1432 return (error); 1433#ifdef MAC 1434 if ((error = mac_proc_check_signal(cred, proc, signum))) 1435 return (error); 1436#endif 1437 if ((error = cr_seeotheruids(cred, proc->p_ucred))) 1438 return (error); 1439 if ((error = cr_seeothergids(cred, proc->p_ucred))) 1440 return (error); 1441 1442 /* 1443 * UNIX signal semantics depend on the status of the P_SUGID 1444 * bit on the target process. If the bit is set, then additional 1445 * restrictions are placed on the set of available signals. 1446 */ 1447 if (conservative_signals && (proc->p_flag & P_SUGID)) { 1448 switch (signum) { 1449 case 0: 1450 case SIGKILL: 1451 case SIGINT: 1452 case SIGTERM: 1453 case SIGALRM: 1454 case SIGSTOP: 1455 case SIGTTIN: 1456 case SIGTTOU: 1457 case SIGTSTP: 1458 case SIGHUP: 1459 case SIGUSR1: 1460 case SIGUSR2: 1461 /* 1462 * Generally, permit job and terminal control 1463 * signals. 1464 */ 1465 break; 1466 default: 1467 /* Not permitted without privilege. */ 1468 error = priv_check_cred(cred, PRIV_SIGNAL_SUGID, 0); 1469 if (error) 1470 return (error); 1471 } 1472 } 1473 1474 /* 1475 * Generally, the target credential's ruid or svuid must match the 1476 * subject credential's ruid or euid. 1477 */ 1478 if (cred->cr_ruid != proc->p_ucred->cr_ruid && 1479 cred->cr_ruid != proc->p_ucred->cr_svuid && 1480 cred->cr_uid != proc->p_ucred->cr_ruid && 1481 cred->cr_uid != proc->p_ucred->cr_svuid) { 1482 error = priv_check_cred(cred, PRIV_SIGNAL_DIFFCRED, 0); 1483 if (error) 1484 return (error); 1485 } 1486 1487 return (0); 1488} 1489 1490/*- 1491 * Determine whether td may deliver the specified signal to p. 1492 * Returns: 0 for permitted, an errno value otherwise 1493 * Locks: Sufficient locks to protect various components of td and p 1494 * must be held. td must be curthread, and a lock must be 1495 * held for p. 1496 * References: td and p must be valid for the lifetime of the call 1497 */ 1498int 1499p_cansignal(struct thread *td, struct proc *p, int signum) 1500{ 1501 1502 KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1503 PROC_LOCK_ASSERT(p, MA_OWNED); 1504 if (td->td_proc == p) 1505 return (0); 1506 1507 /* 1508 * UNIX signalling semantics require that processes in the same 1509 * session always be able to deliver SIGCONT to one another, 1510 * overriding the remaining protections. 1511 */ 1512 /* XXX: This will require an additional lock of some sort. */ 1513 if (signum == SIGCONT && td->td_proc->p_session == p->p_session) 1514 return (0); 1515 /* 1516 * Some compat layers use SIGTHR and higher signals for 1517 * communication between different kernel threads of the same 1518 * process, so that they expect that it's always possible to 1519 * deliver them, even for suid applications where cr_cansignal() can 1520 * deny such ability for security consideration. It should be 1521 * pretty safe to do since the only way to create two processes 1522 * with the same p_leader is via rfork(2). 1523 */ 1524 if (td->td_proc->p_leader != NULL && signum >= SIGTHR && 1525 signum < SIGTHR + 4 && td->td_proc->p_leader == p->p_leader) 1526 return (0); 1527 1528 return (cr_cansignal(td->td_ucred, p, signum)); 1529} 1530 1531/*- 1532 * Determine whether td may reschedule p. 1533 * Returns: 0 for permitted, an errno value otherwise 1534 * Locks: Sufficient locks to protect various components of td and p 1535 * must be held. td must be curthread, and a lock must 1536 * be held for p. 1537 * References: td and p must be valid for the lifetime of the call 1538 */ 1539int 1540p_cansched(struct thread *td, struct proc *p) 1541{ 1542 int error; 1543 1544 KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1545 PROC_LOCK_ASSERT(p, MA_OWNED); 1546 if (td->td_proc == p) 1547 return (0); 1548 if ((error = prison_check(td->td_ucred, p->p_ucred))) 1549 return (error); 1550#ifdef MAC 1551 if ((error = mac_proc_check_sched(td->td_ucred, p))) 1552 return (error); 1553#endif 1554 if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred))) 1555 return (error); 1556 if ((error = cr_seeothergids(td->td_ucred, p->p_ucred))) 1557 return (error); 1558 if (td->td_ucred->cr_ruid != p->p_ucred->cr_ruid && 1559 td->td_ucred->cr_uid != p->p_ucred->cr_ruid) { 1560 error = priv_check(td, PRIV_SCHED_DIFFCRED); 1561 if (error) 1562 return (error); 1563 } 1564 return (0); 1565} 1566 1567/* 1568 * The 'unprivileged_proc_debug' flag may be used to disable a variety of 1569 * unprivileged inter-process debugging services, including some procfs 1570 * functionality, ptrace(), and ktrace(). In the past, inter-process 1571 * debugging has been involved in a variety of security problems, and sites 1572 * not requiring the service might choose to disable it when hardening 1573 * systems. 1574 * 1575 * XXX: Should modifying and reading this variable require locking? 1576 * XXX: data declarations should be together near the beginning of the file. 1577 */ 1578static int unprivileged_proc_debug = 1; 1579SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_proc_debug, CTLFLAG_RW, 1580 &unprivileged_proc_debug, 0, 1581 "Unprivileged processes may use process debugging facilities"); 1582 1583/*- 1584 * Determine whether td may debug p. 1585 * Returns: 0 for permitted, an errno value otherwise 1586 * Locks: Sufficient locks to protect various components of td and p 1587 * must be held. td must be curthread, and a lock must 1588 * be held for p. 1589 * References: td and p must be valid for the lifetime of the call 1590 */ 1591int 1592p_candebug(struct thread *td, struct proc *p) 1593{ 1594 int credentialchanged, error, grpsubset, i, uidsubset; 1595 1596 KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1597 PROC_LOCK_ASSERT(p, MA_OWNED); 1598 if (!unprivileged_proc_debug) { 1599 error = priv_check(td, PRIV_DEBUG_UNPRIV); 1600 if (error) 1601 return (error); 1602 } 1603 if (td->td_proc == p) 1604 return (0); 1605 if ((error = prison_check(td->td_ucred, p->p_ucred))) 1606 return (error); 1607#ifdef MAC 1608 if ((error = mac_proc_check_debug(td->td_ucred, p))) 1609 return (error); 1610#endif 1611 if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred))) 1612 return (error); 1613 if ((error = cr_seeothergids(td->td_ucred, p->p_ucred))) 1614 return (error); 1615 1616 /* 1617 * Is p's group set a subset of td's effective group set? This 1618 * includes p's egid, group access list, rgid, and svgid. 1619 */ 1620 grpsubset = 1; 1621 for (i = 0; i < p->p_ucred->cr_ngroups; i++) { 1622 if (!groupmember(p->p_ucred->cr_groups[i], td->td_ucred)) { 1623 grpsubset = 0; 1624 break; 1625 } 1626 } 1627 grpsubset = grpsubset && 1628 groupmember(p->p_ucred->cr_rgid, td->td_ucred) && 1629 groupmember(p->p_ucred->cr_svgid, td->td_ucred); 1630 1631 /* 1632 * Are the uids present in p's credential equal to td's 1633 * effective uid? This includes p's euid, svuid, and ruid. 1634 */ 1635 uidsubset = (td->td_ucred->cr_uid == p->p_ucred->cr_uid && 1636 td->td_ucred->cr_uid == p->p_ucred->cr_svuid && 1637 td->td_ucred->cr_uid == p->p_ucred->cr_ruid); 1638 1639 /* 1640 * Has the credential of the process changed since the last exec()? 1641 */ 1642 credentialchanged = (p->p_flag & P_SUGID); 1643 1644 /* 1645 * If p's gids aren't a subset, or the uids aren't a subset, 1646 * or the credential has changed, require appropriate privilege 1647 * for td to debug p. 1648 */ 1649 if (!grpsubset || !uidsubset) { 1650 error = priv_check(td, PRIV_DEBUG_DIFFCRED); 1651 if (error) 1652 return (error); 1653 } 1654 1655 if (credentialchanged) { 1656 error = priv_check(td, PRIV_DEBUG_SUGID); 1657 if (error) 1658 return (error); 1659 } 1660 1661 /* Can't trace init when securelevel > 0. */ 1662 if (p == initproc) { 1663 error = securelevel_gt(td->td_ucred, 0); 1664 if (error) 1665 return (error); 1666 } 1667 1668 /* 1669 * Can't trace a process that's currently exec'ing. 1670 * 1671 * XXX: Note, this is not a security policy decision, it's a 1672 * basic correctness/functionality decision. Therefore, this check 1673 * should be moved to the caller's of p_candebug(). 1674 */ 1675 if ((p->p_flag & P_INEXEC) != 0) 1676 return (EBUSY); 1677 1678 return (0); 1679} 1680 1681/*- 1682 * Determine whether the subject represented by cred can "see" a socket. 1683 * Returns: 0 for permitted, ENOENT otherwise. 1684 */ 1685int 1686cr_canseesocket(struct ucred *cred, struct socket *so) 1687{ 1688 int error; 1689 1690 error = prison_check(cred, so->so_cred); 1691 if (error) 1692 return (ENOENT); 1693#ifdef MAC 1694 error = mac_socket_check_visible(cred, so); 1695 if (error) 1696 return (error); 1697#endif 1698 if (cr_seeotheruids(cred, so->so_cred)) 1699 return (ENOENT); 1700 if (cr_seeothergids(cred, so->so_cred)) 1701 return (ENOENT); 1702 1703 return (0); 1704} 1705 1706#if defined(INET) || defined(INET6) 1707/*- 1708 * Determine whether the subject represented by cred can "see" a socket. 1709 * Returns: 0 for permitted, ENOENT otherwise. 1710 */ 1711int 1712cr_canseeinpcb(struct ucred *cred, struct inpcb *inp) 1713{ 1714 int error; 1715 1716 error = prison_check(cred, inp->inp_cred); 1717 if (error) 1718 return (ENOENT); 1719#ifdef MAC 1720 INP_LOCK_ASSERT(inp); 1721 error = mac_inpcb_check_visible(cred, inp); 1722 if (error) 1723 return (error); 1724#endif 1725 if (cr_seeotheruids(cred, inp->inp_cred)) 1726 return (ENOENT); 1727 if (cr_seeothergids(cred, inp->inp_cred)) 1728 return (ENOENT); 1729 1730 return (0); 1731} 1732#endif 1733 1734/*- 1735 * Determine whether td can wait for the exit of p. 1736 * Returns: 0 for permitted, an errno value otherwise 1737 * Locks: Sufficient locks to protect various components of td and p 1738 * must be held. td must be curthread, and a lock must 1739 * be held for p. 1740 * References: td and p must be valid for the lifetime of the call 1741 1742 */ 1743int 1744p_canwait(struct thread *td, struct proc *p) 1745{ 1746 int error; 1747 1748 KASSERT(td == curthread, ("%s: td not curthread", __func__)); 1749 PROC_LOCK_ASSERT(p, MA_OWNED); 1750 if ( 1751#ifdef VIMAGE /* XXX temporary until struct vimage goes away */ 1752 !vi_child_of(TD_TO_VIMAGE(td), P_TO_VIMAGE(p)) && 1753#endif 1754 (error = prison_check(td->td_ucred, p->p_ucred))) 1755 return (error); 1756#ifdef MAC 1757 if ((error = mac_proc_check_wait(td->td_ucred, p))) 1758 return (error); 1759#endif 1760#if 0 1761 /* XXXMAC: This could have odd effects on some shells. */ 1762 if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred))) 1763 return (error); 1764#endif 1765 1766 return (0); 1767} 1768 1769/* 1770 * Allocate a zeroed cred structure. 1771 */ 1772struct ucred * 1773crget(void) 1774{ 1775 register struct ucred *cr; 1776 1777 cr = malloc(sizeof(*cr), M_CRED, M_WAITOK | M_ZERO); 1778 refcount_init(&cr->cr_ref, 1); 1779#ifdef AUDIT 1780 audit_cred_init(cr); 1781#endif 1782#ifdef MAC 1783 mac_cred_init(cr); 1784#endif
|
| 1785 crextend(cr, XU_NGROUPS);
|
1783 return (cr); 1784} 1785 1786/* 1787 * Claim another reference to a ucred structure. 1788 */ 1789struct ucred * 1790crhold(struct ucred *cr) 1791{ 1792 1793 refcount_acquire(&cr->cr_ref); 1794 return (cr); 1795} 1796 1797/* 1798 * Free a cred structure. Throws away space when ref count gets to 0. 1799 */ 1800void 1801crfree(struct ucred *cr) 1802{ 1803 1804 KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref)); 1805 KASSERT(cr->cr_ref != 0xdeadc0de, ("dangling reference to ucred")); 1806 if (refcount_release(&cr->cr_ref)) { 1807 /* 1808 * Some callers of crget(), such as nfs_statfs(), 1809 * allocate a temporary credential, but don't 1810 * allocate a uidinfo structure. 1811 */ 1812 if (cr->cr_uidinfo != NULL) 1813 uifree(cr->cr_uidinfo); 1814 if (cr->cr_ruidinfo != NULL) 1815 uifree(cr->cr_ruidinfo); 1816 /* 1817 * Free a prison, if any. 1818 */ 1819 if (cr->cr_prison != NULL) 1820 prison_free(cr->cr_prison); 1821#ifdef VIMAGE 1822 /* XXX TODO: find out why and when cr_vimage can be NULL here! */ 1823 if (cr->cr_vimage != NULL) 1824 refcount_release(&cr->cr_vimage->vi_ucredrefc); 1825#endif 1826#ifdef AUDIT 1827 audit_cred_destroy(cr); 1828#endif 1829#ifdef MAC 1830 mac_cred_destroy(cr); 1831#endif
| 1786 return (cr); 1787} 1788 1789/* 1790 * Claim another reference to a ucred structure. 1791 */ 1792struct ucred * 1793crhold(struct ucred *cr) 1794{ 1795 1796 refcount_acquire(&cr->cr_ref); 1797 return (cr); 1798} 1799 1800/* 1801 * Free a cred structure. Throws away space when ref count gets to 0. 1802 */ 1803void 1804crfree(struct ucred *cr) 1805{ 1806 1807 KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref)); 1808 KASSERT(cr->cr_ref != 0xdeadc0de, ("dangling reference to ucred")); 1809 if (refcount_release(&cr->cr_ref)) { 1810 /* 1811 * Some callers of crget(), such as nfs_statfs(), 1812 * allocate a temporary credential, but don't 1813 * allocate a uidinfo structure. 1814 */ 1815 if (cr->cr_uidinfo != NULL) 1816 uifree(cr->cr_uidinfo); 1817 if (cr->cr_ruidinfo != NULL) 1818 uifree(cr->cr_ruidinfo); 1819 /* 1820 * Free a prison, if any. 1821 */ 1822 if (cr->cr_prison != NULL) 1823 prison_free(cr->cr_prison); 1824#ifdef VIMAGE 1825 /* XXX TODO: find out why and when cr_vimage can be NULL here! */ 1826 if (cr->cr_vimage != NULL) 1827 refcount_release(&cr->cr_vimage->vi_ucredrefc); 1828#endif 1829#ifdef AUDIT 1830 audit_cred_destroy(cr); 1831#endif 1832#ifdef MAC 1833 mac_cred_destroy(cr); 1834#endif
|
| 1835 free(cr->cr_groups, M_CRED);
|
1832 free(cr, M_CRED); 1833 } 1834} 1835 1836/* 1837 * Check to see if this ucred is shared. 1838 */ 1839int 1840crshared(struct ucred *cr) 1841{ 1842 1843 return (cr->cr_ref > 1); 1844} 1845 1846/* 1847 * Copy a ucred's contents from a template. Does not block. 1848 */ 1849void 1850crcopy(struct ucred *dest, struct ucred *src) 1851{ 1852 1853 KASSERT(crshared(dest) == 0, ("crcopy of shared ucred")); 1854 bcopy(&src->cr_startcopy, &dest->cr_startcopy, 1855 (unsigned)((caddr_t)&src->cr_endcopy - 1856 (caddr_t)&src->cr_startcopy));
| 1836 free(cr, M_CRED); 1837 } 1838} 1839 1840/* 1841 * Check to see if this ucred is shared. 1842 */ 1843int 1844crshared(struct ucred *cr) 1845{ 1846 1847 return (cr->cr_ref > 1); 1848} 1849 1850/* 1851 * Copy a ucred's contents from a template. Does not block. 1852 */ 1853void 1854crcopy(struct ucred *dest, struct ucred *src) 1855{ 1856 1857 KASSERT(crshared(dest) == 0, ("crcopy of shared ucred")); 1858 bcopy(&src->cr_startcopy, &dest->cr_startcopy, 1859 (unsigned)((caddr_t)&src->cr_endcopy - 1860 (caddr_t)&src->cr_startcopy));
|
| 1861 crsetgroups(dest, src->cr_ngroups, src->cr_groups);
|
1857 uihold(dest->cr_uidinfo); 1858 uihold(dest->cr_ruidinfo); 1859 prison_hold(dest->cr_prison); 1860#ifdef VIMAGE 1861 KASSERT(src->cr_vimage != NULL, ("cr_vimage == NULL")); 1862 refcount_acquire(&dest->cr_vimage->vi_ucredrefc); 1863#endif 1864#ifdef AUDIT 1865 audit_cred_copy(src, dest); 1866#endif 1867#ifdef MAC 1868 mac_cred_copy(src, dest); 1869#endif 1870} 1871 1872/* 1873 * Dup cred struct to a new held one. 1874 */ 1875struct ucred * 1876crdup(struct ucred *cr) 1877{ 1878 struct ucred *newcr; 1879 1880 newcr = crget(); 1881 crcopy(newcr, cr); 1882 return (newcr); 1883} 1884 1885/* 1886 * Fill in a struct xucred based on a struct ucred. 1887 */ 1888void 1889cru2x(struct ucred *cr, struct xucred *xcr) 1890{
| 1862 uihold(dest->cr_uidinfo); 1863 uihold(dest->cr_ruidinfo); 1864 prison_hold(dest->cr_prison); 1865#ifdef VIMAGE 1866 KASSERT(src->cr_vimage != NULL, ("cr_vimage == NULL")); 1867 refcount_acquire(&dest->cr_vimage->vi_ucredrefc); 1868#endif 1869#ifdef AUDIT 1870 audit_cred_copy(src, dest); 1871#endif 1872#ifdef MAC 1873 mac_cred_copy(src, dest); 1874#endif 1875} 1876 1877/* 1878 * Dup cred struct to a new held one. 1879 */ 1880struct ucred * 1881crdup(struct ucred *cr) 1882{ 1883 struct ucred *newcr; 1884 1885 newcr = crget(); 1886 crcopy(newcr, cr); 1887 return (newcr); 1888} 1889 1890/* 1891 * Fill in a struct xucred based on a struct ucred. 1892 */ 1893void 1894cru2x(struct ucred *cr, struct xucred *xcr) 1895{
|
| 1896 int ngroups;
|
1891 1892 bzero(xcr, sizeof(*xcr)); 1893 xcr->cr_version = XUCRED_VERSION; 1894 xcr->cr_uid = cr->cr_uid;
| 1897 1898 bzero(xcr, sizeof(*xcr)); 1899 xcr->cr_version = XUCRED_VERSION; 1900 xcr->cr_uid = cr->cr_uid;
|
1895 xcr->cr_ngroups = cr->cr_ngroups; 1896 bcopy(cr->cr_groups, xcr->cr_groups, sizeof(cr->cr_groups));
| 1901 1902 ngroups = MIN(cr->cr_ngroups, XU_NGROUPS); 1903 xcr->cr_ngroups = ngroups; 1904 bcopy(cr->cr_groups, xcr->cr_groups, 1905 ngroups * sizeof(*cr->cr_groups));
|
1897} 1898 1899/* 1900 * small routine to swap a thread's current ucred for the correct one taken 1901 * from the process. 1902 */ 1903void 1904cred_update_thread(struct thread *td) 1905{ 1906 struct proc *p; 1907 struct ucred *cred; 1908 1909 p = td->td_proc; 1910 cred = td->td_ucred; 1911 PROC_LOCK(p); 1912 td->td_ucred = crhold(p->p_ucred); 1913 PROC_UNLOCK(p); 1914 if (cred != NULL) 1915 crfree(cred); 1916} 1917
| 1906} 1907 1908/* 1909 * small routine to swap a thread's current ucred for the correct one taken 1910 * from the process. 1911 */ 1912void 1913cred_update_thread(struct thread *td) 1914{ 1915 struct proc *p; 1916 struct ucred *cred; 1917 1918 p = td->td_proc; 1919 cred = td->td_ucred; 1920 PROC_LOCK(p); 1921 td->td_ucred = crhold(p->p_ucred); 1922 PROC_UNLOCK(p); 1923 if (cred != NULL) 1924 crfree(cred); 1925} 1926
|
| 1927struct ucred * 1928crcopysafe(struct proc *p, struct ucred *cr) 1929{ 1930 struct ucred *oldcred; 1931 int groups; 1932 1933 PROC_LOCK_ASSERT(p, MA_OWNED); 1934 1935 oldcred = p->p_ucred; 1936 while (cr->cr_agroups < oldcred->cr_agroups) { 1937 groups = oldcred->cr_agroups; 1938 PROC_UNLOCK(p); 1939 crextend(cr, groups); 1940 PROC_LOCK(p); 1941 oldcred = p->p_ucred; 1942 } 1943 crcopy(cr, oldcred); 1944 1945 return (oldcred); 1946} 1947
|
1918/*
| 1948/*
|
| 1949 * Extend the passed in credential to hold n items. 1950 */ 1951static void 1952crextend(struct ucred *cr, int n) 1953{ 1954 int cnt; 1955 1956 /* Truncate? */ 1957 if (n <= cr->cr_agroups) 1958 return; 1959 1960 /* 1961 * We extend by 2 each time since we're using a power of two 1962 * allocator until we need enough groups to fill a page. 1963 * Once we're allocating multiple pages, only allocate as many 1964 * as we actually need. The case of processes needing a 1965 * non-power of two number of pages seems more likely than 1966 * a real world process that adds thousands of groups one at a 1967 * time. 1968 */ 1969 if ( n < PAGE_SIZE / sizeof(gid_t) ) { 1970 if (cr->cr_agroups == 0) 1971 cnt = MINALLOCSIZE / sizeof(gid_t); 1972 else 1973 cnt = cr->cr_agroups * 2; 1974 1975 while (cnt < n) 1976 cnt *= 2; 1977 } else 1978 cnt = roundup2(n, PAGE_SIZE / sizeof(gid_t)); 1979 1980 /* Free the old array. */ 1981 if (cr->cr_groups) 1982 free(cr->cr_groups, M_CRED); 1983 1984 cr->cr_groups = malloc(cnt * sizeof(gid_t), M_CRED, M_WAITOK | M_ZERO); 1985 cr->cr_agroups = cnt; 1986} 1987 1988/* 1989 * Copy groups in to a credential, preserving any necessicary invariants 1990 * (i.e. sorting in the future). crextend() must have been called 1991 * before hand to ensure sufficient space is available. If 1992 */ 1993static void 1994crsetgroups_locked(struct ucred *cr, int ngrp, gid_t *groups) 1995{ 1996 1997 KASSERT(cr->cr_agroups >= ngrp, ("cr_ngroups is too small")); 1998 1999 bcopy(groups, cr->cr_groups, ngrp * sizeof(gid_t)); 2000 cr->cr_ngroups = ngrp; 2001} 2002 2003/* 2004 * Copy groups in to a credential after expanding it if required. 2005 * Truncate the list to NGROUPS if it is too large. 2006 */ 2007void 2008crsetgroups(struct ucred *cr, int ngrp, gid_t *groups) 2009{ 2010 2011 if (ngrp > NGROUPS) 2012 ngrp = NGROUPS; 2013 2014 crextend(cr, ngrp); 2015 crsetgroups_locked(cr, ngrp, groups); 2016} 2017 2018/*
|
1919 * Get login name, if available. 1920 */ 1921#ifndef _SYS_SYSPROTO_H_ 1922struct getlogin_args { 1923 char *namebuf; 1924 u_int namelen; 1925}; 1926#endif 1927/* ARGSUSED */ 1928int 1929getlogin(struct thread *td, struct getlogin_args *uap) 1930{ 1931 int error; 1932 char login[MAXLOGNAME]; 1933 struct proc *p = td->td_proc; 1934 1935 if (uap->namelen > MAXLOGNAME) 1936 uap->namelen = MAXLOGNAME; 1937 PROC_LOCK(p); 1938 SESS_LOCK(p->p_session); 1939 bcopy(p->p_session->s_login, login, uap->namelen); 1940 SESS_UNLOCK(p->p_session); 1941 PROC_UNLOCK(p); 1942 error = copyout(login, uap->namebuf, uap->namelen); 1943 return(error); 1944} 1945 1946/* 1947 * Set login name. 1948 */ 1949#ifndef _SYS_SYSPROTO_H_ 1950struct setlogin_args { 1951 char *namebuf; 1952}; 1953#endif 1954/* ARGSUSED */ 1955int 1956setlogin(struct thread *td, struct setlogin_args *uap) 1957{ 1958 struct proc *p = td->td_proc; 1959 int error; 1960 char logintmp[MAXLOGNAME]; 1961 1962 error = priv_check(td, PRIV_PROC_SETLOGIN); 1963 if (error) 1964 return (error); 1965 error = copyinstr(uap->namebuf, logintmp, sizeof(logintmp), NULL); 1966 if (error == ENAMETOOLONG) 1967 error = EINVAL; 1968 else if (!error) { 1969 PROC_LOCK(p); 1970 SESS_LOCK(p->p_session); 1971 (void) memcpy(p->p_session->s_login, logintmp, 1972 sizeof(logintmp)); 1973 SESS_UNLOCK(p->p_session); 1974 PROC_UNLOCK(p); 1975 } 1976 return (error); 1977} 1978 1979void 1980setsugid(struct proc *p) 1981{ 1982 1983 PROC_LOCK_ASSERT(p, MA_OWNED); 1984 p->p_flag |= P_SUGID; 1985 if (!(p->p_pfsflags & PF_ISUGID)) 1986 p->p_stops = 0; 1987} 1988 1989/*- 1990 * Change a process's effective uid. 1991 * Side effects: newcred->cr_uid and newcred->cr_uidinfo will be modified. 1992 * References: newcred must be an exclusive credential reference for the 1993 * duration of the call. 1994 */ 1995void 1996change_euid(struct ucred *newcred, struct uidinfo *euip) 1997{ 1998 1999 newcred->cr_uid = euip->ui_uid; 2000 uihold(euip); 2001 uifree(newcred->cr_uidinfo); 2002 newcred->cr_uidinfo = euip; 2003} 2004 2005/*- 2006 * Change a process's effective gid. 2007 * Side effects: newcred->cr_gid will be modified. 2008 * References: newcred must be an exclusive credential reference for the 2009 * duration of the call. 2010 */ 2011void 2012change_egid(struct ucred *newcred, gid_t egid) 2013{ 2014 2015 newcred->cr_groups[0] = egid; 2016} 2017 2018/*- 2019 * Change a process's real uid. 2020 * Side effects: newcred->cr_ruid will be updated, newcred->cr_ruidinfo 2021 * will be updated, and the old and new cr_ruidinfo proc 2022 * counts will be updated. 2023 * References: newcred must be an exclusive credential reference for the 2024 * duration of the call. 2025 */ 2026void 2027change_ruid(struct ucred *newcred, struct uidinfo *ruip) 2028{ 2029 2030 (void)chgproccnt(newcred->cr_ruidinfo, -1, 0); 2031 newcred->cr_ruid = ruip->ui_uid; 2032 uihold(ruip); 2033 uifree(newcred->cr_ruidinfo); 2034 newcred->cr_ruidinfo = ruip; 2035 (void)chgproccnt(newcred->cr_ruidinfo, 1, 0); 2036} 2037 2038/*- 2039 * Change a process's real gid. 2040 * Side effects: newcred->cr_rgid will be updated. 2041 * References: newcred must be an exclusive credential reference for the 2042 * duration of the call. 2043 */ 2044void 2045change_rgid(struct ucred *newcred, gid_t rgid) 2046{ 2047 2048 newcred->cr_rgid = rgid; 2049} 2050 2051/*- 2052 * Change a process's saved uid. 2053 * Side effects: newcred->cr_svuid will be updated. 2054 * References: newcred must be an exclusive credential reference for the 2055 * duration of the call. 2056 */ 2057void 2058change_svuid(struct ucred *newcred, uid_t svuid) 2059{ 2060 2061 newcred->cr_svuid = svuid; 2062} 2063 2064/*- 2065 * Change a process's saved gid. 2066 * Side effects: newcred->cr_svgid will be updated. 2067 * References: newcred must be an exclusive credential reference for the 2068 * duration of the call. 2069 */ 2070void 2071change_svgid(struct ucred *newcred, gid_t svgid) 2072{ 2073 2074 newcred->cr_svgid = svgid; 2075}
| 2019 * Get login name, if available. 2020 */ 2021#ifndef _SYS_SYSPROTO_H_ 2022struct getlogin_args { 2023 char *namebuf; 2024 u_int namelen; 2025}; 2026#endif 2027/* ARGSUSED */ 2028int 2029getlogin(struct thread *td, struct getlogin_args *uap) 2030{ 2031 int error; 2032 char login[MAXLOGNAME]; 2033 struct proc *p = td->td_proc; 2034 2035 if (uap->namelen > MAXLOGNAME) 2036 uap->namelen = MAXLOGNAME; 2037 PROC_LOCK(p); 2038 SESS_LOCK(p->p_session); 2039 bcopy(p->p_session->s_login, login, uap->namelen); 2040 SESS_UNLOCK(p->p_session); 2041 PROC_UNLOCK(p); 2042 error = copyout(login, uap->namebuf, uap->namelen); 2043 return(error); 2044} 2045 2046/* 2047 * Set login name. 2048 */ 2049#ifndef _SYS_SYSPROTO_H_ 2050struct setlogin_args { 2051 char *namebuf; 2052}; 2053#endif 2054/* ARGSUSED */ 2055int 2056setlogin(struct thread *td, struct setlogin_args *uap) 2057{ 2058 struct proc *p = td->td_proc; 2059 int error; 2060 char logintmp[MAXLOGNAME]; 2061 2062 error = priv_check(td, PRIV_PROC_SETLOGIN); 2063 if (error) 2064 return (error); 2065 error = copyinstr(uap->namebuf, logintmp, sizeof(logintmp), NULL); 2066 if (error == ENAMETOOLONG) 2067 error = EINVAL; 2068 else if (!error) { 2069 PROC_LOCK(p); 2070 SESS_LOCK(p->p_session); 2071 (void) memcpy(p->p_session->s_login, logintmp, 2072 sizeof(logintmp)); 2073 SESS_UNLOCK(p->p_session); 2074 PROC_UNLOCK(p); 2075 } 2076 return (error); 2077} 2078 2079void 2080setsugid(struct proc *p) 2081{ 2082 2083 PROC_LOCK_ASSERT(p, MA_OWNED); 2084 p->p_flag |= P_SUGID; 2085 if (!(p->p_pfsflags & PF_ISUGID)) 2086 p->p_stops = 0; 2087} 2088 2089/*- 2090 * Change a process's effective uid. 2091 * Side effects: newcred->cr_uid and newcred->cr_uidinfo will be modified. 2092 * References: newcred must be an exclusive credential reference for the 2093 * duration of the call. 2094 */ 2095void 2096change_euid(struct ucred *newcred, struct uidinfo *euip) 2097{ 2098 2099 newcred->cr_uid = euip->ui_uid; 2100 uihold(euip); 2101 uifree(newcred->cr_uidinfo); 2102 newcred->cr_uidinfo = euip; 2103} 2104 2105/*- 2106 * Change a process's effective gid. 2107 * Side effects: newcred->cr_gid will be modified. 2108 * References: newcred must be an exclusive credential reference for the 2109 * duration of the call. 2110 */ 2111void 2112change_egid(struct ucred *newcred, gid_t egid) 2113{ 2114 2115 newcred->cr_groups[0] = egid; 2116} 2117 2118/*- 2119 * Change a process's real uid. 2120 * Side effects: newcred->cr_ruid will be updated, newcred->cr_ruidinfo 2121 * will be updated, and the old and new cr_ruidinfo proc 2122 * counts will be updated. 2123 * References: newcred must be an exclusive credential reference for the 2124 * duration of the call. 2125 */ 2126void 2127change_ruid(struct ucred *newcred, struct uidinfo *ruip) 2128{ 2129 2130 (void)chgproccnt(newcred->cr_ruidinfo, -1, 0); 2131 newcred->cr_ruid = ruip->ui_uid; 2132 uihold(ruip); 2133 uifree(newcred->cr_ruidinfo); 2134 newcred->cr_ruidinfo = ruip; 2135 (void)chgproccnt(newcred->cr_ruidinfo, 1, 0); 2136} 2137 2138/*- 2139 * Change a process's real gid. 2140 * Side effects: newcred->cr_rgid will be updated. 2141 * References: newcred must be an exclusive credential reference for the 2142 * duration of the call. 2143 */ 2144void 2145change_rgid(struct ucred *newcred, gid_t rgid) 2146{ 2147 2148 newcred->cr_rgid = rgid; 2149} 2150 2151/*- 2152 * Change a process's saved uid. 2153 * Side effects: newcred->cr_svuid will be updated. 2154 * References: newcred must be an exclusive credential reference for the 2155 * duration of the call. 2156 */ 2157void 2158change_svuid(struct ucred *newcred, uid_t svuid) 2159{ 2160 2161 newcred->cr_svuid = svuid; 2162} 2163 2164/*- 2165 * Change a process's saved gid. 2166 * Side effects: newcred->cr_svgid will be updated. 2167 * References: newcred must be an exclusive credential reference for the 2168 * duration of the call. 2169 */ 2170void 2171change_svgid(struct ucred *newcred, gid_t svgid) 2172{ 2173 2174 newcred->cr_svgid = svgid; 2175}
|