Commit 472f95f32d5aa07eda96a6b2578b85d7b27c5110

Authored by Nicolas Pitre
Committed by Greg Ungerer
1 parent 015feacf93

binfmt_flat: allow compressed flat binary format to work on MMU systems

Let's take the simple and obvious approach by decompressing the binary
into a kernel buffer and then copying it to user space.  Those who are
looking for top performance on an MMU system are unlikely to choose this
executable format anyway.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
Reviewed-by: Greg Ungerer <gerg@linux-m68k.org>
Signed-off-by: Greg Ungerer <gerg@linux-m68k.org>

Showing 1 changed file with 42 additions and 2 deletions Side-by-side Diff

... ... @@ -34,6 +34,7 @@
34 34 #include <linux/init.h>
35 35 #include <linux/flat.h>
36 36 #include <linux/uaccess.h>
  37 +#include <linux/vmalloc.h>
37 38  
38 39 #include <asm/byteorder.h>
39 40 #include <asm/unaligned.h>
... ... @@ -628,6 +629,7 @@
628 629 * load it all in and treat it like a RAM load from now on
629 630 */
630 631 if (flags & FLAT_FLAG_GZIP) {
  632 +#ifndef CONFIG_MMU
631 633 result = decompress_exec(bprm, sizeof(struct flat_hdr),
632 634 (((char *)textpos) + sizeof(struct flat_hdr)),
633 635 (text_len + full_data
634 636  
635 637  
636 638  
... ... @@ -635,13 +637,51 @@
635 637 0);
636 638 memmove((void *) datapos, (void *) realdatastart,
637 639 full_data);
  640 +#else
  641 + /*
  642 + * This is used on MMU systems mainly for testing.
  643 + * Let's use a kernel buffer to simplify things.
  644 + */
  645 + long unz_text_len = text_len - sizeof(struct flat_hdr);
  646 + long unz_len = unz_text_len + full_data;
  647 + char *unz_data = vmalloc(unz_len);
  648 + if (!unz_data) {
  649 + result = -ENOMEM;
  650 + } else {
  651 + result = decompress_exec(bprm, sizeof(struct flat_hdr),
  652 + unz_data, unz_len, 0);
  653 + if (result == 0 &&
  654 + (copy_to_user((void __user *)textpos + sizeof(struct flat_hdr),
  655 + unz_data, unz_text_len) ||
  656 + copy_to_user((void __user *)datapos,
  657 + unz_data + unz_text_len, full_data)))
  658 + result = -EFAULT;
  659 + vfree(unz_data);
  660 + }
  661 +#endif
638 662 } else if (flags & FLAT_FLAG_GZDATA) {
639 663 result = read_code(bprm->file, textpos, 0, text_len);
640   - if (!IS_ERR_VALUE(result))
  664 + if (!IS_ERR_VALUE(result)) {
  665 +#ifndef CONFIG_MMU
641 666 result = decompress_exec(bprm, text_len, (char *) datapos,
642 667 full_data, 0);
643   - } else
  668 +#else
  669 + char *unz_data = vmalloc(full_data);
  670 + if (!unz_data) {
  671 + result = -ENOMEM;
  672 + } else {
  673 + result = decompress_exec(bprm, text_len,
  674 + unz_data, full_data, 0);
  675 + if (result == 0 &&
  676 + copy_to_user((void __user *)datapos,
  677 + unz_data, full_data))
  678 + result = -EFAULT;
  679 + vfree(unz_data);
  680 + }
644 681 #endif
  682 + }
  683 + } else
  684 +#endif /* CONFIG_BINFMT_ZFLAT */
645 685 {
646 686 result = read_code(bprm->file, textpos, 0, text_len);
647 687 if (!IS_ERR_VALUE(result))