diff options
author | Nicolas Pitre <nicolas.pitre@linaro.org> | 2016-07-24 11:30:26 -0400 |
---|---|---|
committer | Greg Ungerer <gerg@linux-m68k.org> | 2016-07-27 23:29:12 -0400 |
commit | 472f95f32d5aa07eda96a6b2578b85d7b27c5110 (patch) | |
tree | e066d346cba4ca529016be057f3294ecd3e2fd98 /fs/binfmt_flat.c | |
parent | 015feacf932108429f59b511b29d7e98a629e333 (diff) |
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>
Diffstat (limited to 'fs/binfmt_flat.c')
-rw-r--r-- | fs/binfmt_flat.c | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 506139bfdc9e..9b2917a30294 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
35 | #include <linux/flat.h> | 35 | #include <linux/flat.h> |
36 | #include <linux/uaccess.h> | 36 | #include <linux/uaccess.h> |
37 | #include <linux/vmalloc.h> | ||
37 | 38 | ||
38 | #include <asm/byteorder.h> | 39 | #include <asm/byteorder.h> |
39 | #include <asm/unaligned.h> | 40 | #include <asm/unaligned.h> |
@@ -628,6 +629,7 @@ static int load_flat_file(struct linux_binprm *bprm, | |||
628 | * load it all in and treat it like a RAM load from now on | 629 | * load it all in and treat it like a RAM load from now on |
629 | */ | 630 | */ |
630 | if (flags & FLAT_FLAG_GZIP) { | 631 | if (flags & FLAT_FLAG_GZIP) { |
632 | #ifndef CONFIG_MMU | ||
631 | result = decompress_exec(bprm, sizeof(struct flat_hdr), | 633 | result = decompress_exec(bprm, sizeof(struct flat_hdr), |
632 | (((char *)textpos) + sizeof(struct flat_hdr)), | 634 | (((char *)textpos) + sizeof(struct flat_hdr)), |
633 | (text_len + full_data | 635 | (text_len + full_data |
@@ -635,13 +637,51 @@ static int load_flat_file(struct linux_binprm *bprm, | |||
635 | 0); | 637 | 0); |
636 | memmove((void *) datapos, (void *) realdatastart, | 638 | memmove((void *) datapos, (void *) realdatastart, |
637 | full_data); | 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 | } else if (flags & FLAT_FLAG_GZDATA) { | 662 | } else if (flags & FLAT_FLAG_GZDATA) { |
639 | result = read_code(bprm->file, textpos, 0, text_len); | 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 | result = decompress_exec(bprm, text_len, (char *) datapos, | 666 | result = decompress_exec(bprm, text_len, (char *) datapos, |
642 | full_data, 0); | 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 | #endif | 681 | #endif |
682 | } | ||
683 | } else | ||
684 | #endif /* CONFIG_BINFMT_ZFLAT */ | ||
645 | { | 685 | { |
646 | result = read_code(bprm->file, textpos, 0, text_len); | 686 | result = read_code(bprm->file, textpos, 0, text_len); |
647 | if (!IS_ERR_VALUE(result)) | 687 | if (!IS_ERR_VALUE(result)) |