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