Geant4  10.00.p03
ProtectedMemory.cc
Go to the documentation of this file.
1 #include <iostream>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <string.h>
6 #include <libgen.h> /* for basename() */
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <sys/wait.h>
10 #include <fcntl.h>
11 #include <sys/mman.h>
12 #include <errno.h>
13 #include <assert.h>
14 //#include <ucontext.h>
15 #include <sys/mman.h>
16 #include <signal.h>
17 #include <execinfo.h>
18 #include <stdlib.h>
19 #include <sys/syscall.h>
20 #include <pthread.h>
21 
22 #include "tls.hh"
23 
24 static pid_t gettid()
25 {
26  pid_t mytid = syscall(SYS_gettid);
27  return mytid;
28 }
29 
30 
31 static char *startPosition = 0;
32 static char *currentPosition = 0;
33 static char *nextPosition = 0;
34 static char *endPosition = 0;
35 
36 void* AllocateInProtectedHeap(size_t size)
37 {
38  if (startPosition != 0)
39  {
41  nextPosition = &nextPosition[size];
43  {
45  return malloc(size);
46  }
47  return currentPosition;
48  }
49  else
50  {
51  return malloc(size);
52  }
53 }
54 
55 static void AllocateProtectedHeap(size_t totalSize, size_t pagesize)
56 {
57 
58  if (startPosition != 0) return;
59 
60  startPosition = (char *) malloc(pagesize * 2 + totalSize);
63  endPosition = nextPosition + totalSize;
64 }
65 
66 
67 #include "memoryprotection/UDSignals.h"
68 
69 static int readFile(char *filename, char *buf, int maxSize);
70 static char *readhex(char *string, long *value);
71 static char *readMapsLine(char *string, void **start, void **end, int *writable, char *filename);
72 static void *getPageNumber(void *theAddress);
73 static void setuphandler0();
74 static void setuphandler1();
75 static void setuphandler2();
76 // static void raisesignal();
77 static void SetUpAllProtect();
78 static void UnSetUpAllProtect();
79 // static void protectAll();
80 // static void unProtectAll();
81 // static void noProtectAll();
82 
83 
84 static size_t pagesize;
85 static int logpagesize;
86 // static int stdOutFile;
87 // static int theSignal;
88 // static void *theAddress;
89 
90 #include "memoryprotection/MemorySegment.h"
91 
92 static char application[1024];
93 
94 //#define PROTECTEDMEMORYDEBUG 1
95 
96 static int phase = 0;
97 
98 static void *getPageNumber(void *address) {return (void *) (((long) address >> logpagesize) << logpagesize);}
99 
100 static G4ThreadLocal void *trace[100];
101 static int outputFile = -1;
102 static int trace_size;
103 
105 {
106  int tmpoutputFile;
107  tmpoutputFile = outputFile;
108 
109  phase++;
110  pid_t myselfpid = getpid();
111  char outputfilename[1024];
112  outputfilename[0] = 0;
113  sprintf(outputfilename, "./memoryhotpot.out.%d.%d", phase, myselfpid);
114 
115  outputFile = open(outputfilename, O_CREAT|O_RDWR, S_IRWXU);
116  close(tmpoutputFile);
117 }
118 
119 static void record_stackframe() {
120  trace_size = 0;
121  trace_size = backtrace(trace, 100);
122  backtrace_symbols_fd(trace, trace_size, outputFile);
123 }
124 
125 static void show_stackframe() {
126  trace_size = 0;
127  trace_size = backtrace(trace, 100);
128  backtrace_symbols_fd(trace, trace_size, STDOUT_FILENO);
129 }
130 
131 static int isCalled = 0;
132 
133 static void handler0(int, siginfo_t *, void *)
134 {
135  #ifdef PROTECTEDMEMORYDEBUG
136  printf("In handler 0 p1.\n");
137  #endif
138  if (isCalled == 0)
139  {
140  #ifdef PROTECTEDMEMORYDEBUG
141  printf("In handler 0 p2.\n");
142  #endif
143  isCalled = 1;
144  SetUpAllProtect();
145  #ifdef PROTECTEDMEMORYDEBUG
146  printf("In handler 0 p3.\n");
147  #endif
148  assert( 0 == raise(SIGUSR2));
149  }
150 }
151 
152 static void handler1(int, siginfo_t *, void *)
153 {
154  #ifdef PROTECTEDMEMORYDEBUG
155  printf("In handler 1 p1.\n");
156  #endif
157 
159 
160  // show_stackframe();
161 
163 
164  #ifdef PROTECTEDMEMORYDEBUG
165  printf("In handler 1 p2.\n");
166  #endif
167 
168  assert( 0 == raise(SIGUSR2));
169 }
170 
171 // mprotect_map and mprotect_addr should be the statically defined arrays
172 // this function protect only one page, it is not correct because
173 // we do not know how large the memory is in one assemble instruction
174 static void handler2(int, siginfo_t *, void *)
175 {
176  #ifdef PROTECTEDMEMORYDEBUG
177  printf("In handler 2 p1.\n");
178  #endif
179 
180  SetUpAllProtect();
181 }
182 
183 void BuildProtectedMemory(size_t totalHeap)
184 {
185  pagesize = getpagesize();
186 
187  pid_t myselfpid = getpid();
188  char outputfilename[1024];
189  outputfilename[0] = 0;
190  sprintf(outputfilename, "./memoryhotpot.out.%d.%d", phase, myselfpid);
191  outputFile = open(outputfilename, O_CREAT|O_RDWR, S_IRWXU);
192 
193  show_stackframe();
194 
195  #ifdef PROTECTEDMEMORYDEBUG
196  printf("Page size: %d\n", pagesize);
197  #endif
198 
199  long tmp;
200  for (logpagesize = -1, tmp = pagesize; tmp > 0; logpagesize++)
201  tmp = tmp >> 1;
202 
203  #ifdef PROTECTEDMEMORYDEBUG
204  printf("log(page size): %d\n", logpagesize);
205  #endif
206 
207  if (totalHeap > 0)
208  {
209  AllocateProtectedHeap(totalHeap, pagesize);
210 
211  memorySegments[numOfSegments].start = getPageNumber(nextPosition);
212  memorySegments[numOfSegments].end = getPageNumber(endPosition);
213  numOfSegments++;
214  }
215 
216  //force to load backtrace library
217  // show_stackframe();
218 
219  //open output file
220  // assert(-1 != (stdOutFile = open("./memoryhotspot.out", O_CREAT, S_IRWXU)));
221 
222  char buf1[1024];
223  char buf2[51200];
224  char *tmp2 = buf2;
225  static char filename2[1024];
226  void *start;
227  void *end;
228  int writable;
229 
230  if (-1 == readFile((char *) "/proc/self/cmdline", buf1, 1024)) {
231  perror("readFile: /proc/self/cmdline");
232  abort();
233  }
234  memset(application, 0, 1024);
235  strcpy(application, buf1);
236 
237  // cout << "command line: " << application << endl;
238 
239  if (-1 == readFile((char *) "/proc/self/maps", buf2, 51200)) {
240  perror("readFile: /proc/self/maps");
241  abort();
242  }
243  static char lastfilename[1024];
244  do {
245  tmp2 = readMapsLine(tmp2, &start, &end, &writable, filename2);
246  if (strlen(filename2) > 0)
247  {
248  lastfilename[0] = 0;
249  strcpy(lastfilename, filename2);
250  }
251  else
252  {
253  strcpy(filename2, lastfilename);
254  }
255 
256  // if (writable == 1 && (long int) start < 0x700000000000 &&
257  // strncmp(filename2, "/lib64/", 7) != 0 && strncmp(filename2, "/opt/", 5) != 0 &&
258  // ((long int) nextPosition < (long int) start || (long int) nextPosition > (long int ) end) &&
259  // ((long int) endPosition < (long int) start || (long int) endPosition > (long int ) end))
260  if (writable == 1)
261  {
262  //ignore
263  if (strstr(filename2, "ld") != 0)
264  {
265  std::cout << "Not protected: " << start << ", " << end << ", "
266  << writable << ", " << filename2
267  << std::endl;
268  }
269  else if (strstr(filename2, "vdso") != 0)
270  {
271  std::cout << "Not protected: " << start << ", " << end << ", "
272  << writable << ", " << filename2
273  << std::endl;
274  }
275  else if (strstr(filename2, "stack") != 0)
276  {
277  std::cout << "Not protected: " << start << ", " << end << ", "
278  << writable << ", " << filename2
279  << std::endl;
280  }
281  else if (strstr(filename2, "libc") != 0)
282  {
283  std::cout << "Not protected: " << start << ", " << end << ", "
284  << writable << ", " << filename2
285  << std::endl;
286  }
287  else if (strstr(filename2, "libProtectedMemory.so") != 0)
288  {
289  std::cout << "Not protected: " << start << ", " << end << ", "
290  << writable << ", " << filename2
291  << std::endl;
292  }
293  else if (strstr(filename2, "libParRunManagerMP.so") != 0)
294  {
295  std::cout << "Not protected: " << start << ", " << end << ", "
296  << writable << ", " << filename2
297  << std::endl;
298  }
299  else if (strstr(filename2, "libmymalloc.so") != 0)
300  {
301  std::cout << "Not protected: " << start << ", " << end << ", "
302  << writable << ", " << filename2
303  << std::endl;
304  }
305  else if (strstr(filename2, "libtpmallocstub.so") != 0)
306  {
307  std::cout << "Not protected: " << start << ", " << end << ", "
308  << writable << ", " << filename2
309  << std::endl;
310  }
311  else if (strstr(filename2, "heap") != 0)
312  {
313  static int Heapcount = 0;
314  //Only one is the data segment follows with [heap] [thread private heap, empty, thread local storage]*
315  Heapcount++;
316  if (Heapcount == 1)
317  {
318  std::cout << "Protected: " << numOfSegments << ", " << start << ", " << end << ", "
319  << writable << ", " << filename2
320  << std::endl;
321  memorySegments[numOfSegments].start = start;
322  memorySegments[numOfSegments].end = end;
323  numOfSegments++;
324  }
325  else
326  {
327  std::cout << "Not protected: " << start << ", " << end << ", "
328  << writable << ", " << filename2
329  << std::endl;
330  }
331  }
332  else if (strstr(filename2, "ParA01") != 0)
333  {
334  static int Parmaincount = 0;
335  //Only one is the data segment follows with [heap] [thread private heap, empty, thread local storage]*
336  Parmaincount++;
337  printf("Determine: %d\n", Parmaincount);
338  // if (Parmaincount == 1 || Parmaincount == 2)
339  {
340  std::cout << "Protected: " << numOfSegments << ", " << start << ", " << end << ", "
341  << writable << ", " << filename2
342  << std::endl;
343  memorySegments[numOfSegments].start = start;
344  memorySegments[numOfSegments].end = end;
345  numOfSegments++;
346  }
347  }
348  else if (strstr(filename2, "geant4") != 0)
349  {
350  std::cout << "Protected: " << numOfSegments << ", " << start << ", " << end << ", "
351  << writable << ", " << filename2
352  << std::endl;
353  memorySegments[numOfSegments].start = start;
354  memorySegments[numOfSegments].end = end;
355  numOfSegments++;
356  }
357 
358  }
359  else
360  {
361  std::cout << "Not protected: " << start << ", " << end << ", "
362  << writable << ", " << filename2
363  << std::endl;
364  }
365 
366  } while ((*tmp2) != '\0' && numOfSegments < 4096);
367 }
368 
369 static int readFile(char *filename, char *buf, int maxSize) {
370  int num;
371  int fd = open(filename, O_RDONLY);
372  char *buf2 = buf;
373 
374  errno = 0;
375  do {
376  num = 0;
377  do {
378  buf2 += num;
379  num = read(fd, buf2, 1000);
380  } while (num != 0 && num != -1 && buf2 - buf < maxSize - 1000);
381  } while (errno == EINTR || errno == EAGAIN);
382  buf2 += num;
383  *buf2 = '\0';
384  *(buf2 + 1) = '\0';
385  close(fd);
386  return (errno == 0 ? 0 : -1);
387 }
388 
389 static char *readhex (char *string, long *value) {
390  char c;
391  *value = 0;
392  while (1) {
393  c = *(string++);
394  if ((c >= '0') && (c <= '9')) c -= '0';
395  else if ((c >= 'a') && (c <= 'f')) c -= 'a' - 10;
396  else if ((c >= 'A') && (c <= 'F')) c -= 'A' - 10;
397  else break;
398  *value = *value * 16 + c;
399  }
400  return (char *) --string;
401 }
402 
403 static char *readMapsLine(char *string, void **start, void **end, int *writable, char *filename) {
404  char *str;
405 
406  string = readhex(string, (long *) start) + 1;
407  string = readhex(string, (long *) end);
408  *writable = (string[2] == 'w');
409  for (str = string; *str != '\n' && *str != '\0'; str++);
410  *(str++) = '\0';
411  for (str = string; (*str != '/' && *str != '[') && *str != '\0'; str++);
412 
413  filename[0] = 0;
414  strcpy(filename, str);
415 
416  while (*str != '\0')
417  str++;
418  return str+1;
419 }
420 
421 static void SetUpAllProtect()
422 {
423  int i;
424  for(i = 0 ; i < numOfSegments ; i++)
425  {
426  struct MemorySegment *tmpSegment = memorySegments + i;
427  #ifdef PROTECTEDMEMORYDEBUG
428  printf("Protect from 0x%lx to 0x%lx.\n", tmpSegment->start, tmpSegment->end);
429  #endif
430 
431  if (-1 == mprotect(tmpSegment->start, (long) tmpSegment->end - (long) tmpSegment->start , PROT_READ))
432  perror("mprotect error");
433 
434  #ifdef PROTECTEDMEMORYDEBUG
435  printf("Finish to protect from 0x%lx to 0x%lx.\n", tmpSegment->start, tmpSegment->end);
436  #endif
437  }
438 }
439 
440 static void UnSetUpAllProtect()
441 {
442  int i;
443  for(i = 0 ; i < numOfSegments ; i++)
444  {
445  struct MemorySegment *tmpSegment = memorySegments + i;
446 
447  #ifdef PROTECTEDMEMORYDEBUG
448  printf("Remove protection from 0x%lx to 0x%lx.\n", tmpSegment->start, tmpSegment->end);
449  #endif
450 
451  if (-1 == mprotect(tmpSegment->start, (long) tmpSegment->end - (long) tmpSegment->start , PROT_READ | PROT_WRITE))
452  perror("mprotect error");
453  }
454 }
455 
456 #define MAXTHREADS 128
459 pid_t tracerpid;
460 
461 //main thread
462 void addThread()
463 {
464  numberOfThreads++;
467 }
468 
469 
470 //forward declaration of a function used here
471 void setuphandlers();
472 
473 //main thread
475 {
477  setuphandlers();
478 
479  if ((tracerpid = fork()) == 0) //child process
480  {
481  char processid[10240];
482  char tmptid[1024];
483  processid[0] = 0;
484  tmptid[0] = 0;
485  sprintf(tmptid, "%d", numberOfThreads);
486  strcat(processid, tmptid);
487  strcat(processid, " ");
488  int i;
489  for (i = 0; i < numberOfThreads; i++)
490  {
491  tmptid[0] = 0;
492  sprintf(tmptid, "%d", threads[i]);
493  strcat(processid, tmptid);
494  strcat(processid, " ");
495  }
496  execl("./memoryprotection/tracer", "./memoryprotection/tracer", application, processid, (char *)0);
497  exit(0);
498  }
499 
500 }
501 
502 //main thread
503 //There is only one worker thread allowed.
504 //This function is invoked after the worker thread exits.
506 {
508  close(outputFile);
509  assert(0 == raise(SIGUSR1));
510  printf("Before wait for child process: %d\n", tracerpid);
511  waitpid(tracerpid, NULL, 0);
512  printf("After wait for child process: %d\n", tracerpid);
513 }
514 
515 //worker thread
517 {
518  printf("waiting for the tracer\n");
519  while (isCalled == 0) usleep(100);
520  printf("the tracer ready\n");
521  assert(0 == raise(SIGUSR2));
522 }
523 
524 //worker thread
526 {
527  //move to main thread
528  // UnSetUpAllProtect();
529 
530  assert(0 == raise(SIGUSR1));
531  //For each thread, can not do this
532 }
533 
534 /*
535 void starttracermain()
536 {
537  // pid_t currentID = getpid();
538  pid_t currentID = gettid();
539  if (fork()== 0) //child process
540  {
541  char processid[1024];
542  processid[0] = 0;
543  sprintf(processid, "%d", currentID);
544  sleep(2);
545  execl("./tracer", "./tracer", processid, application, (char *)0);
546  exit(0);
547  }
548  sleep(5);
549 
550 }
551 
552 void starttracerother()
553 {
554  // pid_t currentID = getpid();
555  pid_t currentID = gettid();
556  if (fork()== 0) //child process
557  {
558  char processid[1024];
559  processid[0] = 0;
560  sprintf(processid, "%d", currentID);
561  sleep(2);
562  execl("./tracer", "./tracer", processid, application, processid, (char *)0);
563  exit(0);
564  }
565  sleep(5);
566 
567 }
568 */
569 
571 {
572  setuphandler0();
573  setuphandler1();
574  setuphandler2();
575 }
576 
577 static void setuphandler0()
578 {
579  struct sigaction sa;
580  sa.sa_sigaction = handler0;
581  sigfillset(&sa.sa_mask);
582  sa.sa_flags = SA_RESTART | SA_SIGINFO; /* Restart functions if
583  interrupted by handler */
584  if (sigaction(SIGUSR2, &sa, NULL) == -1)
585  perror("sigaction"); /* Handle error */;
586 }
587 
588 static void setuphandler1()
589 {
590  struct sigaction sa;
591  sa.sa_sigaction = handler1;
592  sigfillset(&sa.sa_mask);
593  sa.sa_flags = SA_RESTART | SA_SIGINFO; /* Restart functions if
594  interrupted by handler */
595  if (sigaction(SIGSEGV, &sa, NULL) == -1)
596  perror("sigaction"); /* Handle error */;
597 }
598 
599 static void setuphandler2()
600 {
601  struct sigaction sa;
602 
603  sa.sa_sigaction = handler2;
604  sigfillset(&sa.sa_mask);
605  sa.sa_flags = SA_RESTART | SA_SIGINFO; /* Restart functions if
606  interrupted by handler */
607  if (sigaction(SIGUSR1, &sa, NULL) == -1)
608  perror("sigaction"); /* Handle error */;
609 }
610 
int numberOfThreads
static void UnSetUpAllProtect()
static char application[1024]
static size_t pagesize
#define MAXTHREADS
void PhaseChange()
static void handler2(int, siginfo_t *, void *)
static void show_stackframe()
static int isCalled
static void setuphandler0()
static int readFile(char *filename, char *buf, int maxSize)
#define assert(x)
Definition: mymalloc.cc:1309
static G4ThreadLocal void * trace[100]
#define G4ThreadLocal
Definition: tls.hh:52
void BuildProtectedMemory(size_t totalHeap)
void * AllocateInProtectedHeap(size_t size)
static void setuphandler1()
static void setuphandler2()
static char * currentPosition
static int trace_size
void finishtracer()
static char * readhex(char *string, long *value)
static int outputFile
static char * readMapsLine(char *string, void **start, void **end, int *writable, char *filename)
static int phase
static void AllocateProtectedHeap(size_t totalSize, size_t pagesize)
void starttracer()
static void record_stackframe()
void addThread()
pid_t tracerpid
static void handler0(int, siginfo_t *, void *)
static char * nextPosition
void FinishDetection()
static void SetUpAllProtect()
static void handler1(int, siginfo_t *, void *)
void setuphandlers()
static pid_t gettid()
static char * endPosition
static void * getPageNumber(void *theAddress)
static char * startPosition
void * malloc(size_t __size)
Definition: hjmalloc.cc:30
static int logpagesize
pid_t threads[MAXTHREADS]
void StartDetection()