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// A crazy linker test to: 6// - Load a library (libfoo.so) with the linker. 7// - Find the address of the "Foo" function in it. 8// - Call the function. 9// - Close the library. 10 11#include <errno.h> 12#include <stdarg.h> 13#include <stdio.h> 14#include <stdlib.h> 15#include <sys/socket.h> 16#include <sys/uio.h> 17#include <sys/wait.h> 18#include <unistd.h> 19 20#include <crazy_linker.h> 21 22#include "test_util.h" 23 24typedef void (*FunctionPtr)(); 25 26int main() { 27 28 if (!crazy_system_can_share_relro()) { 29 fprintf(stderr, "WARNING: Test ignored due to broken kernel!!\n"); 30 return 0; 31 } 32 33 crazy_context_t* context = crazy_context_create(); 34 35 RelroLibrary foo; 36 37 // Load at fixed address to simplify testing. 38 crazy_context_set_load_address(context, 0x20000000); 39 foo.Init("libfoo_with_relro.so", context); 40 41 printf("Library loaded\n"); 42 43 int pipes[2]; 44 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipes) < 0) 45 Panic("Could not create socket pair: %s", strerror(errno)); 46 47 pid_t child = fork(); 48 if (child < 0) 49 Panic("Could not fork test program!"); 50 51 if (child == 0) { 52 // In the child. 53 printf("Child waiting for foo relro fd\n"); 54 55 foo.ReceiveRelroInfo(pipes[0]); 56 foo.UseSharedRelro(context); 57 58 printf("RELRO used in child process\n"); 59 60 CheckRelroMaps(1); 61 62 FunctionPtr foo_func; 63 if (!crazy_library_find_symbol( 64 foo.library, "Foo", reinterpret_cast<void**>(&foo_func))) 65 Panic("Could not find 'Foo' in library"); 66 67 printf("Calling Foo()\n"); 68 (*foo_func)(); 69 70 printf("Foo called, exiting\n"); 71 72 exit(0); 73 74 } else { 75 // In the parent. 76 77 printf("Parent enabling foo RELRO sharing\n"); 78 79 foo.EnableSharedRelro(context); 80 foo.SendRelroInfo(pipes[1]); 81 82 printf("RELRO enabled and sent to child\n"); 83 84 CheckRelroMaps(1); 85 86 printf("Parent waiting for child\n"); 87 88 // Wait for child to complete. 89 int status; 90 waitpid(child, &status, 0); 91 92 if (WIFSIGNALED(status)) 93 Panic("Child terminated by signal!!\n"); 94 else if (WIFEXITED(status)) { 95 int child_status = WEXITSTATUS(status); 96 if (child_status != 0) 97 Panic("Child terminated with status=%d\n", child_status); 98 } else 99 Panic("Child exited for unknown reason!!\n"); 100 } 101 102 crazy_context_destroy(context); 103 return 0; 104} 105