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
4 changed files with 60 additions and 29 deletions
|
@ -17,4 +17,12 @@
|
|||
#define IPC_STATUS_CALL_TO(call) \
|
||||
(((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 */
|
||||
|
|
|
@ -540,8 +540,12 @@ const int flags;
|
|||
if (!(flags & FROM_KERNEL)) {
|
||||
if(copy_msg_from_user(caller_ptr, m_ptr, &dst_ptr->p_delivermsg))
|
||||
return EFAULT;
|
||||
} else
|
||||
} else {
|
||||
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_misc_flags |= MF_DELIVERMSG;
|
||||
|
||||
|
@ -563,8 +567,15 @@ const int flags;
|
|||
if (!(flags & FROM_KERNEL)) {
|
||||
if(copy_msg_from_user(caller_ptr, m_ptr, &caller_ptr->p_sendmsg))
|
||||
return EFAULT;
|
||||
} else
|
||||
} else {
|
||||
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);
|
||||
caller_ptr->p_sendto_e = dst_e;
|
||||
|
@ -693,6 +704,17 @@ const int flags;
|
|||
|
||||
call = ((*xpp)->p_misc_flags & MF_REPLY_PEND ? SENDREC : SEND);
|
||||
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)
|
||||
sig_delay_done(*xpp);
|
||||
|
||||
|
|
|
@ -221,6 +221,7 @@ struct proc {
|
|||
#define MF_USED_FPU 0x800 /* process used fpu during last execution run */
|
||||
#define MF_FPU_INITIALIZED 0x1000 /* process already used math, so fpu
|
||||
* 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
|
||||
* priority) and increment. Priorities of the processes in the boot image
|
||||
|
|
|
@ -40,7 +40,6 @@ EXTERN unsigned long calls_stats[NCALLS];
|
|||
#endif
|
||||
|
||||
FORWARD _PROTOTYPE( void sendreply, (void) );
|
||||
FORWARD _PROTOTYPE( void get_work, (void) );
|
||||
FORWARD _PROTOTYPE( int get_nice_value, (int queue) );
|
||||
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. */
|
||||
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. */
|
||||
if (mp->mp_flags & EXITING)
|
||||
continue;
|
||||
|
||||
/* Check for system notifications first. Special cases. */
|
||||
if (is_notify(call_nr)) {
|
||||
if (is_ipc_notify(ipc_status)) {
|
||||
switch(who_p) {
|
||||
case CLOCK:
|
||||
pm_expire_timers(m_in.NOTIFY_TIMESTAMP);
|
||||
|
@ -116,7 +133,13 @@ PUBLIC int main()
|
|||
break;
|
||||
case SCHEDULING_NO_QUANTUM:
|
||||
/* This message was sent from the kernel, don't reply */
|
||||
if (IPC_STATUS_FLAGS_TEST(ipc_status, IPC_FLG_MSG_FROM_KERNEL)) {
|
||||
do_noquantum();
|
||||
} else {
|
||||
printf("PM: process %s/%d faked SCHEDULING_NO_QUANTUM "
|
||||
"message!\n",
|
||||
mp->mp_name, mp->mp_endpoint);
|
||||
}
|
||||
continue;
|
||||
default:
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* 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 *
|
||||
*===========================================================================*/
|
||||
|
|
Loading…
Reference in a new issue