diff options
-rw-r--r-- | fs/binfmt_flat.c | 28 |
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); |