]> Zhao Yanbai Git Server - minix.git/commitdiff
A reliable way for userspace to check if a msg is from kernel
authorTomas Hruby <tom@minix3.org>
Mon, 29 Mar 2010 11:25:01 +0000 (11:25 +0000)
committerTomas Hruby <tom@minix3.org>
Mon, 29 Mar 2010 11:25:01 +0000 (11:25 +0000)
- 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

include/minix/ipcconst.h
kernel/proc.c
kernel/proc.h
servers/pm/main.c

index 04aca7954e4ffab0d1f457ebe55d7a6ea418eb76..c077b2c9e3b1dff050ebda541c3b0d450ba26dcc 100644 (file)
 #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 */
index 65d3125d16744364d7a25ecfa04a2046cdda90f3..ae07acfcba6231f584c9cae7f4eb13e72585bb29 100644 (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);
 
index 3de17826916a97f12da3c28688f806241783f36f..b4b38155a52347db9cb9af3745553f7ee7de363a 100644 (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 
index 2f7a6c84a8397d3132a81797759d6e3020b38a5b..0a0212e2abfb8b3063292f2efeb657495f58c012 100644 (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                                     *
  *===========================================================================*/