Home | History | Annotate | Download | only in tests
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Same as test_relro_sharing.cpp, but uses two libraries at the same
      6 // time (libfoo_with_relro.so and libbar_with_relro.so), each one of
      7 // them gets its own shared RELRO.
      8 
      9 #include <errno.h>
     10 #include <pthread.h>
     11 #include <stdarg.h>
     12 #include <stdio.h>
     13 #include <stdlib.h>
     14 #include <sys/socket.h>
     15 #include <sys/uio.h>
     16 #include <sys/wait.h>
     17 #include <unistd.h>
     18 
     19 #include <crazy_linker.h>
     20 
     21 #include "test_util.h"
     22 
     23 typedef void (*FunctionPtr)();
     24 
     25 int main() {
     26 
     27   if (!crazy_system_can_share_relro()) {
     28     fprintf(stderr, "WARNING: Test ignored due to broken kernel!!\n");
     29     return 0;
     30   }
     31 
     32   crazy_context_t* context = crazy_context_create();
     33 
     34   RelroLibrary foo;
     35   RelroLibrary bar;
     36 
     37   crazy_context_add_search_path_for_address(context, (void*)&main);
     38 
     39   // Load libfoo_with_relro.so
     40   crazy_context_set_load_address(context, 0x20000000);
     41   foo.Init("libfoo_with_relro.so", context);
     42 
     43   crazy_context_set_load_address(context, 0x20800000);
     44   bar.Init("libbar_with_relro.so", context);
     45 
     46   printf("Libraries loaded\n");
     47 
     48   int pipes[2];
     49   if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipes) < 0)
     50     Panic("Could not create socket pair: %s", strerror(errno));
     51 
     52   pid_t child = fork();
     53   if (child < 0)
     54     Panic("Could not fork test program!");
     55 
     56   if (child == 0) {
     57     // In the child.
     58     printf("Child waiting for foo relro fd\n");
     59 
     60     foo.ReceiveRelroInfo(pipes[0]);
     61     foo.UseSharedRelro(context);
     62 
     63     printf("Child waiting for bar relro fd\n");
     64     bar.ReceiveRelroInfo(pipes[0]);
     65     bar.UseSharedRelro(context);
     66 
     67     printf("RELROs used in child process\n");
     68 
     69     CheckRelroMaps(2);
     70 
     71     FunctionPtr bar_func;
     72     if (!crazy_library_find_symbol(
     73              bar.library, "Bar", reinterpret_cast<void**>(&bar_func)))
     74       Panic("Could not find 'Bar' in library");
     75 
     76     printf("Calling Bar()\n");
     77     (*bar_func)();
     78 
     79     printf("Bar() called, exiting\n");
     80 
     81     exit(0);
     82 
     83   } else {
     84     // In the parent.
     85 
     86     printf("Parent enabling foo RELRO sharing\n");
     87 
     88     foo.EnableSharedRelro(context);
     89     foo.SendRelroInfo(pipes[1]);
     90 
     91     printf("Parent enabling bar RELRO sharing\n");
     92 
     93     bar.EnableSharedRelro(context);
     94     bar.SendRelroInfo(pipes[1]);
     95 
     96     printf("RELROs enabled and sent to child\n");
     97 
     98     CheckRelroMaps(2);
     99 
    100     printf("Parent waiting for child\n");
    101 
    102     // Wait for child to complete.
    103     int status;
    104     waitpid(child, &status, 0);
    105 
    106     if (WIFSIGNALED(status))
    107       Panic("Child terminated by signal!!\n");
    108     else if (WIFEXITED(status)) {
    109       int child_status = WEXITSTATUS(status);
    110       if (child_status != 0)
    111         Panic("Child terminated with status=%d\n", child_status);
    112     } else
    113       Panic("Child exited for unknown reason!!\n");
    114   }
    115 
    116   printf("Closing libraries\n");
    117   bar.Close();
    118   foo.Close();
    119 
    120   crazy_context_destroy(context);
    121   return 0;
    122 }
    123