📄 signal.c
字号:
18133 if (rmp->mp_effuid != SUPER_USER) return EPERM;
18134
18135 switch (reboot_flag) {
18136 case RBT_HALT:
18137 case RBT_REBOOT:
18138 case RBT_PANIC:
18139 case RBT_RESET:
18140 break;
18141 case RBT_MONITOR:
18142 if (reboot_size > sizeof(monitor_code)) return EINVAL;
18143 memset(monitor_code, 0, sizeof(monitor_code));
18144 if (sys_copy(who, D, (phys_bytes) reboot_code,
18145 MM_PROC_NR, D, (phys_bytes) monitor_code,
18146 (phys_bytes) reboot_size) != OK) return EFAULT;
18147 if (monitor_code[sizeof(monitor_code)-1] != 0) return EINVAL;
18148 break;
18149 default:
18150 return EINVAL;
18151 }
18152
18153 /* Kill all processes except init. */
18154 check_sig(-1, SIGKILL);
18155
18156 tell_fs(EXIT, INIT_PROC_NR, 0, 0); /* cleanup init */
18157
18158 tell_fs(SYNC,0,0,0);
18159
18160 sys_abort(reboot_flag, monitor_code);
18161 /* NOTREACHED */
18162 }
18165 /*===========================================================================*
18166 * sig_proc *
18167 *===========================================================================*/
18168 PUBLIC void sig_proc(rmp, signo)
18169 register struct mproc *rmp; /* pointer to the process to be signaled */
18170 int signo; /* signal to send to process (1 to _NSIG) */
18171 {
18172 /* Send a signal to a process. Check to see if the signal is to be caught,
18173 * ignored, or blocked. If the signal is to be caught, coordinate with
18174 * KERNEL to push a sigcontext structure and a sigframe structure onto
18175 * the catcher's stack. Also, KERNEL will reset the program counter and
18176 * stack pointer, so that when the process next runs, it will be executing
18177 * the signal handler. When the signal handler returns, sigreturn(2)
18178 * will be called. Then KERNEL will restore the signal context from the
18179 * sigcontext structure.
18180 *
18181 * If there is insufficient stack space, kill the process.
18182 */
18183
18184 vir_bytes new_sp;
18185 int slot;
18186 int sigflags;
18187 struct sigmsg sm;
18188
18189 slot = (int) (rmp - mproc);
18190 if (!(rmp->mp_flags & IN_USE)) {
18191 printf("MM: signal %d sent to dead process %d\n", signo, slot);
18192 panic("", NO_NUM);
18193 }
18194 if (rmp->mp_flags & HANGING) {
18195 printf("MM: signal %d sent to HANGING process %d\n", signo, slot);
18196 panic("", NO_NUM);
18197 }
18198 if (rmp->mp_flags & TRACED && signo != SIGKILL) {
18199 /* A traced process has special handling. */
18200 unpause(slot);
18201 stop_proc(rmp, signo); /* a signal causes it to stop */
18202 return;
18203 }
18204 /* Some signals are ignored by default. */
18205 if (sigismember(&rmp->mp_ignore, signo)) return;
18206
18207 if (sigismember(&rmp->mp_sigmask, signo)) {
18208 /* Signal should be blocked. */
18209 sigaddset(&rmp->mp_sigpending, signo);
18210 return;
18211 }
18212 sigflags = rmp->mp_sigact[signo].sa_flags;
18213 if (sigismember(&rmp->mp_catch, signo)) {
18214 if (rmp->mp_flags & SIGSUSPENDED)
18215 sm.sm_mask = rmp->mp_sigmask2;
18216 else
18217 sm.sm_mask = rmp->mp_sigmask;
18218 sm.sm_signo = signo;
18219 sm.sm_sighandler = (vir_bytes) rmp->mp_sigact[signo].sa_handler;
18220 sm.sm_sigreturn = rmp->mp_sigreturn;
18221 sys_getsp(slot, &new_sp);
18222 sm.sm_stkptr = new_sp;
18223
18224 /* Make room for the sigcontext and sigframe struct. */
18225 new_sp -= sizeof(struct sigcontext)
18226 + 3 * sizeof(char *) + 2 * sizeof(int);
18227
18228 if (adjust(rmp, rmp->mp_seg[D].mem_len, new_sp) != OK)
18229 goto doterminate;
18230
18231 rmp->mp_sigmask |= rmp->mp_sigact[signo].sa_mask;
18232 if (sigflags & SA_NODEFER)
18233 sigdelset(&rmp->mp_sigmask, signo);
18234 else
18235 sigaddset(&rmp->mp_sigmask, signo);
18236
18237 if (sigflags & SA_RESETHAND) {
18238 sigdelset(&rmp->mp_catch, signo);
18239 rmp->mp_sigact[signo].sa_handler = SIG_DFL;
18240 }
18241
18242 sys_sendsig(slot, &sm);
18243 sigdelset(&rmp->mp_sigpending, signo);
18244 /* If process is hanging on PAUSE, WAIT, SIGSUSPEND, tty, pipe, etc.,
18245 * release it.
18246 */
18247 unpause(slot);
18248 return;
18249 }
18250 doterminate:
18251 /* Signal should not or cannot be caught. Terminate the process. */
18252 rmp->mp_sigstatus = (char) signo;
18253 if (sigismember(&core_sset, signo)) {
18254 /* Switch to the user's FS environment and dump core. */
18255 tell_fs(CHDIR, slot, FALSE, 0);
18256 dump_core(rmp);
18257 }
18258 mm_exit(rmp, 0); /* terminate process */
18259 }
18262 /*===========================================================================*
18263 * check_sig *
18264 *===========================================================================*/
18265 PUBLIC int check_sig(proc_id, signo)
18266 pid_t proc_id; /* pid of proc to sig, or 0 or -1, or -pgrp */
18267 int signo; /* signal to send to process (0 to _NSIG) */
18268 {
18269 /* Check to see if it is possible to send a signal. The signal may have to be
18270 * sent to a group of processes. This routine is invoked by the KILL system
18271 * call, and also when the kernel catches a DEL or other signal.
18272 */
18273
18274 register struct mproc *rmp;
18275 int count; /* count # of signals sent */
18276 int error_code;
18277
18278 if (signo < 0 || signo > _NSIG) return(EINVAL);
18279
18280 /* Return EINVAL for attempts to send SIGKILL to INIT alone. */
18281 if (proc_id == INIT_PID && signo == SIGKILL) return(EINVAL);
18282
18283 /* Search the proc table for processes to signal. (See forkexit.c about
18284 * pid magic.)
18285 */
18286 count = 0;
18287 error_code = ESRCH;
18288 for (rmp = &mproc[INIT_PROC_NR]; rmp < &mproc[NR_PROCS]; rmp++) {
18289 if ( (rmp->mp_flags & IN_USE) == 0) continue;
18290 if (rmp->mp_flags & HANGING && signo != 0) continue;
18291
18292 /* Check for selection. */
18293 if (proc_id > 0 && proc_id != rmp->mp_pid) continue;
18294 if (proc_id == 0 && mp->mp_procgrp != rmp->mp_procgrp) continue;
18295 if (proc_id == -1 && rmp->mp_pid == INIT_PID) continue;
18296 if (proc_id < -1 && rmp->mp_procgrp != -proc_id) continue;
18297
18298 /* Check for permission. */
18299 if (mp->mp_effuid != SUPER_USER
18300 && mp->mp_realuid != rmp->mp_realuid
18301 && mp->mp_effuid != rmp->mp_realuid
18302 && mp->mp_realuid != rmp->mp_effuid
18303 && mp->mp_effuid != rmp->mp_effuid) {
18304 error_code = EPERM;
18305 continue;
18306 }
18307
18308 count++;
18309 if (signo == 0) continue;
18310
18311 /* 'sig_proc' will handle the disposition of the signal. The
18312 * signal may be caught, blocked, ignored, or cause process
18313 * termination, possibly with core dump.
18314 */
18315 sig_proc(rmp, signo);
18316
18317 if (proc_id > 0) break; /* only one process being signaled */
18318 }
18319
18320 /* If the calling process has killed itself, don't reply. */
18321 if ((mp->mp_flags & IN_USE) == 0 || (mp->mp_flags & HANGING))
18322 dont_reply = TRUE;
18323 return(count > 0 ? OK : error_code);
18324 }
18327 /*===========================================================================*
18328 * check_pending *
18329 *===========================================================================*/
18330 PRIVATE void check_pending()
18331 {
18332 /* Check to see if any pending signals have been unblocked. The
18333 * first such signal found is delivered.
18334 *
18335 * If multiple pending unmasked signals are found, they will be
18336 * delivered sequentially.
18337 *
18338 * There are several places in this file where the signal mask is
18339 * changed. At each such place, check_pending() should be called to
18340 * check for newly unblocked signals.
18341 */
18342
18343 int i;
18344
18345 for (i = 1; i < _NSIG; i++) {
18346 if (sigismember(&mp->mp_sigpending, i) &&
18347 !sigismember(&mp->mp_sigmask, i)) {
18348 sigdelset(&mp->mp_sigpending, i);
18349 sig_proc(mp, i);
18350 break;
18351 }
18352 }
18353 }
18356 /*===========================================================================*
18357 * unpause *
18358 *===========================================================================*/
18359 PRIVATE void unpause(pro)
18360 int pro; /* which process number */
18361 {
18362 /* A signal is to be sent to a process. If that process is hanging on a
18363 * system call, the system call must be terminated with EINTR. Possible
18364 * calls are PAUSE, WAIT, READ and WRITE, the latter two for pipes and ttys.
18365 * First check if the process is hanging on an MM call. If not, tell FS,
18366 * so it can check for READs and WRITEs from pipes, ttys and the like.
18367 */
18368
18369 register struct mproc *rmp;
18370
18371 rmp = &mproc[pro];
18372
18373 /* Check to see if process is hanging on a PAUSE call. */
18374 if ( (rmp->mp_flags & PAUSED) && (rmp->mp_flags & HANGING) == 0) {
18375 rmp->mp_flags &= ~PAUSED;
18376 reply(pro, EINTR, 0, NIL_PTR);
18377 return;
18378 }
18379
18380 /* Check to see if process is hanging on a WAIT call. */
18381 if ( (rmp->mp_flags & WAITING) && (rmp->mp_flags & HANGING) == 0) {
18382 rmp->mp_flags &= ~WAITING;
18383 reply(pro, EINTR, 0, NIL_PTR);
18384 return;
18385 }
18386
18387 /* Check to see if process is hanging on a SIGSUSPEND call. */
18388 if ((rmp->mp_flags & SIGSUSPENDED) && (rmp->mp_flags & HANGING) == 0) {
18389 rmp->mp_flags &= ~SIGSUSPENDED;
18390 reply(pro, EINTR, 0, NIL_PTR);
18391 return;
18392 }
18393
18394 /* Process is not hanging on an MM call. Ask FS to take a look. */
18395 tell_fs(UNPAUSE, pro, 0, 0);
18396 }
18399 /*===========================================================================*
18400 * dump_core *
18401 *===========================================================================*/
18402 PRIVATE void dump_core(rmp)
18403 register struct mproc *rmp; /* whose core is to be dumped */
18404 {
18405 /* Make a core dump on the file "core", if possible. */
18406
18407 int fd, fake_fd, nr_written, seg, slot;
18408 char *buf;
18409 vir_bytes current_sp;
18410 phys_bytes left; /* careful; 64K might overflow vir_bytes */
18411 unsigned nr_to_write; /* unsigned for arg to write() but < INT_MAX */
18412 long trace_data, trace_off;
18413
18414 slot = (int) (rmp - mproc);
18415
18416 /* Can core file be written? We are operating in the user's FS environment,
18417 * so no special permission checks are needed.
18418 */
18419 if (rmp->mp_realuid != rmp->mp_effuid) return;
18420 if ( (fd = creat(core_name, CORE_MODE)) < 0) return;
18421 rmp->mp_sigstatus |= DUMPED;
18422
18423 /* Make sure the stack segment is up to date.
18424 * We don't want adjust() to fail unless current_sp is preposterous,
18425 * but it might fail due to safety checking. Also, we don't really want
18426 * the adjust() for sending a signal to fail due to safety checking.
18427 * Maybe make SAFETY_BYTES a parameter.
18428 */
18429 sys_getsp(slot, ¤t_sp);
18430 adjust(rmp, rmp->mp_seg[D].mem_len, current_sp);
18431
18432 /* Write the memory map of all segments to begin the core file. */
18433 if (write(fd, (char *) rmp->mp_seg, (unsigned) sizeof rmp->mp_seg)
18434 != (unsigned) sizeof rmp->mp_seg) {
18435 close(fd);
18436 return;
18437 }
18438
18439 /* Write out the whole kernel process table entry to get the regs. */
18440 trace_off = 0;
18441 while (sys_trace(3, slot, trace_off, &trace_data) == OK) {
18442 if (write(fd, (char *) &trace_data, (unsigned) sizeof (long))
18443 != (unsigned) sizeof (long)) {
18444 close(fd);
18445 return;
18446 }
18447 trace_off += sizeof (long);
18448 }
18449
18450 /* Loop through segments and write the segments themselves out. */
18451 for (seg = 0; seg < NR_SEGS; seg++) {
18452 buf = (char *) ((vir_bytes) rmp->mp_seg[seg].mem_vir << CLICK_SHIFT);
18453 left = (phys_bytes) rmp->mp_seg[seg].mem_len << CLICK_SHIFT;
18454 fake_fd = (slot << 8) | (seg << 6) | fd;
18455
18456 /* Loop through a segment, dumping it. */
18457 while (left != 0) {
18458 nr_to_write = (unsigned) MIN(left, DUMP_SIZE);
18459 if ( (nr_written = write(fake_fd, buf, nr_to_write)) < 0) {
18460 close(fd);
18461 return;
18462 }
18463 buf += nr_written;
18464 left -= nr_written;
18465 }
18466 }
18467 close(fd);
18468 }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -