aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/binfmt_elf_fdpic.c305
1 files changed, 168 insertions, 137 deletions
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 07624b95aee6..a4ff87389823 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -1,6 +1,6 @@
1/* binfmt_elf_fdpic.c: FDPIC ELF binary format 1/* binfmt_elf_fdpic.c: FDPIC ELF binary format
2 * 2 *
3 * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2003, 2004, 2006 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
5 * Derived from binfmt_elf.c 5 * Derived from binfmt_elf.c
6 * 6 *
@@ -50,43 +50,45 @@ typedef char *elf_caddr_t;
50 50
51MODULE_LICENSE("GPL"); 51MODULE_LICENSE("GPL");
52 52
53static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs); 53static int load_elf_fdpic_binary(struct linux_binprm *, struct pt_regs *);
54//static int load_elf_fdpic_library(struct file *); 54static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *, struct file *);
55static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params, struct file *file); 55static int elf_fdpic_map_file(struct elf_fdpic_params *, struct file *,
56static int elf_fdpic_map_file(struct elf_fdpic_params *params, 56 struct mm_struct *, const char *);
57 struct file *file,
58 struct mm_struct *mm,
59 const char *what);
60 57
61static int create_elf_fdpic_tables(struct linux_binprm *bprm, 58static int create_elf_fdpic_tables(struct linux_binprm *, struct mm_struct *,
62 struct mm_struct *mm, 59 struct elf_fdpic_params *,
63 struct elf_fdpic_params *exec_params, 60 struct elf_fdpic_params *);
64 struct elf_fdpic_params *interp_params);
65 61
66#ifndef CONFIG_MMU 62#ifndef CONFIG_MMU
67static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *bprm, unsigned long *_sp); 63static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *,
68static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *params, 64 unsigned long *);
69 struct file *file, 65static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *,
70 struct mm_struct *mm); 66 struct file *,
67 struct mm_struct *);
71#endif 68#endif
72 69
73static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, 70static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *,
74 struct file *file, 71 struct file *, struct mm_struct *);
75 struct mm_struct *mm);
76 72
77static struct linux_binfmt elf_fdpic_format = { 73static struct linux_binfmt elf_fdpic_format = {
78 .module = THIS_MODULE, 74 .module = THIS_MODULE,
79 .load_binary = load_elf_fdpic_binary, 75 .load_binary = load_elf_fdpic_binary,
80// .load_shlib = load_elf_fdpic_library,
81// .core_dump = elf_fdpic_core_dump, 76// .core_dump = elf_fdpic_core_dump,
82 .min_coredump = ELF_EXEC_PAGESIZE, 77 .min_coredump = ELF_EXEC_PAGESIZE,
83}; 78};
84 79
85static int __init init_elf_fdpic_binfmt(void) { return register_binfmt(&elf_fdpic_format); } 80static int __init init_elf_fdpic_binfmt(void)
86static void __exit exit_elf_fdpic_binfmt(void) { unregister_binfmt(&elf_fdpic_format); } 81{
82 return register_binfmt(&elf_fdpic_format);
83}
87 84
88module_init(init_elf_fdpic_binfmt) 85static void __exit exit_elf_fdpic_binfmt(void)
89module_exit(exit_elf_fdpic_binfmt) 86{
87 unregister_binfmt(&elf_fdpic_format);
88}
89
90module_init(init_elf_fdpic_binfmt);
91module_exit(exit_elf_fdpic_binfmt);
90 92
91static int is_elf_fdpic(struct elfhdr *hdr, struct file *file) 93static int is_elf_fdpic(struct elfhdr *hdr, struct file *file)
92{ 94{
@@ -105,7 +107,8 @@ static int is_elf_fdpic(struct elfhdr *hdr, struct file *file)
105/* 107/*
106 * read the program headers table into memory 108 * read the program headers table into memory
107 */ 109 */
108static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params, struct file *file) 110static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params,
111 struct file *file)
109{ 112{
110 struct elf32_phdr *phdr; 113 struct elf32_phdr *phdr;
111 unsigned long size; 114 unsigned long size;
@@ -121,7 +124,8 @@ static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params, struct file *f
121 if (!params->phdrs) 124 if (!params->phdrs)
122 return -ENOMEM; 125 return -ENOMEM;
123 126
124 retval = kernel_read(file, params->hdr.e_phoff, (char *) params->phdrs, size); 127 retval = kernel_read(file, params->hdr.e_phoff,
128 (char *) params->phdrs, size);
125 if (retval < 0) 129 if (retval < 0)
126 return retval; 130 return retval;
127 131
@@ -141,17 +145,24 @@ static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params, struct file *f
141 } 145 }
142 146
143 return 0; 147 return 0;
144} /* end elf_fdpic_fetch_phdrs() */ 148}
145 149
146/*****************************************************************************/ 150/*****************************************************************************/
147/* 151/*
148 * load an fdpic binary into various bits of memory 152 * load an fdpic binary into various bits of memory
149 */ 153 */
150static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs) 154static int load_elf_fdpic_binary(struct linux_binprm *bprm,
155 struct pt_regs *regs)
151{ 156{
152 struct elf_fdpic_params exec_params, interp_params; 157 struct elf_fdpic_params exec_params, interp_params;
153 struct elf_phdr *phdr; 158 struct elf_phdr *phdr;
154 unsigned long stack_size; 159 unsigned long stack_size, entryaddr;
160#ifndef CONFIG_MMU
161 unsigned long fullsize;
162#endif
163#ifdef ELF_FDPIC_PLAT_INIT
164 unsigned long dynaddr;
165#endif
155 struct file *interpreter = NULL; /* to shut gcc up */ 166 struct file *interpreter = NULL; /* to shut gcc up */
156 char *interpreter_name = NULL; 167 char *interpreter_name = NULL;
157 int executable_stack; 168 int executable_stack;
@@ -212,7 +223,8 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs
212 goto error; 223 goto error;
213 } 224 }
214 225
215 retval = kernel_read(interpreter, 0, bprm->buf, BINPRM_BUF_SIZE); 226 retval = kernel_read(interpreter, 0, bprm->buf,
227 BINPRM_BUF_SIZE);
216 if (retval < 0) 228 if (retval < 0)
217 goto error; 229 goto error;
218 230
@@ -295,7 +307,8 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs
295 &current->mm->start_stack, 307 &current->mm->start_stack,
296 &current->mm->start_brk); 308 &current->mm->start_brk);
297 309
298 retval = setup_arg_pages(bprm, current->mm->start_stack, executable_stack); 310 retval = setup_arg_pages(bprm, current->mm->start_stack,
311 executable_stack);
299 if (retval < 0) { 312 if (retval < 0) {
300 send_sig(SIGKILL, current, 0); 313 send_sig(SIGKILL, current, 0);
301 goto error_kill; 314 goto error_kill;
@@ -303,7 +316,8 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs
303#endif 316#endif
304 317
305 /* load the executable and interpreter into memory */ 318 /* load the executable and interpreter into memory */
306 retval = elf_fdpic_map_file(&exec_params, bprm->file, current->mm, "executable"); 319 retval = elf_fdpic_map_file(&exec_params, bprm->file, current->mm,
320 "executable");
307 if (retval < 0) 321 if (retval < 0)
308 goto error_kill; 322 goto error_kill;
309 323
@@ -324,7 +338,8 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs
324 if (!current->mm->start_brk) 338 if (!current->mm->start_brk)
325 current->mm->start_brk = current->mm->end_data; 339 current->mm->start_brk = current->mm->end_data;
326 340
327 current->mm->brk = current->mm->start_brk = PAGE_ALIGN(current->mm->start_brk); 341 current->mm->brk = current->mm->start_brk =
342 PAGE_ALIGN(current->mm->start_brk);
328 343
329#else 344#else
330 /* create a stack and brk area big enough for everyone 345 /* create a stack and brk area big enough for everyone
@@ -336,47 +351,45 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs
336 stack_size = PAGE_SIZE * 2; 351 stack_size = PAGE_SIZE * 2;
337 352
338 down_write(&current->mm->mmap_sem); 353 down_write(&current->mm->mmap_sem);
339 current->mm->start_brk = do_mmap(NULL, 354 current->mm->start_brk = do_mmap(NULL, 0, stack_size,
340 0,
341 stack_size,
342 PROT_READ | PROT_WRITE | PROT_EXEC, 355 PROT_READ | PROT_WRITE | PROT_EXEC,
343 MAP_PRIVATE | MAP_ANON | MAP_GROWSDOWN, 356 MAP_PRIVATE | MAP_ANON | MAP_GROWSDOWN,
344 0); 357 0);
345 358
346 if (IS_ERR((void *) current->mm->start_brk)) { 359 if (IS_ERR_VALUE(current->mm->start_brk)) {
347 up_write(&current->mm->mmap_sem); 360 up_write(&current->mm->mmap_sem);
348 retval = current->mm->start_brk; 361 retval = current->mm->start_brk;
349 current->mm->start_brk = 0; 362 current->mm->start_brk = 0;
350 goto error_kill; 363 goto error_kill;
351 } 364 }
352 365
353 if (do_mremap(current->mm->start_brk, 366 /* expand the stack mapping to use up the entire allocation granule */
354 stack_size, 367 fullsize = ksize((char *) current->mm->start_brk);
355 ksize((char *) current->mm->start_brk), 368 if (!IS_ERR_VALUE(do_mremap(current->mm->start_brk, stack_size,
356 0, 0 369 fullsize, 0, 0)))
357 ) == current->mm->start_brk 370 stack_size = fullsize;
358 )
359 stack_size = ksize((char *) current->mm->start_brk);
360 up_write(&current->mm->mmap_sem); 371 up_write(&current->mm->mmap_sem);
361 372
362 current->mm->brk = current->mm->start_brk; 373 current->mm->brk = current->mm->start_brk;
363 current->mm->context.end_brk = current->mm->start_brk; 374 current->mm->context.end_brk = current->mm->start_brk;
364 current->mm->context.end_brk += (stack_size > PAGE_SIZE) ? (stack_size - PAGE_SIZE) : 0; 375 current->mm->context.end_brk +=
376 (stack_size > PAGE_SIZE) ? (stack_size - PAGE_SIZE) : 0;
365 current->mm->start_stack = current->mm->start_brk + stack_size; 377 current->mm->start_stack = current->mm->start_brk + stack_size;
366#endif 378#endif
367 379
368 compute_creds(bprm); 380 compute_creds(bprm);
369 current->flags &= ~PF_FORKNOEXEC; 381 current->flags &= ~PF_FORKNOEXEC;
370 if (create_elf_fdpic_tables(bprm, current->mm, &exec_params, &interp_params) < 0) 382 if (create_elf_fdpic_tables(bprm, current->mm,
383 &exec_params, &interp_params) < 0)
371 goto error_kill; 384 goto error_kill;
372 385
373 kdebug("- start_code %lx", (long) current->mm->start_code); 386 kdebug("- start_code %lx", current->mm->start_code);
374 kdebug("- end_code %lx", (long) current->mm->end_code); 387 kdebug("- end_code %lx", current->mm->end_code);
375 kdebug("- start_data %lx", (long) current->mm->start_data); 388 kdebug("- start_data %lx", current->mm->start_data);
376 kdebug("- end_data %lx", (long) current->mm->end_data); 389 kdebug("- end_data %lx", current->mm->end_data);
377 kdebug("- start_brk %lx", (long) current->mm->start_brk); 390 kdebug("- start_brk %lx", current->mm->start_brk);
378 kdebug("- brk %lx", (long) current->mm->brk); 391 kdebug("- brk %lx", current->mm->brk);
379 kdebug("- start_stack %lx", (long) current->mm->start_stack); 392 kdebug("- start_stack %lx", current->mm->start_stack);
380 393
381#ifdef ELF_FDPIC_PLAT_INIT 394#ifdef ELF_FDPIC_PLAT_INIT
382 /* 395 /*
@@ -385,21 +398,18 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs
385 * example. This macro performs whatever initialization to 398 * example. This macro performs whatever initialization to
386 * the regs structure is required. 399 * the regs structure is required.
387 */ 400 */
388 ELF_FDPIC_PLAT_INIT(regs, 401 dynaddr = interp_params.dynamic_addr ?: exec_params.dynamic_addr;
389 exec_params.map_addr, 402 ELF_FDPIC_PLAT_INIT(regs, exec_params.map_addr, interp_params.map_addr,
390 interp_params.map_addr, 403 dynaddr);
391 interp_params.dynamic_addr ?: exec_params.dynamic_addr
392 );
393#endif 404#endif
394 405
395 /* everything is now ready... get the userspace context ready to roll */ 406 /* everything is now ready... get the userspace context ready to roll */
396 start_thread(regs, 407 entryaddr = interp_params.entry_addr ?: exec_params.entry_addr;
397 interp_params.entry_addr ?: exec_params.entry_addr, 408 start_thread(regs, entryaddr, current->mm->start_stack);
398 current->mm->start_stack);
399 409
400 if (unlikely(current->ptrace & PT_PTRACED)) { 410 if (unlikely(current->ptrace & PT_PTRACED)) {
401 if (current->ptrace & PT_TRACE_EXEC) 411 if (current->ptrace & PT_TRACE_EXEC)
402 ptrace_notify ((PTRACE_EVENT_EXEC << 8) | SIGTRAP); 412 ptrace_notify((PTRACE_EVENT_EXEC << 8) | SIGTRAP);
403 else 413 else
404 send_sig(SIGTRAP, current, 0); 414 send_sig(SIGTRAP, current, 0);
405 } 415 }
@@ -419,11 +429,11 @@ error:
419 return retval; 429 return retval;
420 430
421 /* unrecoverable error - kill the process */ 431 /* unrecoverable error - kill the process */
422 error_kill: 432error_kill:
423 send_sig(SIGSEGV, current, 0); 433 send_sig(SIGSEGV, current, 0);
424 goto error; 434 goto error;
425 435
426} /* end load_elf_fdpic_binary() */ 436}
427 437
428/*****************************************************************************/ 438/*****************************************************************************/
429/* 439/*
@@ -471,11 +481,11 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
471 481
472#if defined(__i386__) && defined(CONFIG_SMP) 482#if defined(__i386__) && defined(CONFIG_SMP)
473 /* in some cases (e.g. Hyper-Threading), we want to avoid L1 evictions 483 /* in some cases (e.g. Hyper-Threading), we want to avoid L1 evictions
474 * by the processes running on the same package. One thing we can do 484 * by the processes running on the same package. One thing we can do is
475 * is to shuffle the initial stack for them. 485 * to shuffle the initial stack for them.
476 * 486 *
477 * the conditionals here are unneeded, but kept in to make the 487 * the conditionals here are unneeded, but kept in to make the code
478 * code behaviour the same as pre change unless we have hyperthreaded 488 * behaviour the same as pre change unless we have hyperthreaded
479 * processors. This keeps Mr Marcelo Person happier but should be 489 * processors. This keeps Mr Marcelo Person happier but should be
480 * removed for 2.5 490 * removed for 2.5
481 */ 491 */
@@ -498,11 +508,13 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
498 508
499 if (interp_params->loadmap) { 509 if (interp_params->loadmap) {
500 len = sizeof(struct elf32_fdpic_loadmap); 510 len = sizeof(struct elf32_fdpic_loadmap);
501 len += sizeof(struct elf32_fdpic_loadseg) * interp_params->loadmap->nsegs; 511 len += sizeof(struct elf32_fdpic_loadseg) *
512 interp_params->loadmap->nsegs;
502 sp = (sp - len) & ~7UL; 513 sp = (sp - len) & ~7UL;
503 interp_params->map_addr = sp; 514 interp_params->map_addr = sp;
504 515
505 if (copy_to_user((void __user *) sp, interp_params->loadmap, len) != 0) 516 if (copy_to_user((void __user *) sp, interp_params->loadmap,
517 len) != 0)
506 return -EFAULT; 518 return -EFAULT;
507 519
508 current->mm->context.interp_fdpic_loadmap = (unsigned long) sp; 520 current->mm->context.interp_fdpic_loadmap = (unsigned long) sp;
@@ -526,34 +538,37 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
526 sp -= sp & 15UL; 538 sp -= sp & 15UL;
527 539
528 /* put the ELF interpreter info on the stack */ 540 /* put the ELF interpreter info on the stack */
529#define NEW_AUX_ENT(nr, id, val) \ 541#define NEW_AUX_ENT(nr, id, val) \
530 do { \ 542 do { \
531 struct { unsigned long _id, _val; } __user *ent = (void __user *) csp; \ 543 struct { unsigned long _id, _val; } __user *ent; \
532 __put_user((id), &ent[nr]._id); \ 544 \
533 __put_user((val), &ent[nr]._val); \ 545 ent = (void __user *) csp; \
546 __put_user((id), &ent[nr]._id); \
547 __put_user((val), &ent[nr]._val); \
534 } while (0) 548 } while (0)
535 549
536 csp -= 2 * sizeof(unsigned long); 550 csp -= 2 * sizeof(unsigned long);
537 NEW_AUX_ENT(0, AT_NULL, 0); 551 NEW_AUX_ENT(0, AT_NULL, 0);
538 if (k_platform) { 552 if (k_platform) {
539 csp -= 2 * sizeof(unsigned long); 553 csp -= 2 * sizeof(unsigned long);
540 NEW_AUX_ENT(0, AT_PLATFORM, (elf_addr_t)(unsigned long) u_platform); 554 NEW_AUX_ENT(0, AT_PLATFORM,
555 (elf_addr_t) (unsigned long) u_platform);
541 } 556 }
542 557
543 csp -= DLINFO_ITEMS * 2 * sizeof(unsigned long); 558 csp -= DLINFO_ITEMS * 2 * sizeof(unsigned long);
544 NEW_AUX_ENT( 0, AT_HWCAP, hwcap); 559 NEW_AUX_ENT( 0, AT_HWCAP, hwcap);
545 NEW_AUX_ENT( 1, AT_PAGESZ, PAGE_SIZE); 560 NEW_AUX_ENT( 1, AT_PAGESZ, PAGE_SIZE);
546 NEW_AUX_ENT( 2, AT_CLKTCK, CLOCKS_PER_SEC); 561 NEW_AUX_ENT( 2, AT_CLKTCK, CLOCKS_PER_SEC);
547 NEW_AUX_ENT( 3, AT_PHDR, exec_params->ph_addr); 562 NEW_AUX_ENT( 3, AT_PHDR, exec_params->ph_addr);
548 NEW_AUX_ENT( 4, AT_PHENT, sizeof(struct elf_phdr)); 563 NEW_AUX_ENT( 4, AT_PHENT, sizeof(struct elf_phdr));
549 NEW_AUX_ENT( 5, AT_PHNUM, exec_params->hdr.e_phnum); 564 NEW_AUX_ENT( 5, AT_PHNUM, exec_params->hdr.e_phnum);
550 NEW_AUX_ENT( 6, AT_BASE, interp_params->elfhdr_addr); 565 NEW_AUX_ENT( 6, AT_BASE, interp_params->elfhdr_addr);
551 NEW_AUX_ENT( 7, AT_FLAGS, 0); 566 NEW_AUX_ENT( 7, AT_FLAGS, 0);
552 NEW_AUX_ENT( 8, AT_ENTRY, exec_params->entry_addr); 567 NEW_AUX_ENT( 8, AT_ENTRY, exec_params->entry_addr);
553 NEW_AUX_ENT( 9, AT_UID, (elf_addr_t) current->uid); 568 NEW_AUX_ENT( 9, AT_UID, (elf_addr_t) current->uid);
554 NEW_AUX_ENT(10, AT_EUID, (elf_addr_t) current->euid); 569 NEW_AUX_ENT(10, AT_EUID, (elf_addr_t) current->euid);
555 NEW_AUX_ENT(11, AT_GID, (elf_addr_t) current->gid); 570 NEW_AUX_ENT(11, AT_GID, (elf_addr_t) current->gid);
556 NEW_AUX_ENT(12, AT_EGID, (elf_addr_t) current->egid); 571 NEW_AUX_ENT(12, AT_EGID, (elf_addr_t) current->egid);
557 572
558#ifdef ARCH_DLINFO 573#ifdef ARCH_DLINFO
559 /* ARCH_DLINFO must come last so platform specific code can enforce 574 /* ARCH_DLINFO must come last so platform specific code can enforce
@@ -579,7 +594,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
579#ifdef CONFIG_MMU 594#ifdef CONFIG_MMU
580 current->mm->arg_start = bprm->p; 595 current->mm->arg_start = bprm->p;
581#else 596#else
582 current->mm->arg_start = current->mm->start_stack - (MAX_ARG_PAGES * PAGE_SIZE - bprm->p); 597 current->mm->arg_start = current->mm->start_stack -
598 (MAX_ARG_PAGES * PAGE_SIZE - bprm->p);
583#endif 599#endif
584 600
585 p = (char __user *) current->mm->arg_start; 601 p = (char __user *) current->mm->arg_start;
@@ -607,7 +623,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
607 623
608 mm->start_stack = (unsigned long) sp; 624 mm->start_stack = (unsigned long) sp;
609 return 0; 625 return 0;
610} /* end create_elf_fdpic_tables() */ 626}
611 627
612/*****************************************************************************/ 628/*****************************************************************************/
613/* 629/*
@@ -615,7 +631,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
615 * the stack 631 * the stack
616 */ 632 */
617#ifndef CONFIG_MMU 633#ifndef CONFIG_MMU
618static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *bprm, unsigned long *_sp) 634static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *bprm,
635 unsigned long *_sp)
619{ 636{
620 unsigned long index, stop, sp; 637 unsigned long index, stop, sp;
621 char *src; 638 char *src;
@@ -636,9 +653,9 @@ static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *bprm, unsigned
636 653
637 *_sp = (*_sp - (MAX_ARG_PAGES * PAGE_SIZE - bprm->p)) & ~15; 654 *_sp = (*_sp - (MAX_ARG_PAGES * PAGE_SIZE - bprm->p)) & ~15;
638 655
639 out: 656out:
640 return ret; 657 return ret;
641} /* end elf_fdpic_transfer_args_to_stack() */ 658}
642#endif 659#endif
643 660
644/*****************************************************************************/ 661/*****************************************************************************/
@@ -713,17 +730,18 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
713 seg = loadmap->segs; 730 seg = loadmap->segs;
714 for (loop = loadmap->nsegs; loop > 0; loop--, seg++) { 731 for (loop = loadmap->nsegs; loop > 0; loop--, seg++) {
715 if (params->hdr.e_entry >= seg->p_vaddr && 732 if (params->hdr.e_entry >= seg->p_vaddr &&
716 params->hdr.e_entry < seg->p_vaddr + seg->p_memsz 733 params->hdr.e_entry < seg->p_vaddr + seg->p_memsz) {
717 ) {
718 params->entry_addr = 734 params->entry_addr =
719 (params->hdr.e_entry - seg->p_vaddr) + seg->addr; 735 (params->hdr.e_entry - seg->p_vaddr) +
736 seg->addr;
720 break; 737 break;
721 } 738 }
722 } 739 }
723 } 740 }
724 741
725 /* determine where the program header table has wound up if mapped */ 742 /* determine where the program header table has wound up if mapped */
726 stop = params->hdr.e_phoff + params->hdr.e_phnum * sizeof (struct elf_phdr); 743 stop = params->hdr.e_phoff;
744 stop += params->hdr.e_phnum * sizeof (struct elf_phdr);
727 phdr = params->phdrs; 745 phdr = params->phdrs;
728 746
729 for (loop = 0; loop < params->hdr.e_phnum; loop++, phdr++) { 747 for (loop = 0; loop < params->hdr.e_phnum; loop++, phdr++) {
@@ -737,9 +755,11 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
737 seg = loadmap->segs; 755 seg = loadmap->segs;
738 for (loop = loadmap->nsegs; loop > 0; loop--, seg++) { 756 for (loop = loadmap->nsegs; loop > 0; loop--, seg++) {
739 if (phdr->p_vaddr >= seg->p_vaddr && 757 if (phdr->p_vaddr >= seg->p_vaddr &&
740 phdr->p_vaddr + phdr->p_filesz <= seg->p_vaddr + seg->p_memsz 758 phdr->p_vaddr + phdr->p_filesz <=
741 ) { 759 seg->p_vaddr + seg->p_memsz) {
742 params->ph_addr = (phdr->p_vaddr - seg->p_vaddr) + seg->addr + 760 params->ph_addr =
761 (phdr->p_vaddr - seg->p_vaddr) +
762 seg->addr +
743 params->hdr.e_phoff - phdr->p_offset; 763 params->hdr.e_phoff - phdr->p_offset;
744 break; 764 break;
745 } 765 }
@@ -756,18 +776,22 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
756 seg = loadmap->segs; 776 seg = loadmap->segs;
757 for (loop = loadmap->nsegs; loop > 0; loop--, seg++) { 777 for (loop = loadmap->nsegs; loop > 0; loop--, seg++) {
758 if (phdr->p_vaddr >= seg->p_vaddr && 778 if (phdr->p_vaddr >= seg->p_vaddr &&
759 phdr->p_vaddr + phdr->p_memsz <= seg->p_vaddr + seg->p_memsz 779 phdr->p_vaddr + phdr->p_memsz <=
760 ) { 780 seg->p_vaddr + seg->p_memsz) {
761 params->dynamic_addr = (phdr->p_vaddr - seg->p_vaddr) + seg->addr; 781 params->dynamic_addr =
762 782 (phdr->p_vaddr - seg->p_vaddr) +
763 /* check the dynamic section contains at least one item, and that 783 seg->addr;
764 * the last item is a NULL entry */ 784
785 /* check the dynamic section contains at least
786 * one item, and that the last item is a NULL
787 * entry */
765 if (phdr->p_memsz == 0 || 788 if (phdr->p_memsz == 0 ||
766 phdr->p_memsz % sizeof(Elf32_Dyn) != 0) 789 phdr->p_memsz % sizeof(Elf32_Dyn) != 0)
767 goto dynamic_error; 790 goto dynamic_error;
768 791
769 tmp = phdr->p_memsz / sizeof(Elf32_Dyn); 792 tmp = phdr->p_memsz / sizeof(Elf32_Dyn);
770 if (((Elf32_Dyn *) params->dynamic_addr)[tmp - 1].d_tag != 0) 793 if (((Elf32_Dyn *)
794 params->dynamic_addr)[tmp - 1].d_tag != 0)
771 goto dynamic_error; 795 goto dynamic_error;
772 break; 796 break;
773 } 797 }
@@ -776,8 +800,8 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
776 } 800 }
777 801
778 /* now elide adjacent segments in the load map on MMU linux 802 /* now elide adjacent segments in the load map on MMU linux
779 * - on uClinux the holes between may actually be filled with system stuff or stuff from 803 * - on uClinux the holes between may actually be filled with system
780 * other processes 804 * stuff or stuff from other processes
781 */ 805 */
782#ifdef CONFIG_MMU 806#ifdef CONFIG_MMU
783 nloads = loadmap->nsegs; 807 nloads = loadmap->nsegs;
@@ -788,7 +812,9 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
788 if (seg->p_vaddr - mseg->p_vaddr == seg->addr - mseg->addr) { 812 if (seg->p_vaddr - mseg->p_vaddr == seg->addr - mseg->addr) {
789 load_addr = PAGE_ALIGN(mseg->addr + mseg->p_memsz); 813 load_addr = PAGE_ALIGN(mseg->addr + mseg->p_memsz);
790 if (load_addr == (seg->addr & PAGE_MASK)) { 814 if (load_addr == (seg->addr & PAGE_MASK)) {
791 mseg->p_memsz += load_addr - (mseg->addr + mseg->p_memsz); 815 mseg->p_memsz +=
816 load_addr -
817 (mseg->addr + mseg->p_memsz);
792 mseg->p_memsz += seg->addr & ~PAGE_MASK; 818 mseg->p_memsz += seg->addr & ~PAGE_MASK;
793 mseg->p_memsz += seg->p_memsz; 819 mseg->p_memsz += seg->p_memsz;
794 loadmap->nsegs--; 820 loadmap->nsegs--;
@@ -816,20 +842,21 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
816 842
817 return 0; 843 return 0;
818 844
819 dynamic_error: 845dynamic_error:
820 printk("ELF FDPIC %s with invalid DYNAMIC section (inode=%lu)\n", 846 printk("ELF FDPIC %s with invalid DYNAMIC section (inode=%lu)\n",
821 what, file->f_dentry->d_inode->i_ino); 847 what, file->f_dentry->d_inode->i_ino);
822 return -ELIBBAD; 848 return -ELIBBAD;
823} /* end elf_fdpic_map_file() */ 849}
824 850
825/*****************************************************************************/ 851/*****************************************************************************/
826/* 852/*
827 * map a file with constant displacement under uClinux 853 * map a file with constant displacement under uClinux
828 */ 854 */
829#ifndef CONFIG_MMU 855#ifndef CONFIG_MMU
830static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *params, 856static int elf_fdpic_map_file_constdisp_on_uclinux(
831 struct file *file, 857 struct elf_fdpic_params *params,
832 struct mm_struct *mm) 858 struct file *file,
859 struct mm_struct *mm)
833{ 860{
834 struct elf32_fdpic_loadseg *seg; 861 struct elf32_fdpic_loadseg *seg;
835 struct elf32_phdr *phdr; 862 struct elf32_phdr *phdr;
@@ -840,7 +867,8 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *para
840 load_addr = params->load_addr; 867 load_addr = params->load_addr;
841 seg = params->loadmap->segs; 868 seg = params->loadmap->segs;
842 869
843 /* determine the bounds of the contiguous overall allocation we must make */ 870 /* determine the bounds of the contiguous overall allocation we must
871 * make */
844 phdr = params->phdrs; 872 phdr = params->phdrs;
845 for (loop = 0; loop < params->hdr.e_phnum; loop++, phdr++) { 873 for (loop = 0; loop < params->hdr.e_phnum; loop++, phdr++) {
846 if (params->phdrs[loop].p_type != PT_LOAD) 874 if (params->phdrs[loop].p_type != PT_LOAD)
@@ -861,7 +889,7 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *para
861 maddr = do_mmap(NULL, load_addr, top - base, 889 maddr = do_mmap(NULL, load_addr, top - base,
862 PROT_READ | PROT_WRITE | PROT_EXEC, mflags, 0); 890 PROT_READ | PROT_WRITE | PROT_EXEC, mflags, 0);
863 up_write(&mm->mmap_sem); 891 up_write(&mm->mmap_sem);
864 if (IS_ERR((void *) maddr)) 892 if (IS_ERR_VALUE(maddr))
865 return (int) maddr; 893 return (int) maddr;
866 894
867 if (load_addr != 0) 895 if (load_addr != 0)
@@ -879,7 +907,8 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *para
879 seg->p_vaddr = phdr->p_vaddr; 907 seg->p_vaddr = phdr->p_vaddr;
880 seg->p_memsz = phdr->p_memsz; 908 seg->p_memsz = phdr->p_memsz;
881 909
882 ret = file->f_op->read(file, (void *) seg->addr, phdr->p_filesz, &fpos); 910 ret = file->f_op->read(file, (void *) seg->addr,
911 phdr->p_filesz, &fpos);
883 if (ret < 0) 912 if (ret < 0)
884 return ret; 913 return ret;
885 914
@@ -896,8 +925,7 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *para
896 if (phdr->p_flags & PF_X) { 925 if (phdr->p_flags & PF_X) {
897 mm->start_code = seg->addr; 926 mm->start_code = seg->addr;
898 mm->end_code = seg->addr + phdr->p_memsz; 927 mm->end_code = seg->addr + phdr->p_memsz;
899 } 928 } else if (!mm->start_data) {
900 else if (!mm->start_data) {
901 mm->start_data = seg->addr; 929 mm->start_data = seg->addr;
902#ifndef CONFIG_MMU 930#ifndef CONFIG_MMU
903 mm->end_data = seg->addr + phdr->p_memsz; 931 mm->end_data = seg->addr + phdr->p_memsz;
@@ -914,7 +942,7 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *para
914 } 942 }
915 943
916 return 0; 944 return 0;
917} /* end elf_fdpic_map_file_constdisp_on_uclinux() */ 945}
918#endif 946#endif
919 947
920/*****************************************************************************/ 948/*****************************************************************************/
@@ -975,14 +1003,14 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
975 1003
976 case ELF_FDPIC_FLAG_CONSTDISP: 1004 case ELF_FDPIC_FLAG_CONSTDISP:
977 /* constant displacement 1005 /* constant displacement
978 * - can be mapped anywhere, but must be mapped as a unit 1006 * - can be mapped anywhere, but must be mapped as a
1007 * unit
979 */ 1008 */
980 if (!dvset) { 1009 if (!dvset) {
981 maddr = load_addr; 1010 maddr = load_addr;
982 delta_vaddr = phdr->p_vaddr; 1011 delta_vaddr = phdr->p_vaddr;
983 dvset = 1; 1012 dvset = 1;
984 } 1013 } else {
985 else {
986 maddr = load_addr + phdr->p_vaddr - delta_vaddr; 1014 maddr = load_addr + phdr->p_vaddr - delta_vaddr;
987 flags |= MAP_FIXED; 1015 flags |= MAP_FIXED;
988 } 1016 }
@@ -1006,13 +1034,14 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
1006 up_write(&mm->mmap_sem); 1034 up_write(&mm->mmap_sem);
1007 1035
1008 kdebug("mmap[%d] <file> sz=%lx pr=%x fl=%x of=%lx --> %08lx", 1036 kdebug("mmap[%d] <file> sz=%lx pr=%x fl=%x of=%lx --> %08lx",
1009 loop, phdr->p_memsz + disp, prot, flags, phdr->p_offset - disp, 1037 loop, phdr->p_memsz + disp, prot, flags,
1010 maddr); 1038 phdr->p_offset - disp, maddr);
1011 1039
1012 if (IS_ERR((void *) maddr)) 1040 if (IS_ERR_VALUE(maddr))
1013 return (int) maddr; 1041 return (int) maddr;
1014 1042
1015 if ((params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) == ELF_FDPIC_FLAG_CONTIGUOUS) 1043 if ((params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) ==
1044 ELF_FDPIC_FLAG_CONTIGUOUS)
1016 load_addr += PAGE_ALIGN(phdr->p_memsz + disp); 1045 load_addr += PAGE_ALIGN(phdr->p_memsz + disp);
1017 1046
1018 seg->addr = maddr + disp; 1047 seg->addr = maddr + disp;
@@ -1023,7 +1052,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
1023 if (phdr->p_offset == 0) 1052 if (phdr->p_offset == 0)
1024 params->elfhdr_addr = seg->addr; 1053 params->elfhdr_addr = seg->addr;
1025 1054
1026 /* clear the bit between beginning of mapping and beginning of PT_LOAD */ 1055 /* clear the bit between beginning of mapping and beginning of
1056 * PT_LOAD */
1027 if (prot & PROT_WRITE && disp > 0) { 1057 if (prot & PROT_WRITE && disp > 0) {
1028 kdebug("clear[%d] ad=%lx sz=%lx", loop, maddr, disp); 1058 kdebug("clear[%d] ad=%lx sz=%lx", loop, maddr, disp);
1029 clear_user((void __user *) maddr, disp); 1059 clear_user((void __user *) maddr, disp);
@@ -1039,19 +1069,20 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
1039 excess1 = PAGE_SIZE - ((maddr + phdr->p_filesz) & ~PAGE_MASK); 1069 excess1 = PAGE_SIZE - ((maddr + phdr->p_filesz) & ~PAGE_MASK);
1040 1070
1041#ifdef CONFIG_MMU 1071#ifdef CONFIG_MMU
1042
1043 if (excess > excess1) { 1072 if (excess > excess1) {
1044 unsigned long xaddr = maddr + phdr->p_filesz + excess1; 1073 unsigned long xaddr = maddr + phdr->p_filesz + excess1;
1045 unsigned long xmaddr; 1074 unsigned long xmaddr;
1046 1075
1047 flags |= MAP_FIXED | MAP_ANONYMOUS; 1076 flags |= MAP_FIXED | MAP_ANONYMOUS;
1048 down_write(&mm->mmap_sem); 1077 down_write(&mm->mmap_sem);
1049 xmaddr = do_mmap(NULL, xaddr, excess - excess1, prot, flags, 0); 1078 xmaddr = do_mmap(NULL, xaddr, excess - excess1,
1079 prot, flags, 0);
1050 up_write(&mm->mmap_sem); 1080 up_write(&mm->mmap_sem);
1051 1081
1052 kdebug("mmap[%d] <anon>" 1082 kdebug("mmap[%d] <anon>"
1053 " ad=%lx sz=%lx pr=%x fl=%x of=0 --> %08lx", 1083 " ad=%lx sz=%lx pr=%x fl=%x of=0 --> %08lx",
1054 loop, xaddr, excess - excess1, prot, flags, xmaddr); 1084 loop, xaddr, excess - excess1, prot, flags,
1085 xmaddr);
1055 1086
1056 if (xmaddr != xaddr) 1087 if (xmaddr != xaddr)
1057 return -ENOMEM; 1088 return -ENOMEM;
@@ -1060,7 +1091,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
1060 if (prot & PROT_WRITE && excess1 > 0) { 1091 if (prot & PROT_WRITE && excess1 > 0) {
1061 kdebug("clear[%d] ad=%lx sz=%lx", 1092 kdebug("clear[%d] ad=%lx sz=%lx",
1062 loop, maddr + phdr->p_filesz, excess1); 1093 loop, maddr + phdr->p_filesz, excess1);
1063 clear_user((void __user *) maddr + phdr->p_filesz, excess1); 1094 clear_user((void __user *) maddr + phdr->p_filesz,
1095 excess1);
1064 } 1096 }
1065 1097
1066#else 1098#else
@@ -1075,8 +1107,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
1075 if (phdr->p_flags & PF_X) { 1107 if (phdr->p_flags & PF_X) {
1076 mm->start_code = maddr; 1108 mm->start_code = maddr;
1077 mm->end_code = maddr + phdr->p_memsz; 1109 mm->end_code = maddr + phdr->p_memsz;
1078 } 1110 } else if (!mm->start_data) {
1079 else if (!mm->start_data) {
1080 mm->start_data = maddr; 1111 mm->start_data = maddr;
1081 mm->end_data = maddr + phdr->p_memsz; 1112 mm->end_data = maddr + phdr->p_memsz;
1082 } 1113 }
@@ -1086,4 +1117,4 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
1086 } 1117 }
1087 1118
1088 return 0; 1119 return 0;
1089} /* end elf_fdpic_map_file_by_direct_mmap() */ 1120}