aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/binfmt_flat.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index 9deafb282db5..8e812d7a62e0 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -379,35 +379,38 @@ static void old_reloc(unsigned long rl)
379{ 379{
380 static const char *segment[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" }; 380 static const char *segment[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" };
381 flat_v2_reloc_t r; 381 flat_v2_reloc_t r;
382 unsigned long *ptr; 382 unsigned long __user *ptr;
383 unsigned long val;
383 384
384 r.value = rl; 385 r.value = rl;
385#if defined(CONFIG_COLDFIRE) 386#if defined(CONFIG_COLDFIRE)
386 ptr = (unsigned long *) (current->mm->start_code + r.reloc.offset); 387 ptr = (unsigned long __user *)(current->mm->start_code + r.reloc.offset);
387#else 388#else
388 ptr = (unsigned long *) (current->mm->start_data + r.reloc.offset); 389 ptr = (unsigned long __user *)(current->mm->start_data + r.reloc.offset);
389#endif 390#endif
391 get_user(val, ptr);
390 392
391 pr_debug("Relocation of variable at DATASEG+%x " 393 pr_debug("Relocation of variable at DATASEG+%x "
392 "(address %p, currently %lx) into segment %s\n", 394 "(address %p, currently %lx) into segment %s\n",
393 r.reloc.offset, ptr, *ptr, segment[r.reloc.type]); 395 r.reloc.offset, ptr, val, segment[r.reloc.type]);
394 396
395 switch (r.reloc.type) { 397 switch (r.reloc.type) {
396 case OLD_FLAT_RELOC_TYPE_TEXT: 398 case OLD_FLAT_RELOC_TYPE_TEXT:
397 *ptr += current->mm->start_code; 399 val += current->mm->start_code;
398 break; 400 break;
399 case OLD_FLAT_RELOC_TYPE_DATA: 401 case OLD_FLAT_RELOC_TYPE_DATA:
400 *ptr += current->mm->start_data; 402 val += current->mm->start_data;
401 break; 403 break;
402 case OLD_FLAT_RELOC_TYPE_BSS: 404 case OLD_FLAT_RELOC_TYPE_BSS:
403 *ptr += current->mm->end_data; 405 val += current->mm->end_data;
404 break; 406 break;
405 default: 407 default:
406 pr_err("Unknown relocation type=%x\n", r.reloc.type); 408 pr_err("Unknown relocation type=%x\n", r.reloc.type);
407 break; 409 break;
408 } 410 }
411 put_user(val, ptr);
409 412
410 pr_debug("Relocation became %lx\n", *ptr); 413 pr_debug("Relocation became %lx\n", val);
411} 414}
412 415
413/****************************************************************************/ 416/****************************************************************************/
@@ -780,8 +783,13 @@ static int load_flat_file(struct linux_binprm *bprm,
780 } 783 }
781 } 784 }
782 } else { 785 } else {
783 for (i = 0; i < relocs; i++) 786 for (i = 0; i < relocs; i++) {
784 old_reloc(ntohl(reloc[i])); 787 unsigned long relval;
788 if (get_user(relval, reloc + i))
789 return -EFAULT;
790 relval = ntohl(relval);
791 old_reloc(relval);
792 }
785 } 793 }
786 794
787 flush_icache_range(start_code, end_code); 795 flush_icache_range(start_code, end_code);