symbian-qemu-0.9.1-12/qemu-symbian-svp/bsd-user/bsdload.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /* Code for loading BSD executables.  Mostly linux kernel code.  */
       
     2 
       
     3 #include <sys/types.h>
       
     4 #include <sys/stat.h>
       
     5 #include <fcntl.h>
       
     6 #include <errno.h>
       
     7 #include <unistd.h>
       
     8 #include <stdio.h>
       
     9 #include <stdlib.h>
       
    10 
       
    11 #include "qemu.h"
       
    12 
       
    13 #define NGROUPS 32
       
    14 
       
    15 /* ??? This should really be somewhere else.  */
       
    16 abi_long memcpy_to_target(abi_ulong dest, const void *src,
       
    17                           unsigned long len)
       
    18 {
       
    19     void *host_ptr;
       
    20 
       
    21     host_ptr = lock_user(VERIFY_WRITE, dest, len, 0);
       
    22     if (!host_ptr)
       
    23         return -TARGET_EFAULT;
       
    24     memcpy(host_ptr, src, len);
       
    25     unlock_user(host_ptr, dest, 1);
       
    26     return 0;
       
    27 }
       
    28 
       
    29 static int in_group_p(gid_t g)
       
    30 {
       
    31     /* return TRUE if we're in the specified group, FALSE otherwise */
       
    32     int         ngroup;
       
    33     int         i;
       
    34     gid_t       grouplist[NGROUPS];
       
    35 
       
    36     ngroup = getgroups(NGROUPS, grouplist);
       
    37     for(i = 0; i < ngroup; i++) {
       
    38         if(grouplist[i] == g) {
       
    39             return 1;
       
    40         }
       
    41     }
       
    42     return 0;
       
    43 }
       
    44 
       
    45 static int count(char ** vec)
       
    46 {
       
    47     int         i;
       
    48 
       
    49     for(i = 0; *vec; i++) {
       
    50         vec++;
       
    51     }
       
    52 
       
    53     return(i);
       
    54 }
       
    55 
       
    56 static int prepare_binprm(struct linux_binprm *bprm)
       
    57 {
       
    58     struct stat         st;
       
    59     int mode;
       
    60     int retval, id_change;
       
    61 
       
    62     if(fstat(bprm->fd, &st) < 0) {
       
    63         return(-errno);
       
    64     }
       
    65 
       
    66     mode = st.st_mode;
       
    67     if(!S_ISREG(mode)) {        /* Must be regular file */
       
    68         return(-EACCES);
       
    69     }
       
    70     if(!(mode & 0111)) {        /* Must have at least one execute bit set */
       
    71         return(-EACCES);
       
    72     }
       
    73 
       
    74     bprm->e_uid = geteuid();
       
    75     bprm->e_gid = getegid();
       
    76     id_change = 0;
       
    77 
       
    78     /* Set-uid? */
       
    79     if(mode & S_ISUID) {
       
    80         bprm->e_uid = st.st_uid;
       
    81         if(bprm->e_uid != geteuid()) {
       
    82             id_change = 1;
       
    83         }
       
    84     }
       
    85 
       
    86     /* Set-gid? */
       
    87     /*
       
    88      * If setgid is set but no group execute bit then this
       
    89      * is a candidate for mandatory locking, not a setgid
       
    90      * executable.
       
    91      */
       
    92     if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
       
    93         bprm->e_gid = st.st_gid;
       
    94         if (!in_group_p(bprm->e_gid)) {
       
    95                 id_change = 1;
       
    96         }
       
    97     }
       
    98 
       
    99     memset(bprm->buf, 0, sizeof(bprm->buf));
       
   100     retval = lseek(bprm->fd, 0L, SEEK_SET);
       
   101     if(retval >= 0) {
       
   102         retval = read(bprm->fd, bprm->buf, 128);
       
   103     }
       
   104     if(retval < 0) {
       
   105         perror("prepare_binprm");
       
   106         exit(-1);
       
   107         /* return(-errno); */
       
   108     }
       
   109     else {
       
   110         return(retval);
       
   111     }
       
   112 }
       
   113 
       
   114 /* Construct the envp and argv tables on the target stack.  */
       
   115 abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
       
   116                               abi_ulong stringp, int push_ptr)
       
   117 {
       
   118     int n = sizeof(abi_ulong);
       
   119     abi_ulong envp;
       
   120     abi_ulong argv;
       
   121 
       
   122     sp -= (envc + 1) * n;
       
   123     envp = sp;
       
   124     sp -= (argc + 1) * n;
       
   125     argv = sp;
       
   126     if (push_ptr) {
       
   127         /* FIXME - handle put_user() failures */
       
   128         sp -= n;
       
   129         put_user_ual(envp, sp);
       
   130         sp -= n;
       
   131         put_user_ual(argv, sp);
       
   132     }
       
   133     sp -= n;
       
   134     /* FIXME - handle put_user() failures */
       
   135     put_user_ual(argc, sp);
       
   136 
       
   137     while (argc-- > 0) {
       
   138         /* FIXME - handle put_user() failures */
       
   139         put_user_ual(stringp, argv);
       
   140         argv += n;
       
   141         stringp += target_strlen(stringp) + 1;
       
   142     }
       
   143     /* FIXME - handle put_user() failures */
       
   144     put_user_ual(0, argv);
       
   145     while (envc-- > 0) {
       
   146         /* FIXME - handle put_user() failures */
       
   147         put_user_ual(stringp, envp);
       
   148         envp += n;
       
   149         stringp += target_strlen(stringp) + 1;
       
   150     }
       
   151     /* FIXME - handle put_user() failures */
       
   152     put_user_ual(0, envp);
       
   153 
       
   154     return sp;
       
   155 }
       
   156 
       
   157 int loader_exec(const char * filename, char ** argv, char ** envp,
       
   158              struct target_pt_regs * regs, struct image_info *infop)
       
   159 {
       
   160     struct linux_binprm bprm;
       
   161     int retval;
       
   162     int i;
       
   163 
       
   164     bprm.p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
       
   165     for (i=0 ; i<MAX_ARG_PAGES ; i++)       /* clear page-table */
       
   166             bprm.page[i] = 0;
       
   167     retval = open(filename, O_RDONLY);
       
   168     if (retval < 0)
       
   169         return retval;
       
   170     bprm.fd = retval;
       
   171     bprm.filename = (char *)filename;
       
   172     bprm.argc = count(argv);
       
   173     bprm.argv = argv;
       
   174     bprm.envc = count(envp);
       
   175     bprm.envp = envp;
       
   176 
       
   177     retval = prepare_binprm(&bprm);
       
   178 
       
   179     infop->host_argv = argv;
       
   180 
       
   181     if(retval>=0) {
       
   182         if (bprm.buf[0] == 0x7f
       
   183                 && bprm.buf[1] == 'E'
       
   184                 && bprm.buf[2] == 'L'
       
   185                 && bprm.buf[3] == 'F') {
       
   186             retval = load_elf_binary(&bprm,regs,infop);
       
   187         } else {
       
   188             fprintf(stderr, "Unknown binary format\n");
       
   189             return -1;
       
   190         }
       
   191     }
       
   192 
       
   193     if(retval>=0) {
       
   194         /* success.  Initialize important registers */
       
   195         do_init_thread(regs, infop);
       
   196         return retval;
       
   197     }
       
   198 
       
   199     /* Something went wrong, return the inode and free the argument pages*/
       
   200     for (i=0 ; i<MAX_ARG_PAGES ; i++) {
       
   201         free(bprm.page[i]);
       
   202     }
       
   203     return(retval);
       
   204 }