]> git.proxmox.com Git - mirror_qemu.git/blob - linux-user/linuxload.c
0efbb76ce4a52799ea1a9d4592608061388d525f
[mirror_qemu.git] / linux-user / linuxload.c
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 void 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
26 static 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
42 static int count(char ** vec)
43 {
44 int i;
45
46 for(i = 0; *vec; i++) {
47 vec++;
48 }
49
50 return(i);
51 }
52
53 static 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. */
112 target_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
143 int loader_exec(const char * filename, char ** argv, char ** envp,
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
165 infop->host_argv = argv;
166
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 }
185
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 }