Skip to content

Commit 472f95f

Browse files
Nicolas PitreGreg Ungerer
Nicolas Pitre
authored and
Greg Ungerer
committed
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 <[email protected]> Reviewed-by: Greg Ungerer <[email protected]> Signed-off-by: Greg Ungerer <[email protected]>
1 parent 015feac commit 472f95f

File tree

1 file changed

+42
-2
lines changed

1 file changed

+42
-2
lines changed

fs/binfmt_flat.c

+42-2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <linux/init.h>
3535
#include <linux/flat.h>
3636
#include <linux/uaccess.h>
37+
#include <linux/vmalloc.h>
3738

3839
#include <asm/byteorder.h>
3940
#include <asm/unaligned.h>
@@ -628,20 +629,59 @@ static int load_flat_file(struct linux_binprm *bprm,
628629
* load it all in and treat it like a RAM load from now on
629630
*/
630631
if (flags & FLAT_FLAG_GZIP) {
632+
#ifndef CONFIG_MMU
631633
result = decompress_exec(bprm, sizeof(struct flat_hdr),
632634
(((char *)textpos) + sizeof(struct flat_hdr)),
633635
(text_len + full_data
634636
- sizeof(struct flat_hdr)),
635637
0);
636638
memmove((void *) datapos, (void *) realdatastart,
637639
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
638662
} else if (flags & FLAT_FLAG_GZDATA) {
639663
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
641666
result = decompress_exec(bprm, text_len, (char *) datapos,
642667
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+
}
644681
#endif
682+
}
683+
} else
684+
#endif /* CONFIG_BINFMT_ZFLAT */
645685
{
646686
result = read_code(bprm->file, textpos, 0, text_len);
647687
if (!IS_ERR_VALUE(result))

0 commit comments

Comments
 (0)