linuxload.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /* Code for loading Linux executables. Mostly linux kernel code. */
  2. #include "qemu/osdep.h"
  3. #include "qemu.h"
  4. #include "user-internals.h"
  5. #include "loader.h"
  6. #define NGROUPS 32
  7. /* ??? This should really be somewhere else. */
  8. abi_long memcpy_to_target(abi_ulong dest, const void *src, unsigned long len)
  9. {
  10. void *host_ptr;
  11. host_ptr = lock_user(VERIFY_WRITE, dest, len, 0);
  12. if (!host_ptr) {
  13. return -TARGET_EFAULT;
  14. }
  15. memcpy(host_ptr, src, len);
  16. unlock_user(host_ptr, dest, 1);
  17. return 0;
  18. }
  19. static int count(char **vec)
  20. {
  21. int i;
  22. for (i = 0; *vec; i++) {
  23. vec++;
  24. }
  25. return i;
  26. }
  27. static int prepare_binprm(struct linux_binprm *bprm)
  28. {
  29. struct stat st;
  30. int mode;
  31. int retval;
  32. if (fstat(bprm->fd, &st) < 0) {
  33. return -errno;
  34. }
  35. mode = st.st_mode;
  36. if (!S_ISREG(mode)) { /* Must be regular file */
  37. return -EACCES;
  38. }
  39. if (!(mode & 0111)) { /* Must have at least one execute bit set */
  40. return -EACCES;
  41. }
  42. bprm->e_uid = geteuid();
  43. bprm->e_gid = getegid();
  44. /* Set-uid? */
  45. if (mode & S_ISUID) {
  46. bprm->e_uid = st.st_uid;
  47. }
  48. /* Set-gid? */
  49. /*
  50. * If setgid is set but no group execute bit then this
  51. * is a candidate for mandatory locking, not a setgid
  52. * executable.
  53. */
  54. if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
  55. bprm->e_gid = st.st_gid;
  56. }
  57. retval = read(bprm->fd, bprm->buf, BPRM_BUF_SIZE);
  58. if (retval < 0) {
  59. perror("prepare_binprm");
  60. exit(-1);
  61. }
  62. if (retval < BPRM_BUF_SIZE) {
  63. /* Make sure the rest of the loader won't read garbage. */
  64. memset(bprm->buf + retval, 0, BPRM_BUF_SIZE - retval);
  65. }
  66. return retval;
  67. }
  68. /* Construct the envp and argv tables on the target stack. */
  69. abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
  70. abi_ulong stringp, int push_ptr)
  71. {
  72. TaskState *ts = (TaskState *)thread_cpu->opaque;
  73. int n = sizeof(abi_ulong);
  74. abi_ulong envp;
  75. abi_ulong argv;
  76. sp -= (envc + 1) * n;
  77. envp = sp;
  78. sp -= (argc + 1) * n;
  79. argv = sp;
  80. ts->info->envp = envp;
  81. ts->info->envc = envc;
  82. ts->info->argv = argv;
  83. ts->info->argc = argc;
  84. if (push_ptr) {
  85. /* FIXME - handle put_user() failures */
  86. sp -= n;
  87. put_user_ual(envp, sp);
  88. sp -= n;
  89. put_user_ual(argv, sp);
  90. }
  91. sp -= n;
  92. /* FIXME - handle put_user() failures */
  93. put_user_ual(argc, sp);
  94. ts->info->arg_strings = stringp;
  95. while (argc-- > 0) {
  96. /* FIXME - handle put_user() failures */
  97. put_user_ual(stringp, argv);
  98. argv += n;
  99. stringp += target_strlen(stringp) + 1;
  100. }
  101. /* FIXME - handle put_user() failures */
  102. put_user_ual(0, argv);
  103. ts->info->env_strings = stringp;
  104. while (envc-- > 0) {
  105. /* FIXME - handle put_user() failures */
  106. put_user_ual(stringp, envp);
  107. envp += n;
  108. stringp += target_strlen(stringp) + 1;
  109. }
  110. /* FIXME - handle put_user() failures */
  111. put_user_ual(0, envp);
  112. return sp;
  113. }
  114. int loader_exec(int fdexec, const char *filename, char **argv, char **envp,
  115. struct target_pt_regs *regs, struct image_info *infop,
  116. struct linux_binprm *bprm)
  117. {
  118. int retval;
  119. bprm->fd = fdexec;
  120. bprm->filename = (char *)filename;
  121. bprm->argc = count(argv);
  122. bprm->argv = argv;
  123. bprm->envc = count(envp);
  124. bprm->envp = envp;
  125. retval = prepare_binprm(bprm);
  126. if (retval >= 0) {
  127. if (bprm->buf[0] == 0x7f
  128. && bprm->buf[1] == 'E'
  129. && bprm->buf[2] == 'L'
  130. && bprm->buf[3] == 'F') {
  131. retval = load_elf_binary(bprm, infop);
  132. #if defined(TARGET_HAS_BFLT)
  133. } else if (bprm->buf[0] == 'b'
  134. && bprm->buf[1] == 'F'
  135. && bprm->buf[2] == 'L'
  136. && bprm->buf[3] == 'T') {
  137. retval = load_flt_binary(bprm, infop);
  138. #endif
  139. } else {
  140. return -ENOEXEC;
  141. }
  142. }
  143. if (retval >= 0) {
  144. /* success. Initialize important registers */
  145. do_init_thread(regs, infop);
  146. return retval;
  147. }
  148. return retval;
  149. }