1 
  2 #if (BUILTIN_PROT_SCHED == 1)
  3 
  4 #include "ta_internals.h"
  5 
  6 
  7 #define PROCESS_STATE_NONE        0
  8 #define PROCESS_STATE_RUNNING     1
  9 #define PROCESS_STATE_CALLED      2
 10 
 11 #define DEBUG 0
 12 #if DEBUG
 13 #include <stdio.h>
 14 #define PRINTF(...) printf(__VA_ARGS__)
 15 #else
 16 #define PRINTF(...)
 17 #endif
 18 
 19 void call_process(struct process *p, process_event_t ev, process_data_t data);
 20 void exit_process(struct process *p, struct process *fromprocess);
 21 
 22 static int __attribute__ ((noinline))
 23 __TASecureCallProcess (struct process *p,
 24   process_event_t ev, process_data_t data)
 25 {
 26   static int ret = -1;
 27   eint();
 28   ret = p->thread(&p->pt, ev, data);
 29   dint();
 30   return (ret);
 31 }
 32 
 33 
 34 int SM_ENTRY(TA_SM_NAME) TASecureCallProcess (struct process *p,
 35   process_event_t ev, process_data_t data)
 36 {
 37   static int ret = -1;
 38 
 39 /* Check __TASecureCallProcess()
 40  * Check p->thread
 41  * Store call and timing somewhere
 42  *
 43  * Q: check caller? Do we gain anything from that?
 44  * Q: Why noth check all code sections at every call?
 45  * A: We want to minimise overhead and check a minimum subset of
 46  *    components that enable us to give relatively strong guarantees
 47  *    already. Importantly, this is not a countermeasure against a specific
 48  *    known attack but a pretty much generic approach to mitigate unknown
 49  *    attacks and to detect faulty corruption of software components.
 50  */
 51 
 52 
 53 #ifdef __DEBUG
 54   printf2("TA: calling process '%s' with event %d.\n",
 55     (void *) PROCESS_NAME_STRING(p), (void *) ((int) ev));
 56 #endif
 57 #if (TA_PROCESS_INSPECTOR == 1)
 58   __TIMING_INIT();
 59   if (TAInitialised) {
 60     TAProcessUpdate (p->thread);
 61   }
 62   __TIMING_PRINT("+++ TASecureCallProcess(): update inv & time ");
 63 #endif
 64   ret = __TASecureCallProcess (p, ev, data);
 65 
 66   return (ret);
 67 }
 68 
 69 
 70 
 71 /* modified from contiki/core/sys/process.c */
 72 void
 73 exit_process(struct process *p, struct process *fromprocess)
 74 {
 75   register struct process *q;
 76   struct process *old_current = process_current;
 77 
 78   PRINTF("process: exit_process '%s'\n", PROCESS_NAME_STRING(p));
 79 
 80   /* Make sure the process is in the process list before we try to
 81      exit it. */
 82   for(q = process_list; q != p && q != NULL; q = q->next);
 83   if(q == NULL) {
 84     return;
 85   }
 86 
 87   if(process_is_running(p)) {
 88     /* Process was running */
 89     p->state = PROCESS_STATE_NONE;
 90 
 91     /*
 92      * Post a synchronous event to all processes to inform them that
 93      * this process is about to exit. This will allow services to
 94      * deallocate state associated with this process.
 95      */
 96     for(q = process_list; q != NULL; q = q->next) {
 97       if(p != q) {
 98         call_process(q, PROCESS_EVENT_EXITED, (process_data_t)p);
 99       }
100     }
101 
102     if(p->thread != NULL && p != fromprocess) {
103       /* Post the exit event to the process that is about to exit. */
104       process_current = p;
105       dint();
106       TASecureCallProcess(p, PROCESS_EVENT_EXIT, NULL);
107       eint();
108     }
109   }
110 
111   if(p == process_list) {
112     process_list = process_list->next;
113   } else {
114     for(q = process_list; q != NULL; q = q->next) {
115       if(q->next == p) {
116         q->next = p->next;
117         break;
118       }
119     }
120   }
121 
122   process_current = old_current;
123 }
124 
125 
126 /* modified from contiki/core/sys/process.c */
127 void
128 call_process(struct process *p, process_event_t ev, process_data_t data)
129 {
130   int ret;
131 
132 #if DEBUG
133   if(p->state == PROCESS_STATE_CALLED) {
134     printf("process: process '%s' called again with event %d\n", PROCESS_NAME_STRING(p), ev);
135   }
136 #endif /* DEBUG */
137 
138   if((p->state & PROCESS_STATE_RUNNING) &&
139      p->thread != NULL) {
140     PRINTF("process: calling process '%s' with event %d\n", PROCESS_NAME_STRING(p), ev);
141     process_current = p;
142     p->state = PROCESS_STATE_CALLED;
143     dint();
144     ret = TASecureCallProcess(p, ev, data);
145     eint();
146     if(ret == PT_EXITED ||
147        ret == PT_ENDED ||
148        ev == PROCESS_EVENT_EXIT) {
149       exit_process(p, p);
150     } else {
151       p->state = PROCESS_STATE_RUNNING;
152     }
153   }
154 }
155 
156 
157 #endif /* #if (BUILTIN_PROT_SCHED == 1) */
158