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