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