|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986, 1989, 1990, 1991 Regents of the University ! 3: * of California. All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: * ! 33: * @(#)kern_prot.c 7.21 (Berkeley) 5/3/91 ! 34: */ ! 35: ! 36: /* ! 37: * System calls related to processes and protection ! 38: */ ! 39: ! 40: #include "param.h" ! 41: #include "acct.h" ! 42: #include "systm.h" ! 43: #include "ucred.h" ! 44: #include "proc.h" ! 45: #include "timeb.h" ! 46: #include "times.h" ! 47: #include "malloc.h" ! 48: ! 49: /* ARGSUSED */ ! 50: getpid(p, uap, retval) ! 51: struct proc *p; ! 52: void *uap; ! 53: int *retval; ! 54: { ! 55: ! 56: *retval = p->p_pid; ! 57: #ifdef COMPAT_43 ! 58: retval[1] = p->p_pptr->p_pid; ! 59: #endif ! 60: return (0); ! 61: } ! 62: ! 63: /* ARGSUSED */ ! 64: getppid(p, uap, retval) ! 65: struct proc *p; ! 66: void *uap; ! 67: int *retval; ! 68: { ! 69: ! 70: *retval = p->p_pptr->p_pid; ! 71: return (0); ! 72: } ! 73: ! 74: /* Get process group ID; note that POSIX getpgrp takes no parameter */ ! 75: getpgrp(p, uap, retval) ! 76: struct proc *p; ! 77: void *uap; ! 78: int *retval; ! 79: { ! 80: ! 81: *retval = p->p_pgrp->pg_id; ! 82: return (0); ! 83: } ! 84: ! 85: /* ARGSUSED */ ! 86: getuid(p, uap, retval) ! 87: struct proc *p; ! 88: void *uap; ! 89: int *retval; ! 90: { ! 91: ! 92: *retval = p->p_cred->p_ruid; ! 93: #ifdef COMPAT_43 ! 94: retval[1] = p->p_ucred->cr_uid; ! 95: #endif ! 96: return (0); ! 97: } ! 98: ! 99: /* ARGSUSED */ ! 100: geteuid(p, uap, retval) ! 101: struct proc *p; ! 102: void *uap; ! 103: int *retval; ! 104: { ! 105: ! 106: *retval = p->p_ucred->cr_uid; ! 107: return (0); ! 108: } ! 109: ! 110: /* ARGSUSED */ ! 111: getgid(p, uap, retval) ! 112: struct proc *p; ! 113: void *uap; ! 114: int *retval; ! 115: { ! 116: ! 117: *retval = p->p_cred->p_rgid; ! 118: #ifdef COMPAT_43 ! 119: retval[1] = p->p_ucred->cr_groups[0]; ! 120: #endif ! 121: return (0); ! 122: } ! 123: ! 124: /* ! 125: * Get effective group ID. The "egid" is groups[0], and could be obtained ! 126: * via getgroups. This syscall exists because it is somewhat painful to do ! 127: * correctly in a library function. ! 128: */ ! 129: /* ARGSUSED */ ! 130: getegid(p, uap, retval) ! 131: struct proc *p; ! 132: void *uap; ! 133: int *retval; ! 134: { ! 135: ! 136: *retval = p->p_ucred->cr_groups[0]; ! 137: return (0); ! 138: } ! 139: ! 140: getgroups(p, uap, retval) ! 141: struct proc *p; ! 142: register struct arg { ! 143: u_int gidsetsize; ! 144: int *gidset; /* XXX not yet POSIX */ ! 145: } *uap; ! 146: int *retval; ! 147: { ! 148: register struct pcred *pc = p->p_cred; ! 149: register gid_t *gp; ! 150: register int *lp; ! 151: register u_int ngrp; ! 152: int groups[NGROUPS]; ! 153: int error; ! 154: ! 155: if ((ngrp = uap->gidsetsize) == 0) { ! 156: *retval = pc->pc_ucred->cr_ngroups; ! 157: return (0); ! 158: } ! 159: if (ngrp < pc->pc_ucred->cr_ngroups) ! 160: return (EINVAL); ! 161: ngrp = pc->pc_ucred->cr_ngroups; ! 162: for (gp = pc->pc_ucred->cr_groups, lp = groups; lp < &groups[ngrp]; ) ! 163: *lp++ = *gp++; ! 164: if (error = copyout((caddr_t)groups, (caddr_t)uap->gidset, ! 165: ngrp * sizeof (groups[0]))) ! 166: return (error); ! 167: *retval = ngrp; ! 168: return (0); ! 169: } ! 170: ! 171: /* ARGSUSED */ ! 172: setsid(p, uap, retval) ! 173: register struct proc *p; ! 174: void *uap; ! 175: int *retval; ! 176: { ! 177: ! 178: if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) { ! 179: return (EPERM); ! 180: } else { ! 181: enterpgrp(p, p->p_pid, 1); ! 182: *retval = p->p_pid; ! 183: return (0); ! 184: } ! 185: } ! 186: ! 187: /* ! 188: * set process group (setpgid/old setpgrp) ! 189: * ! 190: * caller does setpgid(targpid, targpgid) ! 191: * ! 192: * pid must be caller or child of caller (ESRCH) ! 193: * if a child ! 194: * pid must be in same session (EPERM) ! 195: * pid can't have done an exec (EACCES) ! 196: * if pgid != pid ! 197: * there must exist some pid in same session having pgid (EPERM) ! 198: * pid must not be session leader (EPERM) ! 199: */ ! 200: /* ARGSUSED */ ! 201: setpgid(curp, uap, retval) ! 202: struct proc *curp; ! 203: register struct args { ! 204: int pid; /* target process id */ ! 205: int pgid; /* target pgrp id */ ! 206: } *uap; ! 207: int *retval; ! 208: { ! 209: register struct proc *targp; /* target process */ ! 210: register struct pgrp *pgrp; /* target pgrp */ ! 211: ! 212: if (uap->pid != 0 && uap->pid != curp->p_pid) { ! 213: if ((targp = pfind(uap->pid)) == 0 || !inferior(targp)) ! 214: return (ESRCH); ! 215: if (targp->p_session != curp->p_session) ! 216: return (EPERM); ! 217: if (targp->p_flag&SEXEC) ! 218: return (EACCES); ! 219: } else ! 220: targp = curp; ! 221: if (SESS_LEADER(targp)) ! 222: return (EPERM); ! 223: if (uap->pgid == 0) ! 224: uap->pgid = targp->p_pid; ! 225: else if (uap->pgid != targp->p_pid) ! 226: if ((pgrp = pgfind(uap->pgid)) == 0 || ! 227: pgrp->pg_session != curp->p_session) ! 228: return (EPERM); ! 229: enterpgrp(targp, uap->pgid, 0); ! 230: return (0); ! 231: } ! 232: ! 233: /* ARGSUSED */ ! 234: setuid(p, uap, retval) ! 235: struct proc *p; ! 236: struct args { ! 237: int uid; ! 238: } *uap; ! 239: int *retval; ! 240: { ! 241: register struct pcred *pc = p->p_cred; ! 242: register uid_t uid; ! 243: int error; ! 244: ! 245: uid = uap->uid; ! 246: if (uid != pc->p_ruid && ! 247: (error = suser(pc->pc_ucred, &p->p_acflag))) ! 248: return (error); ! 249: /* ! 250: * Everything's okay, do it. Copy credentials so other references do ! 251: * not see our changes. ! 252: */ ! 253: pc->pc_ucred = crcopy(pc->pc_ucred); ! 254: pc->pc_ucred->cr_uid = uid; ! 255: pc->p_ruid = uid; ! 256: pc->p_svuid = uid; ! 257: return (0); ! 258: } ! 259: ! 260: /* ARGSUSED */ ! 261: seteuid(p, uap, retval) ! 262: struct proc *p; ! 263: struct args { ! 264: int euid; ! 265: } *uap; ! 266: int *retval; ! 267: { ! 268: register struct pcred *pc = p->p_cred; ! 269: register uid_t euid; ! 270: int error; ! 271: ! 272: euid = uap->euid; ! 273: if (euid != pc->p_ruid && euid != pc->p_svuid && ! 274: (error = suser(pc->pc_ucred, &p->p_acflag))) ! 275: return (error); ! 276: /* ! 277: * Everything's okay, do it. Copy credentials so other references do ! 278: * not see our changes. ! 279: */ ! 280: pc->pc_ucred = crcopy(pc->pc_ucred); ! 281: pc->pc_ucred->cr_uid = euid; ! 282: return (0); ! 283: } ! 284: ! 285: /* ARGSUSED */ ! 286: setgid(p, uap, retval) ! 287: struct proc *p; ! 288: struct args { ! 289: int gid; ! 290: } *uap; ! 291: int *retval; ! 292: { ! 293: register struct pcred *pc = p->p_cred; ! 294: register gid_t gid; ! 295: int error; ! 296: ! 297: gid = uap->gid; ! 298: if (gid != pc->p_rgid && (error = suser(pc->pc_ucred, &p->p_acflag))) ! 299: return (error); ! 300: pc->pc_ucred = crcopy(pc->pc_ucred); ! 301: pc->pc_ucred->cr_groups[0] = gid; ! 302: pc->p_rgid = gid; ! 303: pc->p_svgid = gid; /* ??? */ ! 304: return (0); ! 305: } ! 306: ! 307: /* ARGSUSED */ ! 308: setegid(p, uap, retval) ! 309: struct proc *p; ! 310: struct args { ! 311: int egid; ! 312: } *uap; ! 313: int *retval; ! 314: { ! 315: register struct pcred *pc = p->p_cred; ! 316: register gid_t egid; ! 317: int error; ! 318: ! 319: egid = uap->egid; ! 320: if (egid != pc->p_rgid && egid != pc->p_svgid && ! 321: (error = suser(pc->pc_ucred, &p->p_acflag))) ! 322: return (error); ! 323: pc->pc_ucred = crcopy(pc->pc_ucred); ! 324: pc->pc_ucred->cr_groups[0] = egid; ! 325: return (0); ! 326: } ! 327: ! 328: #ifdef COMPAT_43 ! 329: /* ARGSUSED */ ! 330: osetreuid(p, uap, retval) ! 331: register struct proc *p; ! 332: struct args { ! 333: int ruid; ! 334: int euid; ! 335: } *uap; ! 336: int *retval; ! 337: { ! 338: register struct pcred *pc = p->p_cred; ! 339: register uid_t ruid, euid; ! 340: int error; ! 341: ! 342: if (uap->ruid == -1) ! 343: ruid = pc->p_ruid; ! 344: else ! 345: ruid = uap->ruid; ! 346: /* ! 347: * Allow setting real uid to previous effective, for swapping real and ! 348: * effective. This should be: ! 349: * ! 350: * if (ruid != pc->p_ruid && ! 351: * (error = suser(pc->pc_ucred, &p->p_acflag))) ! 352: */ ! 353: if (ruid != pc->p_ruid && ruid != pc->pc_ucred->cr_uid /* XXX */ && ! 354: (error = suser(pc->pc_ucred, &p->p_acflag))) ! 355: return (error); ! 356: if (uap->euid == -1) ! 357: euid = pc->pc_ucred->cr_uid; ! 358: else ! 359: euid = uap->euid; ! 360: if (euid != pc->pc_ucred->cr_uid && euid != pc->p_ruid && ! 361: euid != pc->p_svuid && (error = suser(pc->pc_ucred, &p->p_acflag))) ! 362: return (error); ! 363: /* ! 364: * Everything's okay, do it. Copy credentials so other references do ! 365: * not see our changes. ! 366: */ ! 367: pc->pc_ucred = crcopy(pc->pc_ucred); ! 368: pc->pc_ucred->cr_uid = euid; ! 369: pc->p_ruid = ruid; ! 370: return (0); ! 371: } ! 372: ! 373: /* ARGSUSED */ ! 374: osetregid(p, uap, retval) ! 375: register struct proc *p; ! 376: struct args { ! 377: int rgid; ! 378: int egid; ! 379: } *uap; ! 380: int *retval; ! 381: { ! 382: register struct pcred *pc = p->p_cred; ! 383: register gid_t rgid, egid; ! 384: int error; ! 385: ! 386: if (uap->rgid == -1) ! 387: rgid = pc->p_rgid; ! 388: else ! 389: rgid = uap->rgid; ! 390: /* ! 391: * Allow setting real gid to previous effective, for swapping real and ! 392: * effective. This didn't really work correctly in 4.[23], but is ! 393: * preserved so old stuff doesn't fail. This should be: ! 394: * ! 395: * if (rgid != pc->p_rgid && ! 396: * (error = suser(pc->pc_ucred, &p->p_acflag))) ! 397: */ ! 398: if (rgid != pc->p_rgid && rgid != pc->pc_ucred->cr_groups[0] /* XXX */ && ! 399: (error = suser(pc->pc_ucred, &p->p_acflag))) ! 400: return (error); ! 401: if (uap->egid == -1) ! 402: egid = pc->pc_ucred->cr_groups[0]; ! 403: else ! 404: egid = uap->egid; ! 405: if (egid != pc->pc_ucred->cr_groups[0] && egid != pc->p_rgid && ! 406: egid != pc->p_svgid && (error = suser(pc->pc_ucred, &p->p_acflag))) ! 407: return (error); ! 408: pc->pc_ucred = crcopy(pc->pc_ucred); ! 409: pc->pc_ucred->cr_groups[0] = egid; ! 410: pc->p_rgid = rgid; ! 411: return (0); ! 412: } ! 413: #endif ! 414: ! 415: /* ARGSUSED */ ! 416: setgroups(p, uap, retval) ! 417: struct proc *p; ! 418: struct args { ! 419: u_int gidsetsize; ! 420: int *gidset; ! 421: } *uap; ! 422: int *retval; ! 423: { ! 424: register struct pcred *pc = p->p_cred; ! 425: register gid_t *gp; ! 426: register u_int ngrp; ! 427: register int *lp; ! 428: int error, groups[NGROUPS]; ! 429: ! 430: if (error = suser(pc->pc_ucred, &p->p_acflag)) ! 431: return (error); ! 432: if ((ngrp = uap->gidsetsize) > NGROUPS) ! 433: return (EINVAL); ! 434: if (error = copyin((caddr_t)uap->gidset, (caddr_t)groups, ! 435: ngrp * sizeof (groups[0]))) ! 436: return (error); ! 437: pc->pc_ucred = crcopy(pc->pc_ucred); ! 438: pc->pc_ucred->cr_ngroups = ngrp; ! 439: /* convert from int's to gid_t's */ ! 440: for (gp = pc->pc_ucred->cr_groups, lp = groups; ngrp--; ) ! 441: *gp++ = *lp++; ! 442: return (0); ! 443: } ! 444: ! 445: /* ! 446: * Check if gid is a member of the group set. ! 447: */ ! 448: groupmember(gid, cred) ! 449: gid_t gid; ! 450: register struct ucred *cred; ! 451: { ! 452: register gid_t *gp; ! 453: gid_t *egp; ! 454: ! 455: egp = &(cred->cr_groups[cred->cr_ngroups]); ! 456: for (gp = cred->cr_groups; gp < egp; gp++) ! 457: if (*gp == gid) ! 458: return (1); ! 459: return (0); ! 460: } ! 461: ! 462: /* ! 463: * Test whether the specified credentials imply "super-user" ! 464: * privilege; if so, and we have accounting info, set the flag ! 465: * indicating use of super-powers. ! 466: * Returns 0 or error. ! 467: */ ! 468: suser(cred, acflag) ! 469: struct ucred *cred; ! 470: short *acflag; ! 471: { ! 472: if (cred->cr_uid == 0) { ! 473: if (acflag) ! 474: *acflag |= ASU; ! 475: return (0); ! 476: } ! 477: return (EPERM); ! 478: } ! 479: ! 480: /* ! 481: * Allocate a zeroed cred structure. ! 482: */ ! 483: struct ucred * ! 484: crget() ! 485: { ! 486: register struct ucred *cr; ! 487: ! 488: MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK); ! 489: bzero((caddr_t)cr, sizeof(*cr)); ! 490: cr->cr_ref = 1; ! 491: return (cr); ! 492: } ! 493: ! 494: /* ! 495: * Free a cred structure. ! 496: * Throws away space when ref count gets to 0. ! 497: */ ! 498: crfree(cr) ! 499: struct ucred *cr; ! 500: { ! 501: int s = splimp(); /* ??? */ ! 502: ! 503: if (--cr->cr_ref != 0) { ! 504: (void) splx(s); ! 505: return; ! 506: } ! 507: FREE((caddr_t)cr, M_CRED); ! 508: (void) splx(s); ! 509: } ! 510: ! 511: /* ! 512: * Copy cred structure to a new one and free the old one. ! 513: */ ! 514: struct ucred * ! 515: crcopy(cr) ! 516: struct ucred *cr; ! 517: { ! 518: struct ucred *newcr; ! 519: ! 520: if (cr->cr_ref == 1) ! 521: return (cr); ! 522: newcr = crget(); ! 523: *newcr = *cr; ! 524: crfree(cr); ! 525: newcr->cr_ref = 1; ! 526: return (newcr); ! 527: } ! 528: ! 529: /* ! 530: * Dup cred struct to a new held one. ! 531: */ ! 532: struct ucred * ! 533: crdup(cr) ! 534: struct ucred *cr; ! 535: { ! 536: struct ucred *newcr; ! 537: ! 538: newcr = crget(); ! 539: *newcr = *cr; ! 540: newcr->cr_ref = 1; ! 541: return (newcr); ! 542: } ! 543: ! 544: /* ! 545: * Get login name, if available. ! 546: */ ! 547: /* ARGSUSED */ ! 548: getlogin(p, uap, retval) ! 549: struct proc *p; ! 550: struct args { ! 551: char *namebuf; ! 552: u_int namelen; ! 553: } *uap; ! 554: int *retval; ! 555: { ! 556: ! 557: if (uap->namelen > sizeof (p->p_pgrp->pg_session->s_login)) ! 558: uap->namelen = sizeof (p->p_pgrp->pg_session->s_login); ! 559: return (copyout((caddr_t) p->p_pgrp->pg_session->s_login, ! 560: (caddr_t) uap->namebuf, uap->namelen)); ! 561: } ! 562: ! 563: /* ! 564: * Set login name. ! 565: */ ! 566: /* ARGSUSED */ ! 567: setlogin(p, uap, retval) ! 568: struct proc *p; ! 569: struct args { ! 570: char *namebuf; ! 571: } *uap; ! 572: int *retval; ! 573: { ! 574: int error; ! 575: ! 576: if (error = suser(p->p_ucred, &p->p_acflag)) ! 577: return (error); ! 578: error = copyinstr((caddr_t) uap->namebuf, ! 579: (caddr_t) p->p_pgrp->pg_session->s_login, ! 580: sizeof (p->p_pgrp->pg_session->s_login) - 1, (u_int *)0); ! 581: if (error == ENAMETOOLONG) ! 582: error = EINVAL; ! 583: return (error); ! 584: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.