1 /* $OpenBSD: kern_prot.c,v 1.66 2016/09/02 18:11:28 tedu Exp $ */ 2 /* $NetBSD: kern_prot.c,v 1.33 1996/02/09 18:59:42 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993 6 * The Regents of the University of California. All rights reserved. 7 * (c) UNIX System Laboratories, Inc. 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 * 3. 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/param.h> 45 #include <sys/acct.h> 46 #include <sys/systm.h> 47 #include <sys/ucred.h> 48 #include <sys/proc.h> 49 #include <sys/filedesc.h> 50 #include <sys/pool.h> 51 52 #include <sys/mount.h> 53 #include <sys/syscallargs.h> 54 55 #ifdef __HAVE_MD_TCB 56 # include <machine/tcb.h> 57 #endif 58 59 inline void 60 crset(struct ucred *newcr, const struct ucred *cr) 61 { 62 KASSERT(cr->cr_ref > 0); 63 memcpy( 64 (char *)newcr + offsetof(struct ucred, cr_startcopy), 65 (const char *)cr + offsetof(struct ucred, cr_startcopy), 66 sizeof(*cr) - offsetof(struct ucred, cr_startcopy)); 67 } 68 69 int 70 sys_getpid(struct proc *p, void *v, register_t *retval) 71 { 72 73 *retval = p->p_p->ps_pid; 74 return (0); 75 } 76 77 int 78 sys_getthrid(struct proc *p, void *v, register_t *retval) 79 { 80 81 *retval = p->p_pid + THREAD_PID_OFFSET; 82 return (0); 83 } 84 85 int 86 sys_getppid(struct proc *p, void *v, register_t *retval) 87 { 88 89 *retval = p->p_p->ps_pptr->ps_pid; 90 return (0); 91 } 92 93 /* Get process group ID; note that POSIX getpgrp takes no parameter */ 94 int 95 sys_getpgrp(struct proc *p, void *v, register_t *retval) 96 { 97 98 *retval = p->p_p->ps_pgrp->pg_id; 99 return (0); 100 } 101 102 /* 103 * SysVR.4 compatible getpgid() 104 */ 105 int 106 sys_getpgid(struct proc *curp, void *v, register_t *retval) 107 { 108 struct sys_getpgid_args /* { 109 syscallarg(pid_t) pid; 110 } */ *uap = v; 111 struct process *targpr = curp->p_p; 112 113 if (SCARG(uap, pid) == 0 || SCARG(uap, pid) == targpr->ps_pid) 114 goto found; 115 if ((targpr = prfind(SCARG(uap, pid))) == NULL) 116 return (ESRCH); 117 if (targpr->ps_session != curp->p_p->ps_session) 118 return (EPERM); 119 found: 120 *retval = targpr->ps_pgid; 121 return (0); 122 } 123 124 int 125 sys_getsid(struct proc *curp, void *v, register_t *retval) 126 { 127 struct sys_getsid_args /* { 128 syscallarg(pid_t) pid; 129 } */ *uap = v; 130 struct process *targpr = curp->p_p; 131 132 if (SCARG(uap, pid) == 0 || SCARG(uap, pid) == targpr->ps_pid) 133 goto found; 134 if ((targpr = prfind(SCARG(uap, pid))) == NULL) 135 return (ESRCH); 136 if (targpr->ps_session != curp->p_p->ps_session) 137 return (EPERM); 138 found: 139 /* Skip exiting processes */ 140 if (targpr->ps_pgrp->pg_session->s_leader == NULL) 141 return (ESRCH); 142 *retval = targpr->ps_pgrp->pg_session->s_leader->ps_pid; 143 return (0); 144 } 145 146 int 147 sys_getuid(struct proc *p, void *v, register_t *retval) 148 { 149 150 *retval = p->p_ucred->cr_ruid; 151 return (0); 152 } 153 154 int 155 sys_geteuid(struct proc *p, void *v, register_t *retval) 156 { 157 158 *retval = p->p_ucred->cr_uid; 159 return (0); 160 } 161 162 int 163 sys_issetugid(struct proc *p, void *v, register_t *retval) 164 { 165 if (p->p_p->ps_flags & PS_SUGIDEXEC) 166 *retval = 1; 167 else 168 *retval = 0; 169 return (0); 170 } 171 172 int 173 sys_getgid(struct proc *p, void *v, register_t *retval) 174 { 175 176 *retval = p->p_ucred->cr_rgid; 177 return (0); 178 } 179 180 /* 181 * Get effective group ID. The "egid" is groups[0], and could be obtained 182 * via getgroups. This syscall exists because it is somewhat painful to do 183 * correctly in a library function. 184 */ 185 int 186 sys_getegid(struct proc *p, void *v, register_t *retval) 187 { 188 189 *retval = p->p_ucred->cr_gid; 190 return (0); 191 } 192 193 int 194 sys_getgroups(struct proc *p, void *v, register_t *retval) 195 { 196 struct sys_getgroups_args /* { 197 syscallarg(int) gidsetsize; 198 syscallarg(gid_t *) gidset; 199 } */ *uap = v; 200 struct ucred *uc = p->p_ucred; 201 u_int ngrp; 202 int error; 203 204 if ((ngrp = SCARG(uap, gidsetsize)) == 0) { 205 *retval = uc->cr_ngroups; 206 return (0); 207 } 208 if (ngrp < uc->cr_ngroups) 209 return (EINVAL); 210 ngrp = uc->cr_ngroups; 211 error = copyout(uc->cr_groups, SCARG(uap, gidset), 212 ngrp * sizeof(gid_t)); 213 if (error) 214 return (error); 215 *retval = ngrp; 216 return (0); 217 } 218 219 int 220 sys_setsid(struct proc *p, void *v, register_t *retval) 221 { 222 struct session *newsess; 223 struct pgrp *newpgrp; 224 struct process *pr = p->p_p; 225 pid_t pid = pr->ps_pid; 226 227 newsess = pool_get(&session_pool, PR_WAITOK); 228 timeout_set(&newsess->s_verauthto, zapverauth, newsess); 229 newpgrp = pool_get(&pgrp_pool, PR_WAITOK); 230 231 if (pr->ps_pgid == pid || pgfind(pid)) { 232 pool_put(&pgrp_pool, newpgrp); 233 pool_put(&session_pool, newsess); 234 return (EPERM); 235 } else { 236 (void) enterpgrp(pr, pid, newpgrp, newsess); 237 *retval = pid; 238 return (0); 239 } 240 } 241 242 /* 243 * set process group (setpgid/old setpgrp) 244 * 245 * caller does setpgid(targpid, targpgid) 246 * 247 * pid must be caller or child of caller (ESRCH) 248 * if a child 249 * pid must be in same session (EPERM) 250 * pid can't have done an exec (EACCES) 251 * if pgid != pid 252 * there must exist some pid in same session having pgid (EPERM) 253 * pid must not be session leader (EPERM) 254 */ 255 int 256 sys_setpgid(struct proc *curp, void *v, register_t *retval) 257 { 258 struct sys_setpgid_args /* { 259 syscallarg(pid_t) pid; 260 syscallarg(pid_t) pgid; 261 } */ *uap = v; 262 struct process *curpr = curp->p_p; 263 struct process *targpr; /* target process */ 264 struct pgrp *pgrp, *newpgrp; /* target pgrp */ 265 pid_t pid, pgid; 266 int error; 267 268 pid = SCARG(uap, pid); 269 pgid = SCARG(uap, pgid); 270 271 if (pgid < 0) 272 return (EINVAL); 273 274 newpgrp = pool_get(&pgrp_pool, PR_WAITOK); 275 276 if (pid != 0 && pid != curpr->ps_pid) { 277 if ((targpr = prfind(pid)) == 0 || !inferior(targpr, curpr)) { 278 error = ESRCH; 279 goto out; 280 } 281 if (targpr->ps_session != curpr->ps_session) { 282 error = EPERM; 283 goto out; 284 } 285 if (targpr->ps_flags & PS_EXEC) { 286 error = EACCES; 287 goto out; 288 } 289 } else 290 targpr = curpr; 291 if (SESS_LEADER(targpr)) { 292 error = EPERM; 293 goto out; 294 } 295 if (pgid == 0) 296 pgid = targpr->ps_pid; 297 else if (pgid != targpr->ps_pid) 298 if ((pgrp = pgfind(pgid)) == 0 || 299 pgrp->pg_session != curpr->ps_session) { 300 error = EPERM; 301 goto out; 302 } 303 return (enterpgrp(targpr, pgid, newpgrp, NULL)); 304 out: 305 pool_put(&pgrp_pool, newpgrp); 306 return (error); 307 } 308 309 int 310 sys_getresuid(struct proc *p, void *v, register_t *retval) 311 { 312 struct sys_getresuid_args /* { 313 syscallarg(uid_t *) ruid; 314 syscallarg(uid_t *) euid; 315 syscallarg(uid_t *) suid; 316 } */ *uap = v; 317 struct ucred *uc = p->p_ucred; 318 uid_t *ruid, *euid, *suid; 319 int error1 = 0, error2 = 0, error3 = 0; 320 321 ruid = SCARG(uap, ruid); 322 euid = SCARG(uap, euid); 323 suid = SCARG(uap, suid); 324 325 if (ruid != NULL) 326 error1 = copyout(&uc->cr_ruid, ruid, sizeof(*ruid)); 327 if (euid != NULL) 328 error2 = copyout(&uc->cr_uid, euid, sizeof(*euid)); 329 if (suid != NULL) 330 error3 = copyout(&uc->cr_svuid, suid, sizeof(*suid)); 331 332 return (error1 ? error1 : error2 ? error2 : error3); 333 } 334 335 int 336 sys_setresuid(struct proc *p, void *v, register_t *retval) 337 { 338 struct sys_setresuid_args /* { 339 syscallarg(uid_t) ruid; 340 syscallarg(uid_t) euid; 341 syscallarg(uid_t) suid; 342 } */ *uap = v; 343 struct process *pr = p->p_p; 344 struct ucred *pruc, *newcred, *uc = p->p_ucred; 345 uid_t ruid, euid, suid; 346 int error; 347 348 ruid = SCARG(uap, ruid); 349 euid = SCARG(uap, euid); 350 suid = SCARG(uap, suid); 351 352 /* 353 * make permission checks against the thread's ucred, 354 * but the actual changes will be to the process's ucred 355 */ 356 pruc = pr->ps_ucred; 357 if ((ruid == (uid_t)-1 || ruid == pruc->cr_ruid) && 358 (euid == (uid_t)-1 || euid == pruc->cr_uid) && 359 (suid == (uid_t)-1 || suid == pruc->cr_svuid)) 360 return (0); /* no change */ 361 362 /* 363 * Any of the real, effective, and saved uids may be changed 364 * to the current value of one of the three (root is not limited). 365 */ 366 if (ruid != (uid_t)-1 && 367 ruid != uc->cr_ruid && 368 ruid != uc->cr_uid && 369 ruid != uc->cr_svuid && 370 (error = suser(p, 0))) 371 return (error); 372 373 if (euid != (uid_t)-1 && 374 euid != uc->cr_ruid && 375 euid != uc->cr_uid && 376 euid != uc->cr_svuid && 377 (error = suser(p, 0))) 378 return (error); 379 380 if (suid != (uid_t)-1 && 381 suid != uc->cr_ruid && 382 suid != uc->cr_uid && 383 suid != uc->cr_svuid && 384 (error = suser(p, 0))) 385 return (error); 386 387 /* 388 * Copy credentials so other references do not see our changes. 389 * ps_ucred may change during the crget(). 390 */ 391 newcred = crget(); 392 pruc = pr->ps_ucred; 393 crset(newcred, pruc); 394 395 /* 396 * Note that unlike the other set*uid() calls, each 397 * uid type is set independently of the others. 398 */ 399 if (ruid != (uid_t)-1) 400 newcred->cr_ruid = ruid; 401 if (euid != (uid_t)-1) 402 newcred->cr_uid = euid; 403 if (suid != (uid_t)-1) 404 newcred->cr_svuid = suid; 405 pr->ps_ucred = newcred; 406 atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); 407 408 /* now that we can sleep, transfer proc count to new user */ 409 if (ruid != (uid_t)-1 && ruid != pruc->cr_ruid) { 410 chgproccnt(pruc->cr_ruid, -1); 411 chgproccnt(ruid, 1); 412 } 413 crfree(pruc); 414 415 return (0); 416 } 417 418 int 419 sys_getresgid(struct proc *p, void *v, register_t *retval) 420 { 421 struct sys_getresgid_args /* { 422 syscallarg(gid_t *) rgid; 423 syscallarg(gid_t *) egid; 424 syscallarg(gid_t *) sgid; 425 } */ *uap = v; 426 struct ucred *uc = p->p_ucred; 427 gid_t *rgid, *egid, *sgid; 428 int error1 = 0, error2 = 0, error3 = 0; 429 430 rgid = SCARG(uap, rgid); 431 egid = SCARG(uap, egid); 432 sgid = SCARG(uap, sgid); 433 434 if (rgid != NULL) 435 error1 = copyout(&uc->cr_rgid, rgid, sizeof(*rgid)); 436 if (egid != NULL) 437 error2 = copyout(&uc->cr_gid, egid, sizeof(*egid)); 438 if (sgid != NULL) 439 error3 = copyout(&uc->cr_svgid, sgid, sizeof(*sgid)); 440 441 return (error1 ? error1 : error2 ? error2 : error3); 442 } 443 444 int 445 sys_setresgid(struct proc *p, void *v, register_t *retval) 446 { 447 struct sys_setresgid_args /* { 448 syscallarg(gid_t) rgid; 449 syscallarg(gid_t) egid; 450 syscallarg(gid_t) sgid; 451 } */ *uap = v; 452 struct process *pr = p->p_p; 453 struct ucred *pruc, *newcred, *uc = p->p_ucred; 454 gid_t rgid, egid, sgid; 455 int error; 456 457 rgid = SCARG(uap, rgid); 458 egid = SCARG(uap, egid); 459 sgid = SCARG(uap, sgid); 460 461 /* 462 * make permission checks against the thread's ucred, 463 * but the actual changes will be to the process's ucred 464 */ 465 pruc = pr->ps_ucred; 466 if ((rgid == (gid_t)-1 || rgid == pruc->cr_rgid) && 467 (egid == (gid_t)-1 || egid == pruc->cr_gid) && 468 (sgid == (gid_t)-1 || sgid == pruc->cr_svgid)) 469 return (0); /* no change */ 470 471 /* 472 * Any of the real, effective, and saved gids may be changed 473 * to the current value of one of the three (root is not limited). 474 */ 475 if (rgid != (gid_t)-1 && 476 rgid != uc->cr_rgid && 477 rgid != uc->cr_gid && 478 rgid != uc->cr_svgid && 479 (error = suser(p, 0))) 480 return (error); 481 482 if (egid != (gid_t)-1 && 483 egid != uc->cr_rgid && 484 egid != uc->cr_gid && 485 egid != uc->cr_svgid && 486 (error = suser(p, 0))) 487 return (error); 488 489 if (sgid != (gid_t)-1 && 490 sgid != uc->cr_rgid && 491 sgid != uc->cr_gid && 492 sgid != uc->cr_svgid && 493 (error = suser(p, 0))) 494 return (error); 495 496 /* 497 * Copy credentials so other references do not see our changes. 498 * ps_ucred may change during the crget(). 499 */ 500 newcred = crget(); 501 pruc = pr->ps_ucred; 502 crset(newcred, pruc); 503 504 /* 505 * Note that unlike the other set*gid() calls, each 506 * gid type is set independently of the others. 507 */ 508 if (rgid != (gid_t)-1) 509 newcred->cr_rgid = rgid; 510 if (egid != (gid_t)-1) 511 newcred->cr_gid = egid; 512 if (sgid != (gid_t)-1) 513 newcred->cr_svgid = sgid; 514 pr->ps_ucred = newcred; 515 atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); 516 crfree(pruc); 517 return (0); 518 } 519 520 int 521 sys_setregid(struct proc *p, void *v, register_t *retval) 522 { 523 struct sys_setregid_args /* { 524 syscallarg(gid_t) rgid; 525 syscallarg(gid_t) egid; 526 } */ *uap = v; 527 struct process *pr = p->p_p; 528 struct ucred *pruc, *newcred, *uc = p->p_ucred; 529 gid_t rgid, egid; 530 int error; 531 532 rgid = SCARG(uap, rgid); 533 egid = SCARG(uap, egid); 534 535 /* 536 * make permission checks against the thread's ucred, 537 * but the actual changes will be to the process's ucred 538 * 539 * The saved gid check here is complicated: we reset the 540 * saved gid to the real gid if the real gid is specified 541 * *and* either it's changing _or_ the saved gid won't equal 542 * the effective gid. So, the svgid *won't* change when 543 * the rgid isn't specified or when the rgid isn't changing 544 * and the svgid equals the requested egid. 545 */ 546 pruc = pr->ps_ucred; 547 if ((rgid == (gid_t)-1 || rgid == pruc->cr_rgid) && 548 (egid == (gid_t)-1 || egid == pruc->cr_gid) && 549 (rgid == (gid_t)-1 || (rgid == pruc->cr_rgid && 550 pruc->cr_svgid == (egid != (gid_t)-1 ? egid : pruc->cr_gid)))) 551 return (0); /* no change */ 552 553 /* 554 * Any of the real, effective, and saved gids may be changed 555 * to the current value of one of the three (root is not limited). 556 */ 557 if (rgid != (gid_t)-1 && 558 rgid != uc->cr_rgid && 559 rgid != uc->cr_gid && 560 rgid != uc->cr_svgid && 561 (error = suser(p, 0))) 562 return (error); 563 564 if (egid != (gid_t)-1 && 565 egid != uc->cr_rgid && 566 egid != uc->cr_gid && 567 egid != uc->cr_svgid && 568 (error = suser(p, 0))) 569 return (error); 570 571 /* 572 * Copy credentials so other references do not see our changes. 573 * ps_ucred may change during the crget(). 574 */ 575 newcred = crget(); 576 pruc = pr->ps_ucred; 577 crset(newcred, pruc); 578 579 if (rgid != (gid_t)-1) 580 newcred->cr_rgid = rgid; 581 if (egid != (gid_t)-1) 582 newcred->cr_gid = egid; 583 584 /* 585 * The saved gid presents a bit of a dilemma, as it did not 586 * exist when setregid(2) was conceived. We only set the saved 587 * gid when the real gid is specified and either its value would 588 * change, or where the saved and effective gids are different. 589 */ 590 if (rgid != (gid_t)-1 && (rgid != pruc->cr_rgid || 591 pruc->cr_svgid != (egid != (gid_t)-1 ? egid : pruc->cr_gid))) 592 newcred->cr_svgid = rgid; 593 pr->ps_ucred = newcred; 594 atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); 595 crfree(pruc); 596 return (0); 597 } 598 599 int 600 sys_setreuid(struct proc *p, void *v, register_t *retval) 601 { 602 struct sys_setreuid_args /* { 603 syscallarg(uid_t) ruid; 604 syscallarg(uid_t) euid; 605 } */ *uap = v; 606 struct process *pr = p->p_p; 607 struct ucred *pruc, *newcred, *uc = p->p_ucred; 608 uid_t ruid, euid; 609 int error; 610 611 ruid = SCARG(uap, ruid); 612 euid = SCARG(uap, euid); 613 614 /* 615 * make permission checks against the thread's ucred, 616 * but the actual changes will be to the process's ucred 617 * 618 * The saved uid check here is complicated: we reset the 619 * saved uid to the real uid if the real uid is specified 620 * *and* either it's changing _or_ the saved uid won't equal 621 * the effective uid. So, the svuid *won't* change when 622 * the ruid isn't specified or when the ruid isn't changing 623 * and the svuid equals the requested euid. 624 */ 625 pruc = pr->ps_ucred; 626 if ((ruid == (uid_t)-1 || ruid == pruc->cr_ruid) && 627 (euid == (uid_t)-1 || euid == pruc->cr_uid) && 628 (ruid == (uid_t)-1 || (ruid == pruc->cr_ruid && 629 pruc->cr_svuid == (euid != (uid_t)-1 ? euid : pruc->cr_uid)))) 630 return (0); /* no change */ 631 632 /* 633 * Any of the real, effective, and saved uids may be changed 634 * to the current value of one of the three (root is not limited). 635 */ 636 if (ruid != (uid_t)-1 && 637 ruid != uc->cr_ruid && 638 ruid != uc->cr_uid && 639 ruid != uc->cr_svuid && 640 (error = suser(p, 0))) 641 return (error); 642 643 if (euid != (uid_t)-1 && 644 euid != uc->cr_ruid && 645 euid != uc->cr_uid && 646 euid != uc->cr_svuid && 647 (error = suser(p, 0))) 648 return (error); 649 650 /* 651 * Copy credentials so other references do not see our changes. 652 * ps_ucred may change during the crget(). 653 */ 654 newcred = crget(); 655 pruc = pr->ps_ucred; 656 crset(newcred, pruc); 657 658 if (ruid != (uid_t)-1) 659 newcred->cr_ruid = ruid; 660 if (euid != (uid_t)-1) 661 newcred->cr_uid = euid; 662 663 /* 664 * The saved uid presents a bit of a dilemma, as it did not 665 * exist when setreuid(2) was conceived. We only set the saved 666 * uid when the real uid is specified and either its value would 667 * change, or where the saved and effective uids are different. 668 */ 669 if (ruid != (uid_t)-1 && (ruid != pruc->cr_ruid || 670 pruc->cr_svuid != (euid != (uid_t)-1 ? euid : pruc->cr_uid))) 671 newcred->cr_svuid = ruid; 672 pr->ps_ucred = newcred; 673 atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); 674 675 /* now that we can sleep, transfer proc count to new user */ 676 if (ruid != (uid_t)-1 && ruid != pruc->cr_ruid) { 677 chgproccnt(pruc->cr_ruid, -1); 678 chgproccnt(ruid, 1); 679 } 680 crfree(pruc); 681 682 return (0); 683 } 684 685 int 686 sys_setuid(struct proc *p, void *v, register_t *retval) 687 { 688 struct sys_setuid_args /* { 689 syscallarg(uid_t) uid; 690 } */ *uap = v; 691 struct process *pr = p->p_p; 692 struct ucred *pruc, *newcred, *uc = p->p_ucred; 693 uid_t uid; 694 int did_real, error; 695 696 uid = SCARG(uap, uid); 697 698 pruc = pr->ps_ucred; 699 if (pruc->cr_uid == uid && 700 pruc->cr_ruid == uid && 701 pruc->cr_svuid == uid) 702 return (0); 703 704 if (uid != uc->cr_ruid && 705 uid != uc->cr_svuid && 706 uid != uc->cr_uid && 707 (error = suser(p, 0))) 708 return (error); 709 710 /* 711 * Copy credentials so other references do not see our changes. 712 * ps_ucred may change during the crget(). 713 */ 714 newcred = crget(); 715 pruc = pr->ps_ucred; 716 crset(newcred, pruc); 717 718 /* 719 * Everything's okay, do it. 720 */ 721 if (uid == pruc->cr_uid || suser(p, 0) == 0) { 722 did_real = 1; 723 newcred->cr_ruid = uid; 724 newcred->cr_svuid = uid; 725 } else 726 did_real = 0; 727 newcred->cr_uid = uid; 728 pr->ps_ucred = newcred; 729 atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); 730 731 /* 732 * Transfer proc count to new user. 733 */ 734 if (did_real && uid != pruc->cr_ruid) { 735 chgproccnt(pruc->cr_ruid, -1); 736 chgproccnt(uid, 1); 737 } 738 crfree(pruc); 739 740 return (0); 741 } 742 743 int 744 sys_seteuid(struct proc *p, void *v, register_t *retval) 745 { 746 struct sys_seteuid_args /* { 747 syscallarg(uid_t) euid; 748 } */ *uap = v; 749 struct process *pr = p->p_p; 750 struct ucred *pruc, *newcred, *uc = p->p_ucred; 751 uid_t euid; 752 int error; 753 754 euid = SCARG(uap, euid); 755 756 if (pr->ps_ucred->cr_uid == euid) 757 return (0); 758 759 if (euid != uc->cr_ruid && euid != uc->cr_svuid && 760 (error = suser(p, 0))) 761 return (error); 762 763 /* 764 * Copy credentials so other references do not see our changes. 765 * ps_ucred may change during the crget(). 766 */ 767 newcred = crget(); 768 pruc = pr->ps_ucred; 769 crset(newcred, pruc); 770 newcred->cr_uid = euid; 771 pr->ps_ucred = newcred; 772 atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); 773 crfree(pruc); 774 return (0); 775 } 776 777 int 778 sys_setgid(struct proc *p, void *v, register_t *retval) 779 { 780 struct sys_setgid_args /* { 781 syscallarg(gid_t) gid; 782 } */ *uap = v; 783 struct process *pr = p->p_p; 784 struct ucred *pruc, *newcred, *uc = p->p_ucred; 785 gid_t gid; 786 int error; 787 788 gid = SCARG(uap, gid); 789 790 pruc = pr->ps_ucred; 791 if (pruc->cr_gid == gid && 792 pruc->cr_rgid == gid && 793 pruc->cr_svgid == gid) 794 return (0); 795 796 if (gid != uc->cr_rgid && 797 gid != uc->cr_svgid && 798 gid != uc->cr_gid && 799 (error = suser(p, 0))) 800 return (error); 801 802 /* 803 * Copy credentials so other references do not see our changes. 804 * ps_ucred may change during the crget(). 805 */ 806 newcred = crget(); 807 pruc = pr->ps_ucred; 808 crset(newcred, pruc); 809 810 if (gid == pruc->cr_gid || suser(p, 0) == 0) { 811 newcred->cr_rgid = gid; 812 newcred->cr_svgid = gid; 813 } 814 newcred->cr_gid = gid; 815 pr->ps_ucred = newcred; 816 atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); 817 crfree(pruc); 818 return (0); 819 } 820 821 int 822 sys_setegid(struct proc *p, void *v, register_t *retval) 823 { 824 struct sys_setegid_args /* { 825 syscallarg(gid_t) egid; 826 } */ *uap = v; 827 struct process *pr = p->p_p; 828 struct ucred *pruc, *newcred, *uc = p->p_ucred; 829 gid_t egid; 830 int error; 831 832 egid = SCARG(uap, egid); 833 834 if (pr->ps_ucred->cr_gid == egid) 835 return (0); 836 837 if (egid != uc->cr_rgid && egid != uc->cr_svgid && 838 (error = suser(p, 0))) 839 return (error); 840 841 /* 842 * Copy credentials so other references do not see our changes. 843 * ps_ucred may change during the crget(). 844 */ 845 newcred = crget(); 846 pruc = pr->ps_ucred; 847 crset(newcred, pruc); 848 newcred->cr_gid = egid; 849 pr->ps_ucred = newcred; 850 atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); 851 crfree(pruc); 852 return (0); 853 } 854 855 int 856 sys_setgroups(struct proc *p, void *v, register_t *retval) 857 { 858 struct sys_setgroups_args /* { 859 syscallarg(int) gidsetsize; 860 syscallarg(const gid_t *) gidset; 861 } */ *uap = v; 862 struct process *pr = p->p_p; 863 struct ucred *pruc, *newcred; 864 gid_t groups[NGROUPS_MAX]; 865 u_int ngrp; 866 int error; 867 868 if ((error = suser(p, 0)) != 0) 869 return (error); 870 ngrp = SCARG(uap, gidsetsize); 871 if (ngrp > NGROUPS_MAX) 872 return (EINVAL); 873 error = copyin(SCARG(uap, gidset), groups, ngrp * sizeof(gid_t)); 874 if (error == 0) { 875 newcred = crget(); 876 pruc = pr->ps_ucred; 877 crset(newcred, pruc); 878 memcpy(newcred->cr_groups, groups, ngrp * sizeof(gid_t)); 879 newcred->cr_ngroups = ngrp; 880 pr->ps_ucred = newcred; 881 atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); 882 crfree(pruc); 883 } 884 return (error); 885 } 886 887 /* 888 * Check if gid is a member of the group set. 889 */ 890 int 891 groupmember(gid_t gid, struct ucred *cred) 892 { 893 gid_t *gp; 894 gid_t *egp; 895 896 if (cred->cr_gid == gid) 897 return (1); 898 egp = &(cred->cr_groups[cred->cr_ngroups]); 899 for (gp = cred->cr_groups; gp < egp; gp++) 900 if (*gp == gid) 901 return (1); 902 return (0); 903 } 904 905 /* 906 * Test whether this process has special user powers. 907 * Returns 0 or error. 908 */ 909 int 910 suser(struct proc *p, u_int flags) 911 { 912 struct ucred *cred = p->p_ucred; 913 914 if (cred->cr_uid == 0) { 915 if (!(flags & SUSER_NOACCT)) 916 p->p_p->ps_acflag |= ASU; 917 return (0); 918 } 919 return (EPERM); 920 } 921 922 /* 923 * replacement for old suser, for callers who don't have a process 924 */ 925 int 926 suser_ucred(struct ucred *cred) 927 { 928 if (cred->cr_uid == 0) 929 return (0); 930 return (EPERM); 931 } 932 933 /* 934 * Allocate a zeroed cred structure. 935 */ 936 struct ucred * 937 crget(void) 938 { 939 struct ucred *cr; 940 941 cr = pool_get(&ucred_pool, PR_WAITOK|PR_ZERO); 942 cr->cr_ref = 1; 943 return (cr); 944 } 945 946 /* 947 * Free a cred structure. 948 * Throws away space when ref count gets to 0. 949 */ 950 void 951 crfree(struct ucred *cr) 952 { 953 954 if (--cr->cr_ref == 0) 955 pool_put(&ucred_pool, cr); 956 } 957 958 /* 959 * Copy cred structure to a new one and free the old one. 960 */ 961 struct ucred * 962 crcopy(struct ucred *cr) 963 { 964 struct ucred *newcr; 965 966 if (cr->cr_ref == 1) 967 return (cr); 968 newcr = crget(); 969 *newcr = *cr; 970 crfree(cr); 971 newcr->cr_ref = 1; 972 return (newcr); 973 } 974 975 /* 976 * Dup cred struct to a new held one. 977 */ 978 struct ucred * 979 crdup(struct ucred *cr) 980 { 981 struct ucred *newcr; 982 983 newcr = crget(); 984 *newcr = *cr; 985 newcr->cr_ref = 1; 986 return (newcr); 987 } 988 989 /* 990 * Convert the userspace xucred to a kernel ucred 991 */ 992 int 993 crfromxucred(struct ucred *cr, const struct xucred *xcr) 994 { 995 if (xcr->cr_ngroups < 0 || xcr->cr_ngroups > NGROUPS_MAX) 996 return (EINVAL); 997 cr->cr_ref = 1; 998 cr->cr_uid = xcr->cr_uid; 999 cr->cr_gid = xcr->cr_gid; 1000 cr->cr_ngroups = xcr->cr_ngroups; 1001 memcpy(cr->cr_groups, xcr->cr_groups, 1002 sizeof(cr->cr_groups[0]) * xcr->cr_ngroups); 1003 return (0); 1004 } 1005 1006 /* 1007 * Get login name, if available. 1008 */ 1009 int 1010 sys_getlogin59(struct proc *p, void *v, register_t *retval) 1011 { 1012 struct sys_getlogin59_args /* { 1013 syscallarg(char *) namebuf; 1014 syscallarg(u_int) namelen; 1015 } */ *uap = v; 1016 struct session *s = p->p_p->ps_pgrp->pg_session; 1017 1018 if (SCARG(uap, namelen) > sizeof(s->s_login)) 1019 SCARG(uap, namelen) = sizeof(s->s_login); 1020 return (copyout((caddr_t)s->s_login, 1021 (caddr_t)SCARG(uap, namebuf), SCARG(uap, namelen))); 1022 } 1023 1024 /* 1025 * Get login name, if available. 1026 */ 1027 int 1028 sys_getlogin_r(struct proc *p, void *v, register_t *retval) 1029 { 1030 struct sys_getlogin_r_args /* { 1031 syscallarg(char *) namebuf; 1032 syscallarg(size_t) namelen; 1033 } */ *uap = v; 1034 size_t namelen = SCARG(uap, namelen); 1035 struct session *s = p->p_p->ps_pgrp->pg_session; 1036 int error; 1037 1038 if (namelen > sizeof(s->s_login)) 1039 namelen = sizeof(s->s_login); 1040 error = copyoutstr(s->s_login, SCARG(uap, namebuf), namelen, NULL); 1041 if (error == ENAMETOOLONG) 1042 error = ERANGE; 1043 *retval = error; 1044 return (0); 1045 } 1046 1047 /* 1048 * Set login name. 1049 */ 1050 int 1051 sys_setlogin(struct proc *p, void *v, register_t *retval) 1052 { 1053 struct sys_setlogin_args /* { 1054 syscallarg(const char *) namebuf; 1055 } */ *uap = v; 1056 struct session *s = p->p_p->ps_pgrp->pg_session; 1057 char buf[sizeof(s->s_login)]; 1058 int error; 1059 1060 if ((error = suser(p, 0)) != 0) 1061 return (error); 1062 error = copyinstr(SCARG(uap, namebuf), buf, sizeof(buf), NULL); 1063 if (error == 0) 1064 strlcpy(s->s_login, buf, sizeof(s->s_login)); 1065 else if (error == ENAMETOOLONG) 1066 error = EINVAL; 1067 return (error); 1068 } 1069 1070 /* 1071 * Check if a process is allowed to raise its privileges. 1072 */ 1073 int 1074 proc_cansugid(struct proc *p) 1075 { 1076 /* ptrace(2)d processes shouldn't. */ 1077 if ((p->p_p->ps_flags & PS_TRACED) != 0) 1078 return (0); 1079 1080 /* processes with shared filedescriptors shouldn't. */ 1081 if (p->p_fd->fd_refcnt > 1) 1082 return (0); 1083 1084 /* Allow. */ 1085 return (1); 1086 } 1087 1088 /* 1089 * Set address of the proc's thread-control-block 1090 */ 1091 int 1092 sys___set_tcb(struct proc *p, void *v, register_t *retval) 1093 { 1094 struct sys___set_tcb_args /* { 1095 syscallarg(void *) tcb; 1096 } */ *uap = v; 1097 1098 TCB_SET(p, SCARG(uap, tcb)); 1099 return (0); 1100 } 1101 1102 /* 1103 * Get address of the proc's thread-control-block 1104 */ 1105 int 1106 sys___get_tcb(struct proc *p, void *v, register_t *retval) 1107 { 1108 *retval = (register_t)TCB_GET(p); 1109 return (0); 1110 } 1111 1112 /* 1113 * Refresh the thread's reference to the process's credentials 1114 */ 1115 void 1116 dorefreshcreds(struct process *pr, struct proc *p) 1117 { 1118 struct ucred *uc = p->p_ucred; 1119 1120 KERNEL_LOCK(); /* XXX should be PROCESS_RLOCK(pr) */ 1121 if (uc != pr->ps_ucred) { 1122 p->p_ucred = pr->ps_ucred; 1123 crhold(p->p_ucred); 1124 crfree(uc); 1125 } 1126 KERNEL_UNLOCK(); 1127 } 1128