qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

linuxload.c (4257B)


      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.  */
     11 abi_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 
     24 static int count(char **vec)
     25 {
     26     int i;
     27 
     28     for (i = 0; *vec; i++) {
     29         vec++;
     30     }
     31     return i;
     32 }
     33 
     34 static 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.  */
     83 abi_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     ts->info->envp = envp;
     96     ts->info->envc = envc;
     97     ts->info->argv = argv;
     98     ts->info->argc = argc;
     99 
    100     if (push_ptr) {
    101         /* FIXME - handle put_user() failures */
    102         sp -= n;
    103         put_user_ual(envp, sp);
    104         sp -= n;
    105         put_user_ual(argv, sp);
    106     }
    107 
    108     sp -= n;
    109     /* FIXME - handle put_user() failures */
    110     put_user_ual(argc, sp);
    111 
    112     ts->info->arg_strings = stringp;
    113     while (argc-- > 0) {
    114         /* FIXME - handle put_user() failures */
    115         put_user_ual(stringp, argv);
    116         argv += n;
    117         stringp += target_strlen(stringp) + 1;
    118     }
    119     /* FIXME - handle put_user() failures */
    120     put_user_ual(0, argv);
    121 
    122     ts->info->env_strings = stringp;
    123     while (envc-- > 0) {
    124         /* FIXME - handle put_user() failures */
    125         put_user_ual(stringp, envp);
    126         envp += n;
    127         stringp += target_strlen(stringp) + 1;
    128     }
    129     /* FIXME - handle put_user() failures */
    130     put_user_ual(0, envp);
    131 
    132     return sp;
    133 }
    134 
    135 int loader_exec(int fdexec, const char *filename, char **argv, char **envp,
    136                 struct target_pt_regs *regs, struct image_info *infop,
    137                 struct linux_binprm *bprm)
    138 {
    139     int retval;
    140 
    141     bprm->fd = fdexec;
    142     bprm->filename = (char *)filename;
    143     bprm->argc = count(argv);
    144     bprm->argv = argv;
    145     bprm->envc = count(envp);
    146     bprm->envp = envp;
    147 
    148     retval = prepare_binprm(bprm);
    149 
    150     if (retval >= 0) {
    151         if (bprm->buf[0] == 0x7f
    152                 && bprm->buf[1] == 'E'
    153                 && bprm->buf[2] == 'L'
    154                 && bprm->buf[3] == 'F') {
    155             retval = load_elf_binary(bprm, infop);
    156 #if defined(TARGET_HAS_BFLT)
    157         } else if (bprm->buf[0] == 'b'
    158                 && bprm->buf[1] == 'F'
    159                 && bprm->buf[2] == 'L'
    160                 && bprm->buf[3] == 'T') {
    161             retval = load_flt_binary(bprm, infop);
    162 #endif
    163         } else {
    164             return -ENOEXEC;
    165         }
    166     }
    167 
    168     if (retval >= 0) {
    169         /* success.  Initialize important registers */
    170         do_init_thread(regs, infop);
    171         return retval;
    172     }
    173 
    174     return retval;
    175 }