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