A reliable way for userspace to check if a msg is from kernel
- IPC_FLG_MSG_FROM_KERNEL status flag is returned to userspace if the receive was satisfied by s message which was sent by the kernel on behalf of a process. This perfectly reliale information. - MF_SENDING_FROM_KERNEL flag added to processes to be able to set IPC_FLG_MSG_FROM_KERNEL when finishing receive if the receiver wasn't ready to receive immediately. - PM is changed to use this information to confirm that the scheduling messages are indeed from the kernel and not faked by a process. PM uses sef_receive_status() - get_work() is removed from PM to make the changes simpler
This commit is contained in:
parent
2521cc6bdf
commit
5b52c5aa02
|
@ -17,4 +17,12 @@
|
||||||
#define IPC_STATUS_CALL_TO(call) \
|
#define IPC_STATUS_CALL_TO(call) \
|
||||||
(((call) & IPC_STATUS_CALL_MASK) << IPC_STATUS_CALL_SHIFT)
|
(((call) & IPC_STATUS_CALL_MASK) << IPC_STATUS_CALL_SHIFT)
|
||||||
|
|
||||||
|
#define IPC_FLG_MSG_FROM_KERNEL 1 /* this message originated in the kernel on
|
||||||
|
behalf of a process, this is a trusted
|
||||||
|
message, never reply to the sender
|
||||||
|
*/
|
||||||
|
#define IPC_STATUS_FLAGS_SHIFT 16
|
||||||
|
#define IPC_STATUS_FLAGS(flgs) ((flgs) << IPC_STATUS_FLAGS_SHIFT)
|
||||||
|
#define IPC_STATUS_FLAGS_TEST(status, flgs) \
|
||||||
|
(((status) >> IPC_STATUS_FLAGS_SHIFT) & (flgs))
|
||||||
#endif /* IPC_CONST_H */
|
#endif /* IPC_CONST_H */
|
||||||
|
|
|
@ -540,8 +540,12 @@ const int flags;
|
||||||
if (!(flags & FROM_KERNEL)) {
|
if (!(flags & FROM_KERNEL)) {
|
||||||
if(copy_msg_from_user(caller_ptr, m_ptr, &dst_ptr->p_delivermsg))
|
if(copy_msg_from_user(caller_ptr, m_ptr, &dst_ptr->p_delivermsg))
|
||||||
return EFAULT;
|
return EFAULT;
|
||||||
} else
|
} else {
|
||||||
dst_ptr->p_delivermsg = *m_ptr;
|
dst_ptr->p_delivermsg = *m_ptr;
|
||||||
|
IPC_STATUS_ADD(dst_ptr,
|
||||||
|
IPC_STATUS_FLAGS(IPC_FLG_MSG_FROM_KERNEL));
|
||||||
|
}
|
||||||
|
|
||||||
dst_ptr->p_delivermsg.m_source = caller_ptr->p_endpoint;
|
dst_ptr->p_delivermsg.m_source = caller_ptr->p_endpoint;
|
||||||
dst_ptr->p_misc_flags |= MF_DELIVERMSG;
|
dst_ptr->p_misc_flags |= MF_DELIVERMSG;
|
||||||
|
|
||||||
|
@ -563,8 +567,15 @@ const int flags;
|
||||||
if (!(flags & FROM_KERNEL)) {
|
if (!(flags & FROM_KERNEL)) {
|
||||||
if(copy_msg_from_user(caller_ptr, m_ptr, &caller_ptr->p_sendmsg))
|
if(copy_msg_from_user(caller_ptr, m_ptr, &caller_ptr->p_sendmsg))
|
||||||
return EFAULT;
|
return EFAULT;
|
||||||
} else
|
} else {
|
||||||
caller_ptr->p_sendmsg = *m_ptr;
|
caller_ptr->p_sendmsg = *m_ptr;
|
||||||
|
/*
|
||||||
|
* we need to remember that this message is from kernel so we
|
||||||
|
* can set the delivery status flags when the message is
|
||||||
|
* actually delivered
|
||||||
|
*/
|
||||||
|
caller_ptr->p_misc_flags |= MF_SENDING_FROM_KERNEL;
|
||||||
|
}
|
||||||
|
|
||||||
RTS_SET(caller_ptr, RTS_SENDING);
|
RTS_SET(caller_ptr, RTS_SENDING);
|
||||||
caller_ptr->p_sendto_e = dst_e;
|
caller_ptr->p_sendto_e = dst_e;
|
||||||
|
@ -693,6 +704,17 @@ const int flags;
|
||||||
|
|
||||||
call = ((*xpp)->p_misc_flags & MF_REPLY_PEND ? SENDREC : SEND);
|
call = ((*xpp)->p_misc_flags & MF_REPLY_PEND ? SENDREC : SEND);
|
||||||
IPC_STATUS_ADD(caller_ptr, IPC_STATUS_CALL_TO(call));
|
IPC_STATUS_ADD(caller_ptr, IPC_STATUS_CALL_TO(call));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if the message is originaly from the kernel on behalf of this
|
||||||
|
* process, we must send the status flags accordingly
|
||||||
|
*/
|
||||||
|
if ((*xpp)->p_misc_flags & MF_SENDING_FROM_KERNEL) {
|
||||||
|
IPC_STATUS_ADD(caller_ptr,
|
||||||
|
IPC_STATUS_FLAGS(IPC_FLG_MSG_FROM_KERNEL));
|
||||||
|
/* we can clean the flag now, not need anymore */
|
||||||
|
(*xpp)->p_misc_flags &= ~MF_SENDING_FROM_KERNEL;
|
||||||
|
}
|
||||||
if ((*xpp)->p_misc_flags & MF_SIG_DELAY)
|
if ((*xpp)->p_misc_flags & MF_SIG_DELAY)
|
||||||
sig_delay_done(*xpp);
|
sig_delay_done(*xpp);
|
||||||
|
|
||||||
|
|
|
@ -221,6 +221,7 @@ struct proc {
|
||||||
#define MF_USED_FPU 0x800 /* process used fpu during last execution run */
|
#define MF_USED_FPU 0x800 /* process used fpu during last execution run */
|
||||||
#define MF_FPU_INITIALIZED 0x1000 /* process already used math, so fpu
|
#define MF_FPU_INITIALIZED 0x1000 /* process already used math, so fpu
|
||||||
* regs are significant (initialized)*/
|
* regs are significant (initialized)*/
|
||||||
|
#define MF_SENDING_FROM_KERNEL 0x2000 /* message of this process is from kernel */
|
||||||
|
|
||||||
/* Scheduling priorities for p_priority. Values must start at zero (highest
|
/* Scheduling priorities for p_priority. Values must start at zero (highest
|
||||||
* priority) and increment. Priorities of the processes in the boot image
|
* priority) and increment. Priorities of the processes in the boot image
|
||||||
|
|
|
@ -40,7 +40,6 @@ EXTERN unsigned long calls_stats[NCALLS];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FORWARD _PROTOTYPE( void sendreply, (void) );
|
FORWARD _PROTOTYPE( void sendreply, (void) );
|
||||||
FORWARD _PROTOTYPE( void get_work, (void) );
|
|
||||||
FORWARD _PROTOTYPE( int get_nice_value, (int queue) );
|
FORWARD _PROTOTYPE( int get_nice_value, (int queue) );
|
||||||
FORWARD _PROTOTYPE( void handle_fs_reply, (void) );
|
FORWARD _PROTOTYPE( void handle_fs_reply, (void) );
|
||||||
|
|
||||||
|
@ -70,14 +69,32 @@ PUBLIC int main()
|
||||||
|
|
||||||
/* This is PM's main loop- get work and do it, forever and forever. */
|
/* This is PM's main loop- get work and do it, forever and forever. */
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
get_work(); /* wait for an PM system call */
|
int ipc_status;
|
||||||
|
|
||||||
|
/* Wait for the next message and extract useful information from it. */
|
||||||
|
if (sef_receive_status(ANY, &m_in, &ipc_status) != OK)
|
||||||
|
panic("PM sef_receive error");
|
||||||
|
who_e = m_in.m_source; /* who sent the message */
|
||||||
|
if(pm_isokendpt(who_e, &who_p) != OK)
|
||||||
|
panic("PM got message from invalid endpoint: %d", who_e);
|
||||||
|
call_nr = m_in.m_type; /* system call number */
|
||||||
|
|
||||||
|
/* Process slot of caller. Misuse PM's own process slot if the kernel is
|
||||||
|
* calling. This can happen in case of synchronous alarms (CLOCK) or or
|
||||||
|
* event like pending kernel signals (SYSTEM).
|
||||||
|
*/
|
||||||
|
mp = &mproc[who_p < 0 ? PM_PROC_NR : who_p];
|
||||||
|
if(who_p >= 0 && mp->mp_endpoint != who_e) {
|
||||||
|
panic("PM endpoint number out of sync with source: %d",
|
||||||
|
mp->mp_endpoint);
|
||||||
|
}
|
||||||
|
|
||||||
/* Drop delayed calls from exiting processes. */
|
/* Drop delayed calls from exiting processes. */
|
||||||
if (mp->mp_flags & EXITING)
|
if (mp->mp_flags & EXITING)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Check for system notifications first. Special cases. */
|
/* Check for system notifications first. Special cases. */
|
||||||
if (is_notify(call_nr)) {
|
if (is_ipc_notify(ipc_status)) {
|
||||||
switch(who_p) {
|
switch(who_p) {
|
||||||
case CLOCK:
|
case CLOCK:
|
||||||
pm_expire_timers(m_in.NOTIFY_TIMESTAMP);
|
pm_expire_timers(m_in.NOTIFY_TIMESTAMP);
|
||||||
|
@ -116,7 +133,13 @@ PUBLIC int main()
|
||||||
break;
|
break;
|
||||||
case SCHEDULING_NO_QUANTUM:
|
case SCHEDULING_NO_QUANTUM:
|
||||||
/* This message was sent from the kernel, don't reply */
|
/* This message was sent from the kernel, don't reply */
|
||||||
|
if (IPC_STATUS_FLAGS_TEST(ipc_status, IPC_FLG_MSG_FROM_KERNEL)) {
|
||||||
do_noquantum();
|
do_noquantum();
|
||||||
|
} else {
|
||||||
|
printf("PM: process %s/%d faked SCHEDULING_NO_QUANTUM "
|
||||||
|
"message!\n",
|
||||||
|
mp->mp_name, mp->mp_endpoint);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
/* Else, if the system call number is valid, perform the
|
/* Else, if the system call number is valid, perform the
|
||||||
|
@ -314,29 +337,6 @@ PRIVATE int sef_cb_signal_manager(endpoint_t target, int signo)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* get_work *
|
|
||||||
*===========================================================================*/
|
|
||||||
PRIVATE void get_work()
|
|
||||||
{
|
|
||||||
/* Wait for the next message and extract useful information from it. */
|
|
||||||
if (sef_receive(ANY, &m_in) != OK)
|
|
||||||
panic("PM sef_receive error");
|
|
||||||
who_e = m_in.m_source; /* who sent the message */
|
|
||||||
if(pm_isokendpt(who_e, &who_p) != OK)
|
|
||||||
panic("PM got message from invalid endpoint: %d", who_e);
|
|
||||||
call_nr = m_in.m_type; /* system call number */
|
|
||||||
|
|
||||||
/* Process slot of caller. Misuse PM's own process slot if the kernel is
|
|
||||||
* calling. This can happen in case of synchronous alarms (CLOCK) or or
|
|
||||||
* event like pending kernel signals (SYSTEM).
|
|
||||||
*/
|
|
||||||
mp = &mproc[who_p < 0 ? PM_PROC_NR : who_p];
|
|
||||||
if(who_p >= 0 && mp->mp_endpoint != who_e) {
|
|
||||||
panic("PM endpoint number out of sync with source: %d", mp->mp_endpoint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* setreply *
|
* setreply *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
|
Loading…
Reference in a new issue