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