1: /* 2: * SCCS id @(#)signojcl.c 2.1 (Berkeley) 9/4/83 3: */ 4: 5: #include "param.h" 6: #include <sys/systm.h> 7: #include <sys/dir.h> 8: #include <sys/user.h> 9: #include <sys/proc.h> 10: #include <sys/inode.h> 11: #include <sys/reg.h> 12: #include <sys/text.h> 13: #include <sys/seg.h> 14: #ifdef UCB_METER 15: #include <sys/vm.h> 16: #endif 17: 18: 19: /* 20: * Priority for tracing 21: */ 22: #define IPCPRI PZERO 23: 24: /* 25: * Tracing variables. 26: * Used to pass trace command from 27: * parent to child being traced. 28: * This data base cannot be 29: * shared and is locked 30: * per user. 31: */ 32: struct 33: { 34: int ip_lock; 35: int ip_req; 36: int *ip_addr; 37: int ip_data; 38: } ipc; 39: 40: /* 41: * Send the specified signal to 42: * all processes with 'pgrp' as 43: * process group. 44: * Called by tty*.c for quits and 45: * interrupts. 46: */ 47: gsignal(pgrp, sig) 48: register pgrp; 49: { 50: register struct proc *p; 51: 52: if(pgrp == 0) 53: return; 54: for(p = &proc[0]; p <= maxproc; p++) 55: if(p->p_pgrp == pgrp) 56: psignal(p, sig); 57: } 58: 59: /* 60: * Send the specified signal to 61: * the specified process. 62: */ 63: psignal(p, sig) 64: register struct proc *p; 65: register sig; 66: { 67: 68: if((unsigned)sig >= NSIG) 69: return; 70: if(sig) 71: p->p_sig |= 1<<(sig-1); 72: if(p->p_pri > PUSER) 73: p->p_pri = PUSER; 74: if(p->p_stat == SSLEEP && p->p_pri > PZERO) 75: setrun(p); 76: } 77: 78: /* 79: * Returns true if the current 80: * process has a signal to process. 81: * This is asked at least once 82: * each time a process enters the 83: * system. 84: * A signal does not do anything 85: * directly to a process; it sets 86: * a flag that asks the process to 87: * do something to itself. 88: */ 89: issig() 90: { 91: register n; 92: register struct proc *p; 93: 94: p = u.u_procp; 95: while(p->p_sig) { 96: n = fsig(p); 97: if(((int)u.u_signal[n]&1) == 0 || (p->p_flag&STRC)) 98: return(n); 99: p->p_sig &= ~(1<<(n-1)); 100: } 101: return(0); 102: } 103: 104: /* 105: * Enter the tracing STOP state. 106: * In this state, the parent is 107: * informed and the process is able to 108: * receive commands from the parent. 109: */ 110: stop() 111: { 112: register struct proc *pp, *cp; 113: 114: loop: 115: cp = u.u_procp; 116: if(cp->p_ppid != 1) 117: for (pp = &proc[0]; pp <= maxproc; pp++) 118: if (pp->p_pid == cp->p_ppid) { 119: wakeup((caddr_t)pp); 120: cp->p_stat = SSTOP; 121: swtch(); 122: if ((cp->p_flag&STRC)==0 || procxmt()) 123: return; 124: goto loop; 125: } 126: exit(fsig(u.u_procp)); 127: } 128: 129: /* 130: * Perform the action specified by 131: * the current signal. 132: * The usual sequence is: 133: * if(issig()) 134: * psig(); 135: */ 136: psig() 137: { 138: register n, p; 139: register struct proc *rp; 140: 141: rp = u.u_procp; 142: #ifndef NONFP 143: if (u.u_fpsaved==0) { 144: savfp(&u.u_fps); 145: u.u_fpsaved = 1; 146: } 147: if (rp->p_flag&STRC) 148: stop(); 149: #else 150: /* allow normal action on SIGILL even if traced */ 151: n = fsig(rp); 152: if ((rp->p_flag&STRC) && (n!=SIGILL || u.u_signal[SIGILL]==0)) 153: stop(); 154: #endif 155: while(n = fsig(rp)) { 156: rp->p_sig &= ~(1<<(n-1)); 157: if((p=u.u_signal[n]) != 0) { 158: u.u_error = 0; 159: if (u.u_signal[n] == 1) 160: continue; 161: if(n != SIGILL && n != SIGTRAP) 162: u.u_signal[n] = 0; 163: sendsig((caddr_t)p); 164: } else { 165: switch(n) { 166: 167: case SIGQUIT: 168: case SIGILL: 169: case SIGTRAP: 170: case SIGIOT: 171: case SIGEMT: 172: case SIGFPE: 173: case SIGBUS: 174: case SIGSEGV: 175: case SIGSYS: 176: if(core()) 177: n += 0200; 178: } 179: exit(n); 180: } 181: } 182: } 183: 184: /* 185: * This table defines the order in which signals 186: * will be reflected to the user process. Signals 187: * later in the list will be stacked after (processed 188: * before) signals earlier in the list. The value 189: * contained in the list is the signal number. 190: */ 191: 192: char siglist[] = { 193: SIGKILL, /* kill */ 194: SIGTERM, /* terminate */ 195: SIGILL, /* illegal instruction */ 196: SIGTRAP, /* trace trap */ 197: SIGIOT, /* iot */ 198: SIGEMT, /* emt */ 199: SIGBUS, /* bus error */ 200: SIGSEGV, /* segmentation error */ 201: SIGSYS, /* invalid system call (unused) */ 202: SIGQUIT, /* quit */ 203: SIGINT, /* interrupt */ 204: SIGHUP, /* hangup */ 205: SIGPIPE, /* broken pipe */ 206: SIGALRM, /* alarm clock */ 207: SIGFPE, /* floating exception */ 208: 16, /* unassigned */ 209: 0, /* end of list */ 210: }; 211: 212: /* 213: * find the highest-priority signal in 214: * bit-position representation in p_sig. 215: */ 216: fsig(p) 217: struct proc *p; 218: { 219: register char *cp; 220: register psig; 221: 222: psig = p->p_sig; 223: for(cp=siglist; *cp; cp++) 224: if(psig & (1 << (*cp-1))) 225: return(*cp); 226: return(0); 227: } 228: 229: /* 230: * Create a core image on the file "core" 231: * If you are looking for protection glitches, 232: * there are probably a wealth of them here 233: * when this occurs to a suid command. 234: * 235: * It writes USIZE block of the 236: * user.h area followed by the entire 237: * data+stack segments. 238: */ 239: core() 240: { 241: register struct inode *ip; 242: register unsigned s; 243: extern schar(); 244: 245: u.u_error = 0; 246: 247: /* 248: * Disallow dump if setuid/setgid. 249: */ 250: if (u.u_gid != u.u_rgid || u.u_uid != u.u_ruid) 251: return(0); 252: 253: u.u_dirp = "core"; 254: #ifndef UCB_SYMLINKS 255: ip = namei(schar, CREATE); 256: #else 257: ip = namei(schar, CREATE, 1); 258: #endif 259: if(ip == NULL) { 260: if(u.u_error) 261: return(0); 262: ip = maknode(0666); 263: if (ip == NULL) 264: return(0); 265: } 266: /* 267: * allow dump only if permissions allow, "core" is 268: * regular file and has exactly one link 269: */ 270: if (!access(ip, IWRITE) && 271: (ip->i_mode&IFMT) == IFREG && 272: ip->i_nlink == 1) { 273: itrunc(ip); 274: u.u_offset = 0; 275: u.u_base = (caddr_t)&u; 276: u.u_count = ctob(USIZE); 277: u.u_segflg = 1; 278: writei(ip); 279: #ifdef VIRUS_VFORK 280: s = u.u_dsize; 281: estabur((unsigned)0, s, u.u_ssize, 0, RO); 282: u.u_base = 0; 283: u.u_count = ctob(s); 284: u.u_segflg = 0; 285: writei(ip); 286: s = u.u_ssize; 287: u.u_base = -(ctob(s)); 288: u.u_count = ctob(s); 289: writei(ip); 290: #else 291: s = u.u_procp->p_size - USIZE; 292: estabur((unsigned)0, s, (unsigned)0, 0, RO); 293: u.u_base = 0; 294: u.u_count = ctob(s); 295: u.u_segflg = 0; 296: writei(ip); 297: #endif 298: } 299: iput(ip); 300: return(u.u_error==0); 301: } 302: 303: /* 304: * grow the stack to include the SP 305: * true return if successful. 306: */ 307: 308: grow(sp) 309: unsigned sp; 310: { 311: register si; 312: #ifndef VIRUS_VFORK 313: register i; 314: #endif 315: register struct proc *p; 316: register a; 317: 318: if(sp >= -ctob(u.u_ssize)) 319: return(0); 320: si = (-sp)/ctob(1) - u.u_ssize + SINCR; 321: /* 322: * Round the increment back to a segment boundary if necessary. 323: */ 324: if (ctos(si + u.u_ssize) > ctos(((-sp)+ctob(1)-1) / ctob(1))) 325: si = stoc(ctos(((-sp)+ctob(1)-1) / ctob(1))) - u.u_ssize; 326: if(si <= 0) 327: return(0); 328: if(estabur(u.u_tsize, u.u_dsize, u.u_ssize+si, u.u_sep, RO)) 329: return(0); 330: p = u.u_procp; 331: #ifdef VIRUS_VFORK 332: /* 333: * expand will put the stack in the right place; 334: * no copy required here. 335: */ 336: expand(u.u_ssize+si,S_STACK); 337: u.u_ssize += si; 338: clear(u.u_procp->p_saddr, si); 339: 340: #else VIRUS_VFORK 341: expand(p->p_size+si); 342: a = u.u_procp->p_addr + USIZE + u.u_dsize; 343: i = u.u_ssize; 344: while (i >= si) { 345: i -= si; 346: copy(a+i, a+i+si, si); 347: } 348: copy(a, a+si, i); 349: clear(a, si); 350: u.u_ssize += si; 351: #endif VIRUS_VFORK 352: return(1); 353: } 354: 355: /* 356: * sys-trace system call. 357: */ 358: ptrace() 359: { 360: register struct proc *p; 361: register struct a { 362: int data; 363: int pid; 364: int *addr; 365: int req; 366: } *uap; 367: 368: uap = (struct a *)u.u_ap; 369: if (uap->req <= 0) { 370: u.u_procp->p_flag |= STRC; 371: return; 372: } 373: for (p = proc; p <= maxproc; p++) 374: if (p->p_stat == SSTOP && p->p_pid == uap->pid 375: && p->p_ppid == u.u_procp->p_pid) { 376: while (ipc.ip_lock) 377: sleep((caddr_t)&ipc, IPCPRI); 378: ipc.ip_lock = p->p_pid; 379: ipc.ip_data = uap->data; 380: ipc.ip_addr = uap->addr; 381: ipc.ip_req = uap->req; 382: p->p_flag &= ~SWTED; 383: setrun(p); 384: while (ipc.ip_req > 0) 385: sleep((caddr_t)&ipc, IPCPRI); 386: u.u_r.r_val1 = ipc.ip_data; 387: if (ipc.ip_req < 0) 388: u.u_error = EIO; 389: ipc.ip_lock = 0; 390: wakeup((caddr_t)&ipc); 391: return; 392: } 393: 394: u.u_error = ESRCH; 395: } 396: 397: /* 398: * Code that the child process 399: * executes to implement the command 400: * of the parent process in tracing. 401: */ 402: procxmt() 403: { 404: register int i; 405: register *p; 406: register struct text *xp; 407: 408: if (ipc.ip_lock != u.u_procp->p_pid) 409: return(0); 410: #ifdef UCB_METER 411: u.u_procp->p_slptime = 0; 412: #endif 413: i = ipc.ip_req; 414: ipc.ip_req = 0; 415: wakeup((caddr_t)&ipc); 416: switch (i) { 417: 418: /* read user I */ 419: case 1: 420: #ifndef NONSEPARATE /* I and D are the same if nonsep */ 421: if (fuibyte((caddr_t)ipc.ip_addr) == -1) 422: goto error; 423: ipc.ip_data = fuiword((caddr_t)ipc.ip_addr); 424: break; 425: 426: #endif 427: /* read user D */ 428: case 2: 429: if (fubyte((caddr_t)ipc.ip_addr) == -1) 430: goto error; 431: ipc.ip_data = fuword((caddr_t)ipc.ip_addr); 432: break; 433: 434: /* read u */ 435: case 3: 436: i = (int)ipc.ip_addr; 437: if (i<0 || i >= ctob(USIZE)) 438: goto error; 439: ipc.ip_data = ((physadr)&u)->r[i>>1]; 440: break; 441: 442: /* write user I */ 443: /* Must set up to allow writing */ 444: case 4: 445: /* 446: * If text, must assure exclusive use 447: */ 448: if (xp = u.u_procp->p_textp) { 449: if (xp->x_count!=1 || xp->x_iptr->i_mode&ISVTX) 450: goto error; 451: xp->x_iptr->i_flag &= ~ITEXT; 452: } 453: estabur(u.u_tsize, u.u_dsize, u.u_ssize, u.u_sep, RW); 454: i = suiword((caddr_t)ipc.ip_addr, 0); 455: suiword((caddr_t)ipc.ip_addr, ipc.ip_data); 456: estabur(u.u_tsize, u.u_dsize, u.u_ssize, u.u_sep, RO); 457: if (i<0) 458: goto error; 459: if (xp) 460: xp->x_flag |= XWRIT; 461: break; 462: 463: /* write user D */ 464: case 5: 465: if (suword((caddr_t)ipc.ip_addr, 0) < 0) 466: goto error; 467: suword((caddr_t)ipc.ip_addr, ipc.ip_data); 468: break; 469: 470: /* write u */ 471: case 6: 472: i = (int)ipc.ip_addr; 473: p = (int *)&((physadr)&u)->r[i>>1]; 474: #ifndef NONFP 475: if (p >= (int *)&u.u_fps && p < (int *)&u.u_fps.u_fpregs[6]) 476: goto ok; 477: #endif 478: for (i=0; i<8; i++) 479: if (p == &u.u_ar0[regloc[i]]) 480: goto ok; 481: if (p == &u.u_ar0[RPS]) { 482: ipc.ip_data |= PS_CURMOD | PS_PRVMOD; /* user space */ 483: ipc.ip_data &= ~PS_USERCLR; /* priority 0 */ 484: goto ok; 485: } 486: #ifdef MENLO_OVLY 487: if ((p == &u.u_ovdata.uo_curov) && ((ipc.ip_data >= 0) && 488: (ipc.ip_data <= NOVL) && u.u_ovdata.uo_ovbase)) { 489: *p = ipc.ip_data; 490: choverlay(RO); 491: break; 492: } 493: #endif 494: goto error; 495: 496: ok: 497: *p = ipc.ip_data; 498: break; 499: 500: /* set signal and continue */ 501: /* one version causes a trace-trap */ 502: case 9: 503: u.u_ar0[RPS] |= PS_T; 504: /* FALL THROUGH TO ... */ 505: case 7: 506: if ((int)ipc.ip_addr != 1) 507: u.u_ar0[PC] = (int)ipc.ip_addr; 508: u.u_procp->p_sig = 0; 509: if (ipc.ip_data) 510: psignal(u.u_procp, ipc.ip_data); 511: return(1); 512: 513: /* force exit */ 514: case 8: 515: exit(fsig(u.u_procp)); 516: /*NOTREACHED*/ 517: 518: default: 519: error: 520: ipc.ip_req = -1; 521: } 522: return(0); 523: }