1 /* $OpenBSD: kern_prot.c,v 1.68 2017/04/13 03:52:25 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 #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, 0))) 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, 0))) 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, 0))) 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, 0))) 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, 0))) 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, 0))) 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, 0))) 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, 0))) 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, 0))) 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, 0))) 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, 0))) 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) == 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, 0))) 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, 0))) 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) == 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, 0))) 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)) != 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, u_int flags) 908 { 909 struct ucred *cred = p->p_ucred; 910 911 if (cred->cr_uid == 0) { 912 if (!(flags & SUSER_NOACCT)) 913 p->p_p->ps_acflag |= ASU; 914 return (0); 915 } 916 return (EPERM); 917 } 918 919 /* 920 * replacement for old suser, for callers who don't have a process 921 */ 922 int 923 suser_ucred(struct ucred *cred) 924 { 925 if (cred->cr_uid == 0) 926 return (0); 927 return (EPERM); 928 } 929 930 /* 931 * Allocate a zeroed cred structure. 932 */ 933 struct ucred * 934 crget(void) 935 { 936 struct ucred *cr; 937 938 cr = pool_get(&ucred_pool, PR_WAITOK|PR_ZERO); 939 cr->cr_ref = 1; 940 return (cr); 941 } 942 943 /* 944 * Free a cred structure. 945 * Throws away space when ref count gets to 0. 946 */ 947 void 948 crfree(struct ucred *cr) 949 { 950 951 if (--cr->cr_ref == 0) 952 pool_put(&ucred_pool, cr); 953 } 954 955 /* 956 * Copy cred structure to a new one and free the old one. 957 */ 958 struct ucred * 959 crcopy(struct ucred *cr) 960 { 961 struct ucred *newcr; 962 963 if (cr->cr_ref == 1) 964 return (cr); 965 newcr = crget(); 966 *newcr = *cr; 967 crfree(cr); 968 newcr->cr_ref = 1; 969 return (newcr); 970 } 971 972 /* 973 * Dup cred struct to a new held one. 974 */ 975 struct ucred * 976 crdup(struct ucred *cr) 977 { 978 struct ucred *newcr; 979 980 newcr = crget(); 981 *newcr = *cr; 982 newcr->cr_ref = 1; 983 return (newcr); 984 } 985 986 /* 987 * Convert the userspace xucred to a kernel ucred 988 */ 989 int 990 crfromxucred(struct ucred *cr, const struct xucred *xcr) 991 { 992 if (xcr->cr_ngroups < 0 || xcr->cr_ngroups > NGROUPS_MAX) 993 return (EINVAL); 994 cr->cr_ref = 1; 995 cr->cr_uid = xcr->cr_uid; 996 cr->cr_gid = xcr->cr_gid; 997 cr->cr_ngroups = xcr->cr_ngroups; 998 memcpy(cr->cr_groups, xcr->cr_groups, 999 sizeof(cr->cr_groups[0]) * xcr->cr_ngroups); 1000 return (0); 1001 } 1002 1003 /* 1004 * Get login name, if available. 1005 */ 1006 int 1007 sys_getlogin59(struct proc *p, void *v, register_t *retval) 1008 { 1009 struct sys_getlogin59_args /* { 1010 syscallarg(char *) namebuf; 1011 syscallarg(u_int) namelen; 1012 } */ *uap = v; 1013 struct session *s = p->p_p->ps_pgrp->pg_session; 1014 1015 if (SCARG(uap, namelen) > sizeof(s->s_login)) 1016 SCARG(uap, namelen) = sizeof(s->s_login); 1017 return (copyout((caddr_t)s->s_login, 1018 (caddr_t)SCARG(uap, namebuf), SCARG(uap, namelen))); 1019 } 1020 1021 /* 1022 * Get login name, if available. 1023 */ 1024 int 1025 sys_getlogin_r(struct proc *p, void *v, register_t *retval) 1026 { 1027 struct sys_getlogin_r_args /* { 1028 syscallarg(char *) namebuf; 1029 syscallarg(size_t) namelen; 1030 } */ *uap = v; 1031 size_t namelen = SCARG(uap, namelen); 1032 struct session *s = p->p_p->ps_pgrp->pg_session; 1033 int error; 1034 1035 if (namelen > sizeof(s->s_login)) 1036 namelen = sizeof(s->s_login); 1037 error = copyoutstr(s->s_login, SCARG(uap, namebuf), namelen, NULL); 1038 if (error == ENAMETOOLONG) 1039 error = ERANGE; 1040 *retval = error; 1041 return (0); 1042 } 1043 1044 /* 1045 * Set login name. 1046 */ 1047 int 1048 sys_setlogin(struct proc *p, void *v, register_t *retval) 1049 { 1050 struct sys_setlogin_args /* { 1051 syscallarg(const char *) namebuf; 1052 } */ *uap = v; 1053 struct session *s = p->p_p->ps_pgrp->pg_session; 1054 char buf[sizeof(s->s_login)]; 1055 int error; 1056 1057 if ((error = suser(p, 0)) != 0) 1058 return (error); 1059 error = copyinstr(SCARG(uap, namebuf), buf, sizeof(buf), NULL); 1060 if (error == 0) 1061 strlcpy(s->s_login, buf, sizeof(s->s_login)); 1062 else if (error == ENAMETOOLONG) 1063 error = EINVAL; 1064 return (error); 1065 } 1066 1067 /* 1068 * Check if a process is allowed to raise its privileges. 1069 */ 1070 int 1071 proc_cansugid(struct proc *p) 1072 { 1073 /* ptrace(2)d processes shouldn't. */ 1074 if ((p->p_p->ps_flags & PS_TRACED) != 0) 1075 return (0); 1076 1077 /* processes with shared filedescriptors shouldn't. */ 1078 if (p->p_fd->fd_refcnt > 1) 1079 return (0); 1080 1081 /* Allow. */ 1082 return (1); 1083 } 1084 1085 /* 1086 * Set address of the proc's thread-control-block 1087 */ 1088 int 1089 sys___set_tcb(struct proc *p, void *v, register_t *retval) 1090 { 1091 struct sys___set_tcb_args /* { 1092 syscallarg(void *) tcb; 1093 } */ *uap = v; 1094 1095 TCB_SET(p, SCARG(uap, tcb)); 1096 return (0); 1097 } 1098 1099 /* 1100 * Get address of the proc's thread-control-block 1101 */ 1102 int 1103 sys___get_tcb(struct proc *p, void *v, register_t *retval) 1104 { 1105 *retval = (register_t)TCB_GET(p); 1106 return (0); 1107 } 1108 1109 /* 1110 * Refresh the thread's reference to the process's credentials 1111 */ 1112 void 1113 dorefreshcreds(struct process *pr, struct proc *p) 1114 { 1115 struct ucred *uc = p->p_ucred; 1116 1117 KERNEL_LOCK(); /* XXX should be PROCESS_RLOCK(pr) */ 1118 if (uc != pr->ps_ucred) { 1119 p->p_ucred = pr->ps_ucred; 1120 crhold(p->p_ucred); 1121 crfree(uc); 1122 } 1123 KERNEL_UNLOCK(); 1124 } 1125