/* kern_sig.c 6.7 84/09/04 */
#include "../machine/reg.h"
#include "../machine/pte.h"
#include "../machine/psl.h"
#define cantmask (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP))
* Quick interface to signal handler.
int (*handler
)(); /* signal handler */
} *uap
= (struct a
*)u
.u_ap
;
register struct sigvec
*sv
= &vec
;
if (sig
<= 0 || sig
>= NSIG
|| sig
== SIGKILL
|| sig
== SIGSTOP
||
(sig
== SIGCONT
&& uap
->handler
== SIG_IGN
)) {
sv
->sv_handler
= uap
->handler
;
u
.u_r
.r_val1
= (int)u
.u_signal
[sig
];
* Generalized interface signal handler.
} *uap
= (struct a
*)u
.u_ap
;
register struct sigvec
*sv
;
if (sig
<= 0 || sig
>= NSIG
|| sig
== SIGKILL
|| sig
== SIGSTOP
) {
sv
->sv_handler
= u
.u_signal
[sig
];
sv
->sv_mask
= u
.u_sigmask
[sig
];
sv
->sv_onstack
= (u
.u_sigonstack
& sigmask(sig
)) != 0;
copyout((caddr_t
)sv
, (caddr_t
)uap
->osv
, sizeof (vec
));
copyin((caddr_t
)uap
->nsv
, (caddr_t
)sv
, sizeof (vec
));
if (sig
== SIGCONT
&& sv
->sv_handler
== SIG_IGN
) {
register struct sigvec
*sv
;
* Change setting atomically.
u
.u_signal
[sig
] = sv
->sv_handler
;
u
.u_sigmask
[sig
] = sv
->sv_mask
&~ cantmask
;
if (sv
->sv_handler
== SIG_IGN
) {
p
->p_sig
&= ~bit
; /* never to be seen again */
if (sv
->sv_handler
== SIG_DFL
)
} *uap
= (struct a
*)u
.u_ap
;
register struct proc
*p
= u
.u_procp
;
u
.u_r
.r_val1
= p
->p_sigmask
;
p
->p_sigmask
|= uap
->mask
&~ cantmask
;
} *uap
= (struct a
*)u
.u_ap
;
register struct proc
*p
= u
.u_procp
;
u
.u_r
.r_val1
= p
->p_sigmask
;
p
->p_sigmask
= uap
->mask
&~ cantmask
;
} *uap
= (struct a
*)u
.u_ap
;
register struct proc
*p
= u
.u_procp
;
* When returning from sigpause, we want
* the old mask to be restored after the
* signal handler has finished. Thus, we
* save it here and mark the proc structure
* to indicate this (should be in u.).
u
.u_oldmask
= p
->p_sigmask
;
p
->p_sigmask
= uap
->mask
&~ cantmask
;
sleep((caddr_t
)&u
, PSLEP
);
} *uap
= (struct a
*)u
.u_ap
;
u
.u_error
= copyout((caddr_t
)&u
.u_sigstack
, (caddr_t
)uap
->oss
,
sizeof (struct sigstack
));
copyin((caddr_t
)uap
->nss
, (caddr_t
)&ss
, sizeof (ss
));
/* KILL SHOULD BE UPDATED */
} *uap
= (struct a
*)u
.u_ap
;
u
.u_error
= kill1(uap
->signo
< 0,
uap
->signo
< 0 ? -uap
->signo
: uap
->signo
, uap
->pid
);
} *uap
= (struct a
*)u
.u_ap
;
u
.u_error
= kill1(1, uap
->signo
, uap
->pgrp
);
/* KILL CODE SHOULDNT KNOW ABOUT PROCESS INTERNALS !?! */
kill1(ispgrp
, signo
, who
)
if (signo
< 0 || signo
> NSIG
)
if (who
> 0 && !ispgrp
) {
if (u
.u_uid
&& u
.u_uid
!= p
->p_uid
)
if (who
== -1 && u
.u_uid
== 0)
priv
++, who
= 0, ispgrp
= 1; /* like sending to pgrp */
* Zero process id means send to my process group.
for (f
= 0, p
= allproc
; p
!= NULL
; p
= p
->p_nxt
) {
} else if (p
->p_pgrp
!= who
&& 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
&&
(signo
!= SIGCONT
|| !inferior(p
)))
return (f
== 0 ? ESRCH
: 0);
* Send the specified signal to
* all processes with 'pgrp' as
for (p
= allproc
; p
!= NULL
; p
= p
->p_nxt
)
* Send the specified signal to
register int (*action
)();
if ((unsigned)sig
>= NSIG
)
* If proc is traced, always give parent a chance.
* If the signal is being ignored,
* then we forget about it immediately.
if (p
->p_sigignore
& mask
)
else if (p
->p_sigcatch
& mask
)
#define stops (sigmask(SIGSTOP)|sigmask(SIGTSTP)| \
sigmask(SIGTTIN)|sigmask(SIGTTOU))
if ((p
->p_flag
&STRC
) || action
!= SIG_DFL
)
p
->p_sig
&= ~sigmask(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
&= ~mask
; /* 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
&= ~mask
; /* 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.
sigbits
= p
->p_sig
&~ p
->p_sigmask
;
if ((p
->p_flag
&STRC
) == 0)
sigbits
&= ~p
->p_sigignore
;
#define bit(a) (1<<(a-1))
sigbits
&= ~(bit(SIGSTOP
)|bit(SIGTSTP
)|bit(SIGTTIN
)|bit(SIGTTOU
));
p
->p_sig
&= ~mask
; /* 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 p_sig* 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.
* If signal is being masked put it back
* into p_sig and look for other signals.
if (p
->p_sigmask
& mask
) {
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
*p
= u
.u_procp
;
register int sig
= p
->p_cursig
;
int mask
= sigmask(sig
), returnmask
;
register int (*action
)();
action
= u
.u_signal
[sig
];
if (action
== SIG_IGN
|| (p
->p_sigmask
& mask
))
* Set the new mask value and also defer further
* occurences of this signal (unless we're simulating
* the old signal facilities).
* Special case: user has done a sigpause. Here the
* current mask is not of interest, but rather the
* mask from before the sigpause is what we want restored
* after the signal processing is completed.
if (p
->p_flag
& SOUSIG
) {
if (sig
!= SIGILL
&& sig
!= SIGTRAP
) {
u
.u_signal
[sig
] = SIG_DFL
;
if (p
->p_flag
& SOMASK
) {
returnmask
= u
.u_oldmask
;
returnmask
= p
->p_sigmask
;
p
->p_sigmask
|= u
.u_sigmask
[sig
] | mask
;
sendsig(action
, sig
, returnmask
);
* 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
;
register struct nameidata
*ndp
= &u
.u_nd
;
if (u
.u_uid
!= u
.u_ruid
|| u
.u_gid
!= u
.u_rgid
)
if (ctob(UPAGES
+u
.u_dsize
+u
.u_ssize
) >=
u
.u_rlimit
[RLIMIT_CORE
].rlim_cur
)
ndp
->ni_nameiop
= CREATE
| FOLLOW
;
ndp
->ni_segflg
= UIO_SYSSPACE
;
if (access(ip
, IWRITE
) ||
(ip
->i_mode
&IFMT
) != IFREG
||
u
.u_error
= rdwri(UIO_WRITE
, ip
,
u
.u_error
= rdwri(UIO_WRITE
, ip
,
(caddr_t
)ctob(dptov(u
.u_procp
, 0)),
ctob(UPAGES
), 0, (int *)0);
u
.u_error
= rdwri(UIO_WRITE
, ip
,
(caddr_t
)ctob(sptov(u
.u_procp
, u
.u_ssize
- 1)),
ctob(UPAGES
)+ctob(u
.u_dsize
), 0, (int *)0);