/* kern_sig.c 5.10 82/10/21 */
/* KILL CODE SHOULDNT KNOW ABOUT PROCESS INTERNALS !?! */
uap
= (struct a
*)u
.u_ap
;
* A negative signal means send to process group.
uap
->signo
= -uap
->signo
;
if (uap
->signo
== 0 || uap
->signo
> NSIG
) {
if (p
== 0 || u
.u_uid
&& u
.u_uid
!= p
->p_uid
) {
if (a
==-1 && u
.u_uid
==0) {
sig
= -1; /* like sending to pgrp */
* Zero process id means send to my process group.
for(p
= proc
; p
< procNPROC
; p
++) {
} else if (p
->p_pgrp
!=a
&& priv
==0 || p
->p_ppid
==0 ||
(p
->p_flag
&SSYS
) || (priv
&& p
==u
.u_procp
))
if (u
.u_uid
!= 0 && u
.u_uid
!= p
->p_uid
&&
(uap
->signo
!= SIGCONT
|| !inferior(p
)))
register struct proc
*p
= u
.u_procp
;
uap
= (struct a
*)u
.u_ap
;
a
= uap
->signo
& SIGNUMMASK
;
if (a
<=0 || a
>=NSIG
|| a
==SIGKILL
|| a
==SIGSTOP
||
a
==SIGCONT
&& (f
== SIG_IGN
|| f
== SIG_HOLD
)) {
if ((uap
->signo
&~ SIGNUMMASK
) || (f
!= SIG_DFL
&& f
!= SIG_IGN
&&
u
.u_procp
->p_flag
|= SNUSIG
;
* Don't clobber registers if we are to simulate
if ((uap
->signo
&SIGDORTI
) == 0)
u
.u_r
.r_val1
= (int)u
.u_signal
[a
];
* Change setting atomically.
if (u
.u_signal
[a
] == SIG_IGN
)
p
->p_sig
&= ~sigmask
; /* never to be seen again */
if (f
!= SIG_DFL
&& f
!= SIG_IGN
&& f
!= SIG_HOLD
)
if (uap
->signo
& SIGDOPAUSE
) {
* Simulate a PDP11 style wait instrution which
* atomically lowers priority, enables interrupts
if (uap
->signo
& SIGDORTI
)
* Send the specified signal to
* all processes with 'pgrp' as
* Called by tty.c for quits and
for(p
= proc
; p
< procNPROC
; p
++)
* Send the specified signal to
register int (*action
)();
if ((unsigned)sig
>= NSIG
)
sigmask
= (1L << (sig
-1));
* If proc is traced, always give parent a chance.
* Otherwise get the signal action from the bits in the proc table.
s
= (p
->p_siga1
&sigmask
) != 0;
s
|= (p
->p_siga0
&sigmask
) != 0;
* If the signal is ignored, we forget about it immediately.
#define mask(sig) (1<<(sig-1))
#define stops (mask(SIGSTOP)|mask(SIGTSTP)|mask(SIGTTIN)|mask(SIGTTOU))
if ((p
->p_flag
&STRC
) != 0 || action
!= SIG_DFL
)
p
->p_sig
&= ~mask(SIGCONT
);
* Defer further processing for signals which are held.
* If process is sleeping at negative priority
* we can't interrupt the sleep... the signal will
* be noticed when the process returns through
* Process is sleeping and traced... make it runnable
* so it can discover the signal in issig() and stop
* These are the signals which by default
* Don't clog system with children of init
* stopped from the keyboard.
if (sig
!= SIGSTOP
&& p
->p_pptr
== &proc
[1]) {
* If a child in vfork(), stopping could
* These signals are special in that they
* don't get propogated... if the process
* isn't interested, forget it.
p
->p_sig
&= ~sigmask
; /* take it away */
* All other signals cause the process to run
* If traced process is already stopped,
* then no further action is necessary.
* Kill signal always sets processes running.
* If the process catches SIGCONT, let it handle
* the signal itself. If it isn't waiting on
* an event, then it goes back to run state.
* Otherwise, process goes back to sleep state.
if (action
!= SIG_DFL
|| p
->p_wchan
== 0)
* Already stopped, don't need to stop again.
* (If we did the shell could get confused.)
p
->p_sig
&= ~sigmask
; /* take it away */
* If process is sleeping interruptibly, then
* unstick it so that when it is continued
* it can look at the signal.
* But don't setrun the process as its not to
* be unstopped by the signal alone.
if (p
->p_wchan
&& p
->p_pri
> PZERO
)
* SRUN, SIDL, SZOMB do nothing with the signal,
* other than kicking ourselves if we are running.
* It will either never be noticed, or noticed very soon.
if (p
== u
.u_procp
&& !noproc
)
* Raise priority to at least PUSER.
if ((p
!= u
.u_procp
|| noproc
) && p
->p_stat
== SRUN
&&
* Returns true if the current
* process has a signal to process.
* The signal to process is put in p_cursig.
* This is asked at least once each time a process enters the
* system (though this can usually be done without actually
* calling issig by checking the pending signal masks.)
* A signal does not do anything
* directly to a process; it sets
* a flag that asks the process to
* do something to itself.
if ((p
->p_flag
&STRC
) == 0)
#define bit(a) (1<<(a-1))
sigbits
&= ~(bit(SIGSTOP
)|bit(SIGTSTP
)|bit(SIGTTIN
)|bit(SIGTTOU
));
p
->p_sig
&= ~sigmask
; /* take the signal! */
if (p
->p_flag
&STRC
&& (p
->p_flag
&SVFORK
)==0) {
* If traced, always stop, and stay
* stopped until released by the parent.
} while (!procxmt() && p
->p_flag
&STRC
);
* If the traced bit got turned off,
* then put the signal taken above back into p_sig
* and go back up to the top to rescan signals.
* This ensures that siga0 and u_signal are consistent.
if ((p
->p_flag
&STRC
) == 0) {
* If parent wants us to take the signal,
* then it will leave it in p->p_cursig;
* otherwise we just look for signals again.
switch (u
.u_signal
[sig
]) {
* Don't take default actions on system processes.
* Children of init aren't allowed to stop
* on signals from the keyboard.
if (p
->p_pptr
== &proc
[1]) {
* These signals are normally not
* sent if the action is the default.
continue; /* == ignore */
* Masking above should prevent us
* ever trying to take action on a held
* or ignored signal, unless process is traced.
if ((p
->p_flag
&STRC
) == 0)
* This signal has an action, let
* Didn't find a signal to send.
* Let psig process the signal.
* Put the argument process into the stopped
* state and notify the parent via wakeup and/or signal.
wakeup((caddr_t
)p
->p_pptr
);
* Avoid sending signal to parent if process is traced
psignal(p
->p_pptr
, SIGCHLD
);
* Perform the action specified by
* The signal bit has already been cleared by issig,
* and the current signal number stored in p->p_cursig.
register struct proc
*rp
= u
.u_procp
;
register int n
= rp
->p_cursig
;
long sigmask
= 1L << (n
-1);
register int (*action
)();
if (action
== SIG_IGN
|| action
== SIG_HOLD
)
if (n
!= SIGILL
&& n
!= SIGTRAP
)
* If this catch value indicates automatic holding of
* subsequent signals, set the hold value.
if (SIGISDEFER(action
)) {
u
.u_signal
[n
] = SIG_HOLD
;
action
= SIGUNDEFER(action
);
* Create a core image on the file "core"
* If you are looking for protection glitches,
* there are probably a wealth of them here
* when this occurs to a suid command.
* It writes UPAGES block of the
* user.h area followed by the entire
register struct inode
*ip
;
printf(", uid %d\n", u
.u_uid
);
if (ctob(UPAGES
+u
.u_dsize
+u
.u_ssize
) >=
u
.u_rlimit
[RLIMIT_CORE
].rlim_cur
)
if (access(ip
, IWRITE
) ||
(ip
->i_mode
&IFMT
) != IFREG
||
u
.u_error
= rdwri(UIO_WRITE
, ip
,
(caddr_t
)&u
, ctob(UPAGES
),
u
.u_error
= rdwri(UIO_WRITE
, ip
,
(caddr_t
)ctob(u
.u_tsize
), ctob(u
.u_dsize
),
ctob(UPAGES
), 0, (int *)0);
u
.u_error
= rdwri(UIO_WRITE
, ip
,
(caddr_t
)(USRSTACK
-ctob(u
.u_ssize
)), ctob(u
.u_ssize
),
ctob(UPAGES
)+ctob(u
.u_dsize
), 0, (int *)0);