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