1 /* $OpenBSD: kern_prot.c,v 1.72 2018/02/19 08:59:52 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 timeout_set(&newsess->s_verauthto, zapverauth, newsess); 226 newpgrp = pool_get(&pgrp_pool, PR_WAITOK); 227 228 if (pr->ps_pgid == pid || pgfind(pid)) { 229 pool_put(&pgrp_pool, newpgrp); 230 pool_put(&session_pool, newsess); 231 return (EPERM); 232 } else { 233 (void) enterpgrp(pr, pid, 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)) == 0 || !inferior(targpr, curpr)) { 275 error = ESRCH; 276 goto out; 277 } 278 if (targpr->ps_session != curpr->ps_session) { 279 error = EPERM; 280 goto out; 281 } 282 if (targpr->ps_flags & PS_EXEC) { 283 error = EACCES; 284 goto out; 285 } 286 } else 287 targpr = curpr; 288 if (SESS_LEADER(targpr)) { 289 error = EPERM; 290 goto out; 291 } 292 if (pgid == 0) 293 pgid = targpr->ps_pid; 294 else if (pgid != targpr->ps_pid) 295 if ((pgrp = pgfind(pgid)) == 0 || 296 pgrp->pg_session != curpr->ps_session) { 297 error = EPERM; 298 goto out; 299 } 300 return (enterpgrp(targpr, pgid, newpgrp, NULL)); 301 out: 302 pool_put(&pgrp_pool, newpgrp); 303 return (error); 304 } 305 306 int 307 sys_getresuid(struct proc *p, void *v, register_t *retval) 308 { 309 struct sys_getresuid_args /* { 310 syscallarg(uid_t *) ruid; 311 syscallarg(uid_t *) euid; 312 syscallarg(uid_t *) suid; 313 } */ *uap = v; 314 struct ucred *uc = p->p_ucred; 315 uid_t *ruid, *euid, *suid; 316 int error1 = 0, error2 = 0, error3 = 0; 317 318 ruid = SCARG(uap, ruid); 319 euid = SCARG(uap, euid); 320 suid = SCARG(uap, suid); 321 322 if (ruid != NULL) 323 error1 = copyout(&uc->cr_ruid, ruid, sizeof(*ruid)); 324 if (euid != NULL) 325 error2 = copyout(&uc->cr_uid, euid, sizeof(*euid)); 326 if (suid != NULL) 327 error3 = copyout(&uc->cr_svuid, suid, sizeof(*suid)); 328 329 return (error1 ? error1 : error2 ? error2 : error3); 330 } 331 332 int 333 sys_setresuid(struct proc *p, void *v, register_t *retval) 334 { 335 struct sys_setresuid_args /* { 336 syscallarg(uid_t) ruid; 337 syscallarg(uid_t) euid; 338 syscallarg(uid_t) suid; 339 } */ *uap = v; 340 struct process *pr = p->p_p; 341 struct ucred *pruc, *newcred, *uc = p->p_ucred; 342 uid_t ruid, euid, suid; 343 int error; 344 345 ruid = SCARG(uap, ruid); 346 euid = SCARG(uap, euid); 347 suid = SCARG(uap, suid); 348 349 /* 350 * make permission checks against the thread's ucred, 351 * but the actual changes will be to the process's ucred 352 */ 353 pruc = pr->ps_ucred; 354 if ((ruid == (uid_t)-1 || ruid == pruc->cr_ruid) && 355 (euid == (uid_t)-1 || euid == pruc->cr_uid) && 356 (suid == (uid_t)-1 || suid == pruc->cr_svuid)) 357 return (0); /* no change */ 358 359 /* 360 * Any of the real, effective, and saved uids may be changed 361 * to the current value of one of the three (root is not limited). 362 */ 363 if (ruid != (uid_t)-1 && 364 ruid != uc->cr_ruid && 365 ruid != uc->cr_uid && 366 ruid != uc->cr_svuid && 367 (error = suser(p))) 368 return (error); 369 370 if (euid != (uid_t)-1 && 371 euid != uc->cr_ruid && 372 euid != uc->cr_uid && 373 euid != uc->cr_svuid && 374 (error = suser(p))) 375 return (error); 376 377 if (suid != (uid_t)-1 && 378 suid != uc->cr_ruid && 379 suid != uc->cr_uid && 380 suid != uc->cr_svuid && 381 (error = suser(p))) 382 return (error); 383 384 /* 385 * Copy credentials so other references do not see our changes. 386 * ps_ucred may change during the crget(). 387 */ 388 newcred = crget(); 389 pruc = pr->ps_ucred; 390 crset(newcred, pruc); 391 392 /* 393 * Note that unlike the other set*uid() calls, each 394 * uid type is set independently of the others. 395 */ 396 if (ruid != (uid_t)-1) 397 newcred->cr_ruid = ruid; 398 if (euid != (uid_t)-1) 399 newcred->cr_uid = euid; 400 if (suid != (uid_t)-1) 401 newcred->cr_svuid = suid; 402 pr->ps_ucred = newcred; 403 atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); 404 405 /* now that we can sleep, transfer proc count to new user */ 406 if (ruid != (uid_t)-1 && ruid != pruc->cr_ruid) { 407 chgproccnt(pruc->cr_ruid, -1); 408 chgproccnt(ruid, 1); 409 } 410 crfree(pruc); 411 412 return (0); 413 } 414 415 int 416 sys_getresgid(struct proc *p, void *v, register_t *retval) 417 { 418 struct sys_getresgid_args /* { 419 syscallarg(gid_t *) rgid; 420 syscallarg(gid_t *) egid; 421 syscallarg(gid_t *) sgid; 422 } */ *uap = v; 423 struct ucred *uc = p->p_ucred; 424 gid_t *rgid, *egid, *sgid; 425 int error1 = 0, error2 = 0, error3 = 0; 426 427 rgid = SCARG(uap, rgid); 428 egid = SCARG(uap, egid); 429 sgid = SCARG(uap, sgid); 430 431 if (rgid != NULL) 432 error1 = copyout(&uc->cr_rgid, rgid, sizeof(*rgid)); 433 if (egid != NULL) 434 error2 = copyout(&uc->cr_gid, egid, sizeof(*egid)); 435 if (sgid != NULL) 436 error3 = copyout(&uc->cr_svgid, sgid, sizeof(*sgid)); 437 438 return (error1 ? error1 : error2 ? error2 : error3); 439 } 440 441 int 442 sys_setresgid(struct proc *p, void *v, register_t *retval) 443 { 444 struct sys_setresgid_args /* { 445 syscallarg(gid_t) rgid; 446 syscallarg(gid_t) egid; 447 syscallarg(gid_t) sgid; 448 } */ *uap = v; 449 struct process *pr = p->p_p; 450 struct ucred *pruc, *newcred, *uc = p->p_ucred; 451 gid_t rgid, egid, sgid; 452 int error; 453 454 rgid = SCARG(uap, rgid); 455 egid = SCARG(uap, egid); 456 sgid = SCARG(uap, sgid); 457 458 /* 459 * make permission checks against the thread's ucred, 460 * but the actual changes will be to the process's ucred 461 */ 462 pruc = pr->ps_ucred; 463 if ((rgid == (gid_t)-1 || rgid == pruc->cr_rgid) && 464 (egid == (gid_t)-1 || egid == pruc->cr_gid) && 465 (sgid == (gid_t)-1 || sgid == pruc->cr_svgid)) 466 return (0); /* no change */ 467 468 /* 469 * Any of the real, effective, and saved gids may be changed 470 * to the current value of one of the three (root is not limited). 471 */ 472 if (rgid != (gid_t)-1 && 473 rgid != uc->cr_rgid && 474 rgid != uc->cr_gid && 475 rgid != uc->cr_svgid && 476 (error = suser(p))) 477 return (error); 478 479 if (egid != (gid_t)-1 && 480 egid != uc->cr_rgid && 481 egid != uc->cr_gid && 482 egid != uc->cr_svgid && 483 (error = suser(p))) 484 return (error); 485 486 if (sgid != (gid_t)-1 && 487 sgid != uc->cr_rgid && 488 sgid != uc->cr_gid && 489 sgid != uc->cr_svgid && 490 (error = suser(p))) 491 return (error); 492 493 /* 494 * Copy credentials so other references do not see our changes. 495 * ps_ucred may change during the crget(). 496 */ 497 newcred = crget(); 498 pruc = pr->ps_ucred; 499 crset(newcred, pruc); 500 501 /* 502 * Note that unlike the other set*gid() calls, each 503 * gid type is set independently of the others. 504 */ 505 if (rgid != (gid_t)-1) 506 newcred->cr_rgid = rgid; 507 if (egid != (gid_t)-1) 508 newcred->cr_gid = egid; 509 if (sgid != (gid_t)-1) 510 newcred->cr_svgid = sgid; 511 pr->ps_ucred = newcred; 512 atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); 513 crfree(pruc); 514 return (0); 515 } 516 517 int 518 sys_setregid(struct proc *p, void *v, register_t *retval) 519 { 520 struct sys_setregid_args /* { 521 syscallarg(gid_t) rgid; 522 syscallarg(gid_t) egid; 523 } */ *uap = v; 524 struct process *pr = p->p_p; 525 struct ucred *pruc, *newcred, *uc = p->p_ucred; 526 gid_t rgid, egid; 527 int error; 528 529 rgid = SCARG(uap, rgid); 530 egid = SCARG(uap, egid); 531 532 /* 533 * make permission checks against the thread's ucred, 534 * but the actual changes will be to the process's ucred 535 * 536 * The saved gid check here is complicated: we reset the 537 * saved gid to the real gid if the real gid is specified 538 * *and* either it's changing _or_ the saved gid won't equal 539 * the effective gid. So, the svgid *won't* change when 540 * the rgid isn't specified or when the rgid isn't changing 541 * and the svgid equals the requested egid. 542 */ 543 pruc = pr->ps_ucred; 544 if ((rgid == (gid_t)-1 || rgid == pruc->cr_rgid) && 545 (egid == (gid_t)-1 || egid == pruc->cr_gid) && 546 (rgid == (gid_t)-1 || (rgid == pruc->cr_rgid && 547 pruc->cr_svgid == (egid != (gid_t)-1 ? egid : pruc->cr_gid)))) 548 return (0); /* no change */ 549 550 /* 551 * Any of the real, effective, and saved gids may be changed 552 * to the current value of one of the three (root is not limited). 553 */ 554 if (rgid != (gid_t)-1 && 555 rgid != uc->cr_rgid && 556 rgid != uc->cr_gid && 557 rgid != uc->cr_svgid && 558 (error = suser(p))) 559 return (error); 560 561 if (egid != (gid_t)-1 && 562 egid != uc->cr_rgid && 563 egid != uc->cr_gid && 564 egid != uc->cr_svgid && 565 (error = suser(p))) 566 return (error); 567 568 /* 569 * Copy credentials so other references do not see our changes. 570 * ps_ucred may change during the crget(). 571 */ 572 newcred = crget(); 573 pruc = pr->ps_ucred; 574 crset(newcred, pruc); 575 576 if (rgid != (gid_t)-1) 577 newcred->cr_rgid = rgid; 578 if (egid != (gid_t)-1) 579 newcred->cr_gid = egid; 580 581 /* 582 * The saved gid presents a bit of a dilemma, as it did not 583 * exist when setregid(2) was conceived. We only set the saved 584 * gid when the real gid is specified and either its value would 585 * change, or where the saved and effective gids are different. 586 */ 587 if (rgid != (gid_t)-1 && (rgid != pruc->cr_rgid || 588 pruc->cr_svgid != (egid != (gid_t)-1 ? egid : pruc->cr_gid))) 589 newcred->cr_svgid = rgid; 590 pr->ps_ucred = newcred; 591 atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); 592 crfree(pruc); 593 return (0); 594 } 595 596 int 597 sys_setreuid(struct proc *p, void *v, register_t *retval) 598 { 599 struct sys_setreuid_args /* { 600 syscallarg(uid_t) ruid; 601 syscallarg(uid_t) euid; 602 } */ *uap = v; 603 struct process *pr = p->p_p; 604 struct ucred *pruc, *newcred, *uc = p->p_ucred; 605 uid_t ruid, euid; 606 int error; 607 608 ruid = SCARG(uap, ruid); 609 euid = SCARG(uap, euid); 610 611 /* 612 * make permission checks against the thread's ucred, 613 * but the actual changes will be to the process's ucred 614 * 615 * The saved uid check here is complicated: we reset the 616 * saved uid to the real uid if the real uid is specified 617 * *and* either it's changing _or_ the saved uid won't equal 618 * the effective uid. So, the svuid *won't* change when 619 * the ruid isn't specified or when the ruid isn't changing 620 * and the svuid equals the requested euid. 621 */ 622 pruc = pr->ps_ucred; 623 if ((ruid == (uid_t)-1 || ruid == pruc->cr_ruid) && 624 (euid == (uid_t)-1 || euid == pruc->cr_uid) && 625 (ruid == (uid_t)-1 || (ruid == pruc->cr_ruid && 626 pruc->cr_svuid == (euid != (uid_t)-1 ? euid : pruc->cr_uid)))) 627 return (0); /* no change */ 628 629 /* 630 * Any of the real, effective, and saved uids may be changed 631 * to the current value of one of the three (root is not limited). 632 */ 633 if (ruid != (uid_t)-1 && 634 ruid != uc->cr_ruid && 635 ruid != uc->cr_uid && 636 ruid != uc->cr_svuid && 637 (error = suser(p))) 638 return (error); 639 640 if (euid != (uid_t)-1 && 641 euid != uc->cr_ruid && 642 euid != uc->cr_uid && 643 euid != uc->cr_svuid && 644 (error = suser(p))) 645 return (error); 646 647 /* 648 * Copy credentials so other references do not see our changes. 649 * ps_ucred may change during the crget(). 650 */ 651 newcred = crget(); 652 pruc = pr->ps_ucred; 653 crset(newcred, pruc); 654 655 if (ruid != (uid_t)-1) 656 newcred->cr_ruid = ruid; 657 if (euid != (uid_t)-1) 658 newcred->cr_uid = euid; 659 660 /* 661 * The saved uid presents a bit of a dilemma, as it did not 662 * exist when setreuid(2) was conceived. We only set the saved 663 * uid when the real uid is specified and either its value would 664 * change, or where the saved and effective uids are different. 665 */ 666 if (ruid != (uid_t)-1 && (ruid != pruc->cr_ruid || 667 pruc->cr_svuid != (euid != (uid_t)-1 ? euid : pruc->cr_uid))) 668 newcred->cr_svuid = ruid; 669 pr->ps_ucred = newcred; 670 atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); 671 672 /* now that we can sleep, transfer proc count to new user */ 673 if (ruid != (uid_t)-1 && ruid != pruc->cr_ruid) { 674 chgproccnt(pruc->cr_ruid, -1); 675 chgproccnt(ruid, 1); 676 } 677 crfree(pruc); 678 679 return (0); 680 } 681 682 int 683 sys_setuid(struct proc *p, void *v, register_t *retval) 684 { 685 struct sys_setuid_args /* { 686 syscallarg(uid_t) uid; 687 } */ *uap = v; 688 struct process *pr = p->p_p; 689 struct ucred *pruc, *newcred, *uc = p->p_ucred; 690 uid_t uid; 691 int did_real, error; 692 693 uid = SCARG(uap, uid); 694 695 pruc = pr->ps_ucred; 696 if (pruc->cr_uid == uid && 697 pruc->cr_ruid == uid && 698 pruc->cr_svuid == uid) 699 return (0); 700 701 if (uid != uc->cr_ruid && 702 uid != uc->cr_svuid && 703 uid != uc->cr_uid && 704 (error = suser(p))) 705 return (error); 706 707 /* 708 * Copy credentials so other references do not see our changes. 709 * ps_ucred may change during the crget(). 710 */ 711 newcred = crget(); 712 pruc = pr->ps_ucred; 713 crset(newcred, pruc); 714 715 /* 716 * Everything's okay, do it. 717 */ 718 if (uid == pruc->cr_uid || suser(p) == 0) { 719 did_real = 1; 720 newcred->cr_ruid = uid; 721 newcred->cr_svuid = uid; 722 } else 723 did_real = 0; 724 newcred->cr_uid = uid; 725 pr->ps_ucred = newcred; 726 atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); 727 728 /* 729 * Transfer proc count to new user. 730 */ 731 if (did_real && uid != pruc->cr_ruid) { 732 chgproccnt(pruc->cr_ruid, -1); 733 chgproccnt(uid, 1); 734 } 735 crfree(pruc); 736 737 return (0); 738 } 739 740 int 741 sys_seteuid(struct proc *p, void *v, register_t *retval) 742 { 743 struct sys_seteuid_args /* { 744 syscallarg(uid_t) euid; 745 } */ *uap = v; 746 struct process *pr = p->p_p; 747 struct ucred *pruc, *newcred, *uc = p->p_ucred; 748 uid_t euid; 749 int error; 750 751 euid = SCARG(uap, euid); 752 753 if (pr->ps_ucred->cr_uid == euid) 754 return (0); 755 756 if (euid != uc->cr_ruid && euid != uc->cr_svuid && 757 (error = suser(p))) 758 return (error); 759 760 /* 761 * Copy credentials so other references do not see our changes. 762 * ps_ucred may change during the crget(). 763 */ 764 newcred = crget(); 765 pruc = pr->ps_ucred; 766 crset(newcred, pruc); 767 newcred->cr_uid = euid; 768 pr->ps_ucred = newcred; 769 atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); 770 crfree(pruc); 771 return (0); 772 } 773 774 int 775 sys_setgid(struct proc *p, void *v, register_t *retval) 776 { 777 struct sys_setgid_args /* { 778 syscallarg(gid_t) gid; 779 } */ *uap = v; 780 struct process *pr = p->p_p; 781 struct ucred *pruc, *newcred, *uc = p->p_ucred; 782 gid_t gid; 783 int error; 784 785 gid = SCARG(uap, gid); 786 787 pruc = pr->ps_ucred; 788 if (pruc->cr_gid == gid && 789 pruc->cr_rgid == gid && 790 pruc->cr_svgid == gid) 791 return (0); 792 793 if (gid != uc->cr_rgid && 794 gid != uc->cr_svgid && 795 gid != uc->cr_gid && 796 (error = suser(p))) 797 return (error); 798 799 /* 800 * Copy credentials so other references do not see our changes. 801 * ps_ucred may change during the crget(). 802 */ 803 newcred = crget(); 804 pruc = pr->ps_ucred; 805 crset(newcred, pruc); 806 807 if (gid == pruc->cr_gid || suser(p) == 0) { 808 newcred->cr_rgid = gid; 809 newcred->cr_svgid = gid; 810 } 811 newcred->cr_gid = gid; 812 pr->ps_ucred = newcred; 813 atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); 814 crfree(pruc); 815 return (0); 816 } 817 818 int 819 sys_setegid(struct proc *p, void *v, register_t *retval) 820 { 821 struct sys_setegid_args /* { 822 syscallarg(gid_t) egid; 823 } */ *uap = v; 824 struct process *pr = p->p_p; 825 struct ucred *pruc, *newcred, *uc = p->p_ucred; 826 gid_t egid; 827 int error; 828 829 egid = SCARG(uap, egid); 830 831 if (pr->ps_ucred->cr_gid == egid) 832 return (0); 833 834 if (egid != uc->cr_rgid && egid != uc->cr_svgid && 835 (error = suser(p))) 836 return (error); 837 838 /* 839 * Copy credentials so other references do not see our changes. 840 * ps_ucred may change during the crget(). 841 */ 842 newcred = crget(); 843 pruc = pr->ps_ucred; 844 crset(newcred, pruc); 845 newcred->cr_gid = egid; 846 pr->ps_ucred = newcred; 847 atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); 848 crfree(pruc); 849 return (0); 850 } 851 852 int 853 sys_setgroups(struct proc *p, void *v, register_t *retval) 854 { 855 struct sys_setgroups_args /* { 856 syscallarg(int) gidsetsize; 857 syscallarg(const gid_t *) gidset; 858 } */ *uap = v; 859 struct process *pr = p->p_p; 860 struct ucred *pruc, *newcred; 861 gid_t groups[NGROUPS_MAX]; 862 u_int ngrp; 863 int error; 864 865 if ((error = suser(p)) != 0) 866 return (error); 867 ngrp = SCARG(uap, gidsetsize); 868 if (ngrp > NGROUPS_MAX) 869 return (EINVAL); 870 error = copyin(SCARG(uap, gidset), groups, ngrp * sizeof(gid_t)); 871 if (error == 0) { 872 newcred = crget(); 873 pruc = pr->ps_ucred; 874 crset(newcred, pruc); 875 memcpy(newcred->cr_groups, groups, ngrp * sizeof(gid_t)); 876 newcred->cr_ngroups = ngrp; 877 pr->ps_ucred = newcred; 878 atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); 879 crfree(pruc); 880 } 881 return (error); 882 } 883 884 /* 885 * Check if gid is a member of the group set. 886 */ 887 int 888 groupmember(gid_t gid, struct ucred *cred) 889 { 890 gid_t *gp; 891 gid_t *egp; 892 893 if (cred->cr_gid == gid) 894 return (1); 895 egp = &(cred->cr_groups[cred->cr_ngroups]); 896 for (gp = cred->cr_groups; gp < egp; gp++) 897 if (*gp == gid) 898 return (1); 899 return (0); 900 } 901 902 /* 903 * Test whether this process has special user powers. 904 * Returns 0 or error. 905 */ 906 int 907 suser(struct proc *p) 908 { 909 struct ucred *cred = p->p_ucred; 910 911 if (cred->cr_uid == 0) 912 return (0); 913 return (EPERM); 914 } 915 916 /* 917 * replacement for old suser, for callers who don't have a process 918 */ 919 int 920 suser_ucred(struct ucred *cred) 921 { 922 if (cred->cr_uid == 0) 923 return (0); 924 return (EPERM); 925 } 926 927 /* 928 * Allocate a zeroed cred structure. 929 */ 930 struct ucred * 931 crget(void) 932 { 933 struct ucred *cr; 934 935 cr = pool_get(&ucred_pool, PR_WAITOK|PR_ZERO); 936 cr->cr_ref = 1; 937 return (cr); 938 } 939 940 /* 941 * Free a cred structure. 942 * Throws away space when ref count gets to 0. 943 */ 944 void 945 crfree(struct ucred *cr) 946 { 947 948 if (--cr->cr_ref == 0) 949 pool_put(&ucred_pool, cr); 950 } 951 952 /* 953 * Copy cred structure to a new one and free the old one. 954 */ 955 struct ucred * 956 crcopy(struct ucred *cr) 957 { 958 struct ucred *newcr; 959 960 if (cr->cr_ref == 1) 961 return (cr); 962 newcr = crget(); 963 *newcr = *cr; 964 crfree(cr); 965 newcr->cr_ref = 1; 966 return (newcr); 967 } 968 969 /* 970 * Dup cred struct to a new held one. 971 */ 972 struct ucred * 973 crdup(struct ucred *cr) 974 { 975 struct ucred *newcr; 976 977 newcr = crget(); 978 *newcr = *cr; 979 newcr->cr_ref = 1; 980 return (newcr); 981 } 982 983 /* 984 * Convert the userspace xucred to a kernel ucred 985 */ 986 int 987 crfromxucred(struct ucred *cr, const struct xucred *xcr) 988 { 989 if (xcr->cr_ngroups < 0 || xcr->cr_ngroups > NGROUPS_MAX) 990 return (EINVAL); 991 cr->cr_ref = 1; 992 cr->cr_uid = xcr->cr_uid; 993 cr->cr_gid = xcr->cr_gid; 994 cr->cr_ngroups = xcr->cr_ngroups; 995 memcpy(cr->cr_groups, xcr->cr_groups, 996 sizeof(cr->cr_groups[0]) * xcr->cr_ngroups); 997 return (0); 998 } 999 1000 /* 1001 * Get login name, if available. 1002 */ 1003 int 1004 sys_getlogin_r(struct proc *p, void *v, register_t *retval) 1005 { 1006 struct sys_getlogin_r_args /* { 1007 syscallarg(char *) namebuf; 1008 syscallarg(size_t) namelen; 1009 } */ *uap = v; 1010 size_t namelen = SCARG(uap, namelen); 1011 struct session *s = p->p_p->ps_pgrp->pg_session; 1012 int error; 1013 1014 if (namelen > sizeof(s->s_login)) 1015 namelen = sizeof(s->s_login); 1016 error = copyoutstr(s->s_login, SCARG(uap, namebuf), namelen, NULL); 1017 if (error == ENAMETOOLONG) 1018 error = ERANGE; 1019 *retval = error; 1020 return (0); 1021 } 1022 1023 /* 1024 * Set login name. 1025 */ 1026 int 1027 sys_setlogin(struct proc *p, void *v, register_t *retval) 1028 { 1029 struct sys_setlogin_args /* { 1030 syscallarg(const char *) namebuf; 1031 } */ *uap = v; 1032 struct session *s = p->p_p->ps_pgrp->pg_session; 1033 char buf[sizeof(s->s_login)]; 1034 int error; 1035 1036 if ((error = suser(p)) != 0) 1037 return (error); 1038 error = copyinstr(SCARG(uap, namebuf), buf, sizeof(buf), NULL); 1039 if (error == 0) 1040 strlcpy(s->s_login, buf, sizeof(s->s_login)); 1041 else if (error == ENAMETOOLONG) 1042 error = EINVAL; 1043 return (error); 1044 } 1045 1046 /* 1047 * Check if a process is allowed to raise its privileges. 1048 */ 1049 int 1050 proc_cansugid(struct proc *p) 1051 { 1052 /* ptrace(2)d processes shouldn't. */ 1053 if ((p->p_p->ps_flags & PS_TRACED) != 0) 1054 return (0); 1055 1056 /* processes with shared filedescriptors shouldn't. */ 1057 if (p->p_fd->fd_refcnt > 1) 1058 return (0); 1059 1060 /* Allow. */ 1061 return (1); 1062 } 1063 1064 /* 1065 * Set address of the proc's thread-control-block 1066 */ 1067 int 1068 sys___set_tcb(struct proc *p, void *v, register_t *retval) 1069 { 1070 struct sys___set_tcb_args /* { 1071 syscallarg(void *) tcb; 1072 } */ *uap = v; 1073 void *tcb = SCARG(uap, tcb); 1074 1075 #ifdef TCB_INVALID 1076 if (TCB_INVALID(tcb)) 1077 return EINVAL; 1078 #endif /* TCB_INVALID */ 1079 TCB_SET(p, tcb); 1080 return (0); 1081 } 1082 1083 /* 1084 * Get address of the proc's thread-control-block 1085 */ 1086 int 1087 sys___get_tcb(struct proc *p, void *v, register_t *retval) 1088 { 1089 *retval = (register_t)TCB_GET(p); 1090 return (0); 1091 } 1092 1093 /* 1094 * Refresh the thread's reference to the process's credentials 1095 */ 1096 void 1097 dorefreshcreds(struct process *pr, struct proc *p) 1098 { 1099 struct ucred *uc = p->p_ucred; 1100 1101 KERNEL_LOCK(); /* XXX should be PROCESS_RLOCK(pr) */ 1102 if (uc != pr->ps_ucred) { 1103 p->p_ucred = pr->ps_ucred; 1104 crhold(p->p_ucred); 1105 crfree(uc); 1106 } 1107 KERNEL_UNLOCK(); 1108 } 1109