run_pie.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. //
  3. // Redistribution and use in source and binary forms, with or without
  4. // modification, are permitted provided that the following conditions are
  5. // met:
  6. //
  7. // * Redistributions of source code must retain the above copyright
  8. // notice, this list of conditions and the following disclaimer.
  9. // * Redistributions in binary form must reproduce the above
  10. // copyright notice, this list of conditions and the following disclaimer
  11. // in the documentation and/or other materials provided with the
  12. // distribution.
  13. // * Neither the name of Google Inc. nor the names of its
  14. // contributors may be used to endorse or promote products derived from
  15. // this software without specific prior written permission.
  16. //
  17. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  20. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  21. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  22. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  23. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  24. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  25. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  27. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. #include <dlfcn.h>
  29. #include <stdio.h>
  30. #include <string.h>
  31. #include <sys/prctl.h>
  32. #include <unistd.h>
  33. // This is a wrapper to run position independent executables on Android ICS,
  34. // where the linker doesn't support PIE. This requires the PIE binaries to be
  35. // built with CFLAGS +=-fvisibility=default -fPIE, and LDFLAGS += -rdynamic -pie
  36. // such that the main() symbol remains exported and can be dlsym-ed.
  37. #define ERR_PREFIX "[PIE Loader] "
  38. typedef int (*main_t)(int, char**);
  39. int main(int argc, char** argv) {
  40. if (argc < 2) {
  41. printf("Usage: %s path_to_pie_executable [args]\n", argv[0]);
  42. return -1;
  43. }
  44. // Shift left the argv[]. argv is what /proc/PID/cmdline prints out. In turn
  45. // cmdline is what Android "ps" prints out. In turn "ps" is what many scripts
  46. // look for to decide which processes to kill / killall.
  47. int i;
  48. char* next_argv_start = argv[0];
  49. for (i = 1; i < argc; ++i) {
  50. const size_t argv_len = strlen(argv[i]) + 1;
  51. memmove(argv[i - 1], argv[i], argv_len);
  52. next_argv_start += argv_len;
  53. argv[i] = next_argv_start;
  54. }
  55. argv[argc - 1] = NULL; // The last argv must be a NULL ptr.
  56. // Set also the proc name accordingly (/proc/PID/comm).
  57. prctl(PR_SET_NAME, (long) argv[0]);
  58. // dlopen should not fail, unless:
  59. // - The target binary does not exists:
  60. // - The dependent .so libs cannot be loaded.
  61. // In both cases, just bail out with an explicit error message.
  62. void* handle = dlopen(argv[0], RTLD_NOW);
  63. if (handle == NULL) {
  64. printf(ERR_PREFIX "dlopen() failed: %s.\n", dlerror());
  65. return -1;
  66. }
  67. main_t pie_main = (main_t) dlsym(handle, "main");
  68. if (pie_main) {
  69. return pie_main(argc - 1, argv);
  70. }
  71. // If we reached this point dlsym failed, very likely because the target
  72. // binary has not been compiled with the proper CFLAGS / LDFLAGS.
  73. // At this point the most sensible thing to do is running that normally
  74. // via exec and hope that the target binary wasn't a PIE.
  75. execv(argv[0], argv);
  76. // exevc is supposed to never return, unless it fails.
  77. printf(ERR_PREFIX "Both dlsym() and the execv() fallback failed.\n");
  78. perror("execv");
  79. return -1;
  80. }