/* kern_sig.c 5.1 82/07/15 */
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
)
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
)))
* Used to pass trace command from
* parent to child being traced.
* This data base cannot be
* 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_limit
[LIM_CORE
])
if (!access(ip
, IWRITE
) &&
(ip
->i_mode
&IFMT
) == IFREG
&&
u
.u_count
= ctob(UPAGES
);
u
.u_base
= (char *)ctob(u
.u_tsize
);
u
.u_count
= ctob(u
.u_dsize
);
u
.u_base
= (char *)(USRSTACK
- ctob(u
.u_ssize
));
u
.u_count
= ctob(u
.u_ssize
);
* grow the stack to include the SP
* true return if successful.
if (sp
>= USRSTACK
-ctob(u
.u_ssize
))
si
= clrnd(btoc((USRSTACK
-sp
)) - u
.u_ssize
+ SINCR
);
if (ctob(u
.u_ssize
+si
) > u
.u_limit
[LIM_STACK
])
if (chksize(u
.u_tsize
, u
.u_dsize
, u
.u_ssize
+si
))
if (swpexpand(u
.u_dsize
, u
.u_ssize
+si
, &u
.u_dmap
, &u
.u_smap
)==0)
uap
= (struct a
*)u
.u_ap
;
u
.u_procp
->p_flag
|= STRC
;
if (p
== 0 || p
->p_stat
!= SSTOP
|| p
->p_ppid
!= u
.u_procp
->p_pid
) {
sleep((caddr_t
)&ipc
, IPCPRI
);
sleep((caddr_t
)&ipc
, IPCPRI
);
u
.u_r
.r_val1
= ipc
.ip_data
;
int ipcreg
[] = {R0
,R1
,R2
,R3
,R4
,R5
,R6
,R7
,R8
,R9
,R10
,R11
,AP
,FP
,SP
,PC
};
* Code that the child process
* executes to implement the command
* of the parent process in tracing.
register struct text
*xp
;
if (ipc
.ip_lock
!= u
.u_procp
->p_pid
)
u
.u_procp
->p_slptime
= 0;
if (!useracc((caddr_t
)ipc
.ip_addr
, 4, B_READ
))
ipc
.ip_data
= fuiword((caddr_t
)ipc
.ip_addr
);
if (!useracc((caddr_t
)ipc
.ip_addr
, 4, B_READ
))
ipc
.ip_data
= fuword((caddr_t
)ipc
.ip_addr
);
if (i
<0 || i
>= ctob(UPAGES
))
ipc
.ip_data
= ((physadr
)&u
)->r
[i
>>2];
/* Must set up to allow writing */
* If text, must assure exclusive use
if (xp
= u
.u_procp
->p_textp
) {
if (xp
->x_count
!=1 || xp
->x_iptr
->i_mode
&ISVTX
)
xp
->x_iptr
->i_flag
&= ~ITEXT
;
if (chgprot((caddr_t
)ipc
.ip_addr
, RW
) &&
chgprot((caddr_t
)ipc
.ip_addr
+(sizeof(int)-1), RW
))
i
= suiword((caddr_t
)ipc
.ip_addr
, ipc
.ip_data
);
(void) chgprot((caddr_t
)ipc
.ip_addr
, RO
);
(void) chgprot((caddr_t
)ipc
.ip_addr
+(sizeof(int)-1), RO
);
if (suword((caddr_t
)ipc
.ip_addr
, 0) < 0)
(void) suword((caddr_t
)ipc
.ip_addr
, ipc
.ip_data
);
p
= (int *)&((physadr
)&u
)->r
[i
>>2];
if (p
== &u
.u_ar0
[ipcreg
[i
]])
ipc
.ip_data
|= PSL_CURMOD
|PSL_PRVMOD
;
ipc
.ip_data
&= ~PSL_USERCLR
;
/* set signal and continue */
/* one version causes a trace-trap */
if ((int)ipc
.ip_addr
!= 1)
u
.u_ar0
[PC
] = (int)ipc
.ip_addr
;
if ((unsigned)ipc
.ip_data
> NSIG
)
u
.u_procp
->p_cursig
= ipc
.ip_data
; /* see issig */
exit(u
.u_procp
->p_cursig
);