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:
Tomas Hruby 2010-03-29 11:25:01 +00:00
parent 2521cc6bdf
commit 5b52c5aa02
4 changed files with 60 additions and 29 deletions

View file

@ -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 */

View file

@ -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);

View file

@ -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

View file

@ -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 */
do_noquantum();
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 *
*===========================================================================*/