cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

linuxload.c (4139B)


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