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