Statistics
| Branch: | Revision:

root / linux-user / linuxload.c @ 93148aa5

History | View | Annotate | Download (4.5 kB)

1
/* Code for loading Linux 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 count(char ** vec)
30
{
31
    int                i;
32

    
33
    for(i = 0; *vec; i++) {
34
        vec++;
35
    }
36

    
37
    return(i);
38
}
39

    
40
static int prepare_binprm(struct linux_binprm *bprm)
41
{
42
    struct stat                st;
43
    int mode;
44
    int retval;
45

    
46
    if(fstat(bprm->fd, &st) < 0) {
47
        return(-errno);
48
    }
49

    
50
    mode = st.st_mode;
51
    if(!S_ISREG(mode)) {        /* Must be regular file */
52
        return(-EACCES);
53
    }
54
    if(!(mode & 0111)) {        /* Must have at least one execute bit set */
55
        return(-EACCES);
56
    }
57

    
58
    bprm->e_uid = geteuid();
59
    bprm->e_gid = getegid();
60

    
61
    /* Set-uid? */
62
    if(mode & S_ISUID) {
63
            bprm->e_uid = st.st_uid;
64
    }
65

    
66
    /* Set-gid? */
67
    /*
68
     * If setgid is set but no group execute bit then this
69
     * is a candidate for mandatory locking, not a setgid
70
     * executable.
71
     */
72
    if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
73
        bprm->e_gid = st.st_gid;
74
    }
75

    
76
    retval = read(bprm->fd, bprm->buf, BPRM_BUF_SIZE);
77
    if (retval < 0) {
78
        perror("prepare_binprm");
79
        exit(-1);
80
    }
81
    if (retval < BPRM_BUF_SIZE) {
82
        /* Make sure the rest of the loader won't read garbage.  */
83
        memset(bprm->buf + retval, 0, BPRM_BUF_SIZE - retval);
84
    }
85
    return retval;
86
}
87

    
88
/* Construct the envp and argv tables on the target stack.  */
89
abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
90
                              abi_ulong stringp, int push_ptr)
91
{
92
    TaskState *ts = (TaskState *)thread_env->opaque;
93
    int n = sizeof(abi_ulong);
94
    abi_ulong envp;
95
    abi_ulong argv;
96

    
97
    sp -= (envc + 1) * n;
98
    envp = sp;
99
    sp -= (argc + 1) * n;
100
    argv = sp;
101
    if (push_ptr) {
102
        /* FIXME - handle put_user() failures */
103
        sp -= n;
104
        put_user_ual(envp, sp);
105
        sp -= n;
106
        put_user_ual(argv, sp);
107
    }
108
    sp -= n;
109
    /* FIXME - handle put_user() failures */
110
    put_user_ual(argc, sp);
111
    ts->info->arg_start = stringp;
112
    while (argc-- > 0) {
113
        /* FIXME - handle put_user() failures */
114
        put_user_ual(stringp, argv);
115
        argv += n;
116
        stringp += target_strlen(stringp) + 1;
117
    }
118
    ts->info->arg_end = stringp;
119
    /* FIXME - handle put_user() failures */
120
    put_user_ual(0, argv);
121
    while (envc-- > 0) {
122
        /* FIXME - handle put_user() failures */
123
        put_user_ual(stringp, envp);
124
        envp += n;
125
        stringp += target_strlen(stringp) + 1;
126
    }
127
    /* FIXME - handle put_user() failures */
128
    put_user_ual(0, envp);
129

    
130
    return sp;
131
}
132

    
133
int loader_exec(const char * filename, char ** argv, char ** envp,
134
             struct target_pt_regs * regs, struct image_info *infop,
135
             struct linux_binprm *bprm)
136
{
137
    int retval;
138
    int i;
139

    
140
    bprm->p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
141
    memset(bprm->page, 0, sizeof(bprm->page));
142
    retval = open(filename, O_RDONLY);
143
    if (retval < 0)
144
        return retval;
145
    bprm->fd = retval;
146
    bprm->filename = (char *)filename;
147
    bprm->argc = count(argv);
148
    bprm->argv = argv;
149
    bprm->envc = count(envp);
150
    bprm->envp = envp;
151

    
152
    retval = prepare_binprm(bprm);
153

    
154
    if(retval>=0) {
155
        if (bprm->buf[0] == 0x7f
156
                && bprm->buf[1] == 'E'
157
                && bprm->buf[2] == 'L'
158
                && bprm->buf[3] == 'F') {
159
            retval = load_elf_binary(bprm, regs, infop);
160
#if defined(TARGET_HAS_BFLT)
161
        } else if (bprm->buf[0] == 'b'
162
                && bprm->buf[1] == 'F'
163
                && bprm->buf[2] == 'L'
164
                && bprm->buf[3] == 'T') {
165
            retval = load_flt_binary(bprm,regs,infop);
166
#endif
167
        } else {
168
            fprintf(stderr, "Unknown binary format\n");
169
            return -1;
170
        }
171
    }
172

    
173
    if(retval>=0) {
174
        /* success.  Initialize important registers */
175
        do_init_thread(regs, infop);
176
        return retval;
177
    }
178

    
179
    /* Something went wrong, return the inode and free the argument pages*/
180
    for (i=0 ; i<MAX_ARG_PAGES ; i++) {
181
        g_free(bprm->page[i]);
182
    }
183
    return(retval);
184
}