qemu/bsd-user/bsdload.c
<<
>>
Prefs
   1/* Code for loading BSD executables.  Mostly linux kernel code.  */
   2
   3#include "qemu/osdep.h"
   4
   5#include "qemu.h"
   6
   7#define TARGET_NGROUPS 32
   8
   9/* ??? This should really be somewhere else.  */
  10abi_long memcpy_to_target(abi_ulong dest, const void *src,
  11                          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    memcpy(host_ptr, src, len);
  19    unlock_user(host_ptr, dest, 1);
  20    return 0;
  21}
  22
  23static int count(char ** vec)
  24{
  25    int         i;
  26
  27    for(i = 0; *vec; i++) {
  28        vec++;
  29    }
  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    memset(bprm->buf, 0, sizeof(bprm->buf));
  71    retval = lseek(bprm->fd, 0L, SEEK_SET);
  72    if(retval >= 0) {
  73        retval = read(bprm->fd, bprm->buf, 128);
  74    }
  75    if(retval < 0) {
  76        perror("prepare_binprm");
  77        exit(-1);
  78        /* return(-errno); */
  79    }
  80    else {
  81        return(retval);
  82    }
  83}
  84
  85/* Construct the envp and argv tables on the target stack.  */
  86abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
  87                              abi_ulong stringp, int push_ptr)
  88{
  89    int n = sizeof(abi_ulong);
  90    abi_ulong envp;
  91    abi_ulong argv;
  92
  93    sp -= (envc + 1) * n;
  94    envp = sp;
  95    sp -= (argc + 1) * n;
  96    argv = sp;
  97    if (push_ptr) {
  98        /* FIXME - handle put_user() failures */
  99        sp -= n;
 100        put_user_ual(envp, sp);
 101        sp -= n;
 102        put_user_ual(argv, sp);
 103    }
 104    sp -= n;
 105    /* FIXME - handle put_user() failures */
 106    put_user_ual(argc, sp);
 107
 108    while (argc-- > 0) {
 109        /* FIXME - handle put_user() failures */
 110        put_user_ual(stringp, argv);
 111        argv += n;
 112        stringp += target_strlen(stringp) + 1;
 113    }
 114    /* FIXME - handle put_user() failures */
 115    put_user_ual(0, argv);
 116    while (envc-- > 0) {
 117        /* FIXME - handle put_user() failures */
 118        put_user_ual(stringp, envp);
 119        envp += n;
 120        stringp += target_strlen(stringp) + 1;
 121    }
 122    /* FIXME - handle put_user() failures */
 123    put_user_ual(0, envp);
 124
 125    return sp;
 126}
 127
 128int loader_exec(const char * filename, char ** argv, char ** envp,
 129             struct target_pt_regs * regs, struct image_info *infop)
 130{
 131    struct linux_binprm bprm;
 132    int retval;
 133    int i;
 134
 135    bprm.p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
 136    for (i=0 ; i<MAX_ARG_PAGES ; i++)       /* clear page-table */
 137            bprm.page[i] = NULL;
 138    retval = open(filename, O_RDONLY);
 139    if (retval < 0)
 140        return retval;
 141    bprm.fd = retval;
 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,regs,infop);
 156        } else {
 157            fprintf(stderr, "Unknown binary format\n");
 158            return -1;
 159        }
 160    }
 161
 162    if(retval>=0) {
 163        /* success.  Initialize important registers */
 164        do_init_thread(regs, infop);
 165        return retval;
 166    }
 167
 168    /* Something went wrong, return the inode and free the argument pages*/
 169    for (i=0 ; i<MAX_ARG_PAGES ; i++) {
 170        g_free(bprm.page[i]);
 171    }
 172    return(retval);
 173}
 174