This source file includes following definitions.
- padzero
- load_elf_binary
- load_elf_library
1
2
3
4 #include <linux/fs.h>
5 #include <linux/sched.h>
6 #include <linux/mm.h>
7 #include <linux/mman.h>
8 #include <linux/a.out.h>
9 #include <linux/errno.h>
10 #include <linux/signal.h>
11 #include <linux/binfmts.h>
12 #include <linux/string.h>
13 #include <linux/fcntl.h>
14 #include <linux/ptrace.h>
15 #include <linux/malloc.h>
16
17 #include <asm/segment.h>
18
19 asmlinkage int sys_exit(int exit_code);
20 asmlinkage int sys_close(unsigned fd);
21 asmlinkage int sys_open(const char *, int, int);
22 asmlinkage int sys_brk(unsigned long);
23
24 #include <linux/elf.h>
25
26
27
28
29
30
31 static void padzero(int elf_bss){
32 unsigned int fpnt, nbyte;
33
34 if(elf_bss & 0xfff) {
35
36 nbyte = (PAGE_SIZE - (elf_bss & 0xfff)) & 0xfff;
37 if(nbyte){
38 verify_area(VERIFY_WRITE, (void *) elf_bss, nbyte);
39
40 fpnt = elf_bss;
41 while(fpnt & 0xfff) put_fs_byte(0, fpnt++);
42 };
43 };
44 }
45
46
47
48
49
50
51 int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
52 {
53 struct elfhdr elf_ex;
54 struct file * file;
55 struct exec ex;
56 struct inode *interpreter_inode;
57 int i;
58 int old_fs;
59 int error;
60 struct elf_phdr * elf_ppnt, *elf_phdata;
61 int elf_exec_fileno;
62 unsigned int elf_bss, k, elf_brk;
63 int retval;
64 char * elf_interpreter;
65 unsigned int elf_entry;
66 int status;
67 unsigned int start_code, end_code, end_data;
68 unsigned int elf_stack;
69 char passed_fileno[6];
70
71 status = 0;
72 elf_ex = *((struct elfhdr *) bprm->buf);
73
74 if (elf_ex.e_ident[0] != 0x7f ||
75 strncmp(&elf_ex.e_ident[1], "ELF",3) != 0)
76 return -ENOEXEC;
77
78
79
80 if(elf_ex.e_type != ET_EXEC ||
81 (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
82 (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops ||
83 !bprm->inode->i_op->default_file_ops->mmap)){
84 return -ENOEXEC;
85 };
86
87
88
89 elf_phdata = (struct elf_phdr *) kmalloc(elf_ex.e_phentsize *
90 elf_ex.e_phnum, GFP_KERNEL);
91
92 old_fs = get_fs();
93 set_fs(get_ds());
94 retval = read_exec(bprm->inode, elf_ex.e_phoff, (char *) elf_phdata,
95 elf_ex.e_phentsize * elf_ex.e_phnum);
96 set_fs(old_fs);
97 if (retval < 0) {
98 kfree (elf_phdata);
99 return retval;
100 }
101
102 elf_ppnt = elf_phdata;
103
104 elf_bss = 0;
105 elf_brk = 0;
106
107 elf_exec_fileno = open_inode(bprm->inode, O_RDONLY);
108
109 if (elf_exec_fileno < 0) {
110 kfree (elf_phdata);
111 return elf_exec_fileno;
112 }
113
114 file = current->filp[elf_exec_fileno];
115
116 elf_stack = 0xffffffff;
117 elf_interpreter = NULL;
118 start_code = 0;
119 end_code = 0;
120 end_data = 0;
121
122 old_fs = get_fs();
123 set_fs(get_ds());
124
125 for(i=0;i < elf_ex.e_phnum; i++){
126 if(elf_ppnt->p_type == PT_INTERP) {
127
128
129
130 elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz,
131 GFP_KERNEL);
132
133 retval = read_exec(bprm->inode,elf_ppnt->p_offset,elf_interpreter,
134 elf_ppnt->p_filesz);
135 #if 0
136 printk("Using ELF interpreter %s\n", elf_interpreter);
137 #endif
138 if(retval >= 0)
139 retval = namei(elf_interpreter, &interpreter_inode);
140 if(retval >= 0)
141 retval = read_exec(interpreter_inode,0,bprm->buf,128);
142
143 if(retval >= 0){
144 ex = *((struct exec *) bprm->buf);
145
146 #if 0
147 printk("Interpreter: %x %x %x\n",N_MAGIC(ex), ex.a_text,ex.a_data);
148 #endif
149 };
150 };
151 elf_ppnt++;
152 };
153
154 set_fs(old_fs);
155
156
157 if(elf_interpreter){
158 if(retval < 0) {
159 kfree(elf_interpreter);
160 kfree(elf_phdata);
161 return -ELIBACC;
162 };
163 if((N_MAGIC(ex) != OMAGIC) && (N_MAGIC(ex) != ZMAGIC)) {
164 kfree(elf_interpreter);
165 kfree(elf_phdata);
166 return -ELIBBAD;
167 };
168 }
169
170
171
172
173 if (!bprm->sh_bang) {
174 char * passed_p;
175
176 sprintf(passed_fileno, "%d", elf_exec_fileno);
177 passed_p = passed_fileno;
178
179 if(elf_interpreter) {
180 bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p,2);
181 bprm->argc++;
182 };
183 if (!bprm->p) {
184 if(elf_interpreter) {
185 kfree(elf_interpreter);
186 }
187 kfree (elf_phdata);
188 return -E2BIG;
189 }
190 }
191
192
193 flush_old_exec(bprm);
194
195 current->end_data = 0;
196 current->end_code = 0;
197 current->start_mmap = ELF_START_MMAP;
198 current->mmap = NULL;
199 elf_entry = (unsigned int) elf_ex.e_entry;
200
201
202
203 current->rss = 0;
204 bprm->p += change_ldt(0, bprm->page);
205 current->start_stack = bprm->p;
206
207
208
209
210
211
212 old_fs = get_fs();
213 set_fs(get_ds());
214
215 elf_ppnt = elf_phdata;
216 for(i=0;i < elf_ex.e_phnum; i++){
217
218 if(elf_ppnt->p_type == PT_INTERP) {
219
220 current->brk = ex.a_bss +
221 (current->end_data = ex.a_data +
222 (current->end_code = ex.a_text));
223 elf_entry = ex.a_entry;
224
225
226 set_fs(old_fs);
227
228 if (N_MAGIC(ex) == OMAGIC) {
229 do_mmap(NULL, 0, ex.a_text+ex.a_data,
230 PROT_READ|PROT_WRITE|PROT_EXEC,
231 MAP_FIXED|MAP_PRIVATE, 0);
232 retval = read_exec(interpreter_inode, 32, (char *) 0,
233 ex.a_text+ex.a_data);
234 iput(interpreter_inode);
235 } else if (N_MAGIC(ex) == ZMAGIC || N_MAGIC(ex) == QMAGIC) {
236 do_mmap(NULL, 0, ex.a_text+ex.a_data,
237 PROT_READ|PROT_WRITE|PROT_EXEC,
238 MAP_FIXED|MAP_PRIVATE, 0);
239 retval = read_exec(interpreter_inode,
240 N_TXTOFF(ex) ,
241 (char *) N_TXTADDR(ex),
242 ex.a_text+ex.a_data);
243 iput(interpreter_inode);
244 } else
245 retval = -1;
246
247 old_fs = get_fs();
248 set_fs(get_ds());
249
250 if(retval >= 0)
251 do_mmap(NULL, (ex.a_text + ex.a_data + 0xfff) &
252 0xfffff000, ex.a_bss,
253 PROT_READ|PROT_WRITE|PROT_EXEC,
254 MAP_FIXED|MAP_PRIVATE, 0);
255
256 kfree(elf_interpreter);
257
258 if(retval < 0) {
259 kfree(elf_phdata);
260 send_sig(SIGSEGV, current, 0);
261 return 0;
262 };
263 };
264
265
266 if(elf_ppnt->p_type == PT_LOAD) {
267 error = do_mmap(file,
268 elf_ppnt->p_vaddr & 0xfffff000,
269 elf_ppnt->p_filesz + (elf_ppnt->p_vaddr & 0xfff),
270 PROT_READ | PROT_WRITE | PROT_EXEC,
271 MAP_FIXED | MAP_PRIVATE,
272 elf_ppnt->p_offset & 0xfffff000);
273
274 #ifdef LOW_ELF_STACK
275 if(elf_ppnt->p_vaddr & 0xfffff000 < elf_stack)
276 elf_stack = elf_ppnt->p_vaddr & 0xfffff000;
277 #endif
278
279 k = elf_ppnt->p_vaddr;
280 if(k > start_code) start_code = k;
281 k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
282 if(k > elf_bss) elf_bss = k;
283 if((elf_ppnt->p_flags | PROT_WRITE) && end_code < k)
284 end_code = k;
285 if(end_data < k) end_data = k;
286 k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
287 if(k > elf_brk) elf_brk = k;
288
289 if(status == 0xffffffff) {
290 set_fs(old_fs);
291 kfree(elf_phdata);
292 send_sig(SIGSEGV, current, 0);
293 return 0;
294 };
295 };
296 elf_ppnt++;
297 };
298 set_fs(old_fs);
299
300 kfree(elf_phdata);
301
302 if(!elf_interpreter) sys_close(elf_exec_fileno);
303 current->elf_executable = 1;
304 current->executable = bprm->inode;
305 bprm->inode->i_count++;
306 #ifdef LOW_ELF_STACK
307 current->start_stack = p = elf_stack - 4;
308 #endif
309 bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
310 bprm->p = (unsigned long) create_tables((char *)bprm->p,bprm->argc,bprm->envc,0);
311 if(elf_interpreter) current->arg_start += strlen(passed_fileno) + 1;
312 current->start_brk = current->brk = elf_brk;
313 current->end_code = end_code;
314 current->start_code = start_code;
315 current->end_data = end_data;
316 current->start_stack = bprm->p;
317 current->suid = current->euid = bprm->e_uid;
318 current->sgid = current->egid = bprm->e_gid;
319
320
321
322 current->brk = (elf_bss + 0xfff) & 0xfffff000;
323 sys_brk((elf_brk + 0xfff) & 0xfffff000);
324
325 padzero(elf_bss);
326
327 regs->eip = elf_entry;
328 regs->esp = bprm->p;
329 if (current->flags & PF_PTRACED)
330 send_sig(SIGTRAP, current, 0);
331 return 0;
332 }
333
334
335
336
337 int load_elf_library(int fd){
338 struct file * file;
339 struct elfhdr elf_ex;
340 struct elf_phdr *elf_phdata = NULL;
341 struct inode * inode;
342 unsigned int len;
343 int elf_bss;
344 int old_fs, retval;
345 unsigned int bss;
346 int error;
347 int i,j, k;
348
349 len = 0;
350 file = current->filp[fd];
351 inode = file->f_inode;
352 elf_bss = 0;
353
354 set_fs(KERNEL_DS);
355 if (file->f_op->read(inode, file, (char *) &elf_ex, sizeof(elf_ex)) != sizeof(elf_ex)) {
356 sys_close(fd);
357 return -EACCES;
358 }
359 set_fs(USER_DS);
360
361 if (elf_ex.e_ident[0] != 0x7f ||
362 strncmp(&elf_ex.e_ident[1], "ELF",3) != 0)
363 return -ENOEXEC;
364
365
366 if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
367 (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
368 (!inode->i_op || !inode->i_op->bmap ||
369 !inode->i_op->default_file_ops->mmap)){
370 return -ENOEXEC;
371 };
372
373
374
375 if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE)
376 return -ENOEXEC;
377
378 elf_phdata = (struct elf_phdr *)
379 kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL);
380
381 old_fs = get_fs();
382 set_fs(get_ds());
383 retval = read_exec(inode, elf_ex.e_phoff, (char *) elf_phdata,
384 sizeof(struct elf_phdr) * elf_ex.e_phnum);
385 set_fs(old_fs);
386
387 j = 0;
388 for(i=0; i<elf_ex.e_phnum; i++)
389 if((elf_phdata + i)->p_type == PT_LOAD) j++;
390
391 if(j != 1) {
392 kfree(elf_phdata);
393 return -ENOEXEC;
394 };
395
396 while(elf_phdata->p_type != PT_LOAD) elf_phdata++;
397
398
399 error = do_mmap(file,
400 elf_phdata->p_vaddr & 0xfffff000,
401 elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff),
402 PROT_READ | PROT_WRITE | PROT_EXEC,
403 MAP_FIXED | MAP_PRIVATE,
404 elf_phdata->p_offset & 0xfffff000);
405
406 k = elf_phdata->p_vaddr + elf_phdata->p_filesz;
407 if(k > elf_bss) elf_bss = k;
408
409 sys_close(fd);
410 if (error != elf_phdata->p_vaddr & 0xfffff000) {
411 kfree(elf_phdata);
412 return error;
413 }
414
415 padzero(elf_bss);
416
417 len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000;
418 bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
419 if (bss > len)
420 do_mmap(NULL, len, bss-len,
421 PROT_READ|PROT_WRITE|PROT_EXEC,
422 MAP_FIXED|MAP_PRIVATE, 0);
423 kfree(elf_phdata);
424 return 0;
425 }