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 
main()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