18 #include <linux/export.h>
19 #include <linux/kernel.h>
20 #include <linux/sched.h>
22 #include <linux/mman.h>
23 #include <linux/errno.h>
24 #include <linux/signal.h>
25 #include <linux/string.h>
28 #include <linux/stat.h>
29 #include <linux/fcntl.h>
30 #include <linux/ptrace.h>
32 #include <linux/slab.h>
33 #include <linux/binfmts.h>
34 #include <linux/personality.h>
36 #include <linux/flat.h>
39 #include <asm/byteorder.h>
40 #include <asm/uaccess.h>
41 #include <asm/unaligned.h>
42 #include <asm/cacheflush.h>
52 #define DBG_FLT(a...) printk(a)
63 #define FLAT_DATA_ALIGN (0x20)
70 #define FLAT_STACK_ALIGN max_t(unsigned long, sizeof(void *), ARCH_SLAB_MINALIGN)
72 #define RELOC_FAILED 0xff00ff01
73 #define UNLOADED_LIB 0x7ff000ff
87 #ifdef CONFIG_BINFMT_SHARED_FLAT
88 static int load_flat_shared_library(
int id,
struct lib_info *
p);
96 .load_binary = load_flat_binary,
97 .core_dump = flat_core_dump,
109 printk(
"Process %s:%d received signr %d and should have core dumped\n",
121 static unsigned long create_flat_tables(
125 unsigned long *argv,*envp;
127 char *
p = (
char*)pp;
129 int envc = bprm->
envc;
132 sp = (
unsigned long *)p;
136 envp = argv + (argc + 1);
139 put_user((
unsigned long) envp, sp + 2);
140 put_user((
unsigned long) argv, sp + 1);
146 put_user((
unsigned long) p, argv++);
154 put_user((
unsigned long)p, envp); envp++;
161 return (
unsigned long)
sp;
166 #ifdef CONFIG_BINFMT_ZFLAT
170 #define LBUFSIZE 4000
173 #define ASCII_FLAG 0x01
174 #define CONTINUATION 0x02
175 #define EXTRA_FIELD 0x04
176 #define ORIG_NAME 0x08
178 #define ENCRYPTED 0x20
179 #define RESERVED 0xC0
181 static int decompress_exec(
193 DBG_FLT(
"decompress_exec(offset=%x,buf=%x,len=%x)\n",(
int)offset, (
int)dst, (
int)len);
195 memset(&strm, 0,
sizeof(strm));
198 DBG_FLT(
"binfmt_flat: no memory for decompress workspace\n");
203 DBG_FLT(
"binfmt_flat: no memory for read buffer\n");
210 ret = bprm->
file->f_op->read(bprm->
file, buf, LBUFSIZE, &fpos);
220 DBG_FLT(
"binfmt_flat: file too small?\n");
225 if ((buf[0] != 037) || ((buf[1] != 0213) && (buf[1] != 0236))) {
226 DBG_FLT(
"binfmt_flat: unknown compression magic?\n");
232 DBG_FLT(
"binfmt_flat: unknown compression method?\n");
236 if ((buf[3] & ENCRYPTED) || (buf[3] & CONTINUATION) ||
237 (buf[3] & RESERVED)) {
238 DBG_FLT(
"binfmt_flat: unknown flags?\n");
243 if (buf[3] & EXTRA_FIELD) {
244 ret += 2 + buf[10] + (buf[11] << 8);
246 DBG_FLT(
"binfmt_flat: buffer overflow (EXTRA)?\n");
250 if (buf[3] & ORIG_NAME) {
251 while (ret < LBUFSIZE && buf[ret++] != 0)
254 DBG_FLT(
"binfmt_flat: buffer overflow (ORIG_NAME)?\n");
259 while (ret < LBUFSIZE && buf[ret++] != 0)
262 DBG_FLT(
"binfmt_flat: buffer overflow (COMMENT)?\n");
275 DBG_FLT(
"binfmt_flat: zlib init failed?\n");
280 ret = bprm->
file->f_op->read(bprm->
file, buf, LBUFSIZE, &fpos);
291 DBG_FLT(
"binfmt_flat: decompression failed (%d), %s\n",
311 calc_reloc(
unsigned long r,
struct lib_info *p,
int curid,
int internalp)
315 unsigned long start_brk;
316 unsigned long start_data;
317 unsigned long text_len;
318 unsigned long start_code;
320 #ifdef CONFIG_BINFMT_SHARED_FLAT
324 id = (r >> 24) & 0xff;
328 printk(
"BINFMT_FLAT: reference 0x%x to shared library %d",
334 printk(
"BINFMT_FLAT: reloc address 0x%x not in same module "
335 "(%d != %d)", (
unsigned) r, curid,
id);
337 }
else if ( ! p->
lib_list[
id].loaded &&
339 printk(
"BINFMT_FLAT: failed to load library %d",
id);
345 printk(
"BINFMT_FLAT: library %d is younger than %d",
id, curid);
359 printk(
"BINFMT_FLAT: reloc outside program 0x%x (0 - 0x%x/0x%x)",
360 (
int) r,(
int)(start_brk-start_data+text_len),(
int)text_len);
365 addr = r + start_code;
367 addr = r - text_len + start_data;
384 char *
segment[] = {
"TEXT",
"DATA",
"BSS",
"*UNKNOWN*" };
390 #if defined(CONFIG_COLDFIRE)
391 ptr = (
unsigned long *) (
current->mm->start_code + r.
reloc.offset);
393 ptr = (
unsigned long *) (
current->mm->start_data + r.
reloc.offset);
397 printk(
"Relocation of variable at DATASEG+%x "
398 "(address %p, currently %x) into segment %s\n",
399 r.
reloc.offset, ptr, (
int)*ptr, segment[r.
reloc.type]);
402 switch (r.
reloc.type) {
404 *ptr +=
current->mm->start_code;
407 *ptr +=
current->mm->start_data;
413 printk(
"BINFMT_FLAT: Unknown relocation type=%x\n", r.
reloc.type);
418 printk(
"Relocation became %x\n", (
int)*ptr);
425 struct lib_info *libinfo,
int id,
unsigned long *extra_stack)
428 unsigned long textpos = 0, datapos = 0,
result;
429 unsigned long realdatastart = 0;
431 unsigned long len, memp = 0;
432 unsigned long memp_size,
extra, rlim;
433 unsigned long *reloc = 0, *
rp;
435 int i,
rev, relocs = 0;
437 unsigned long start_code, end_code;
441 inode = bprm->
file->f_path.dentry->d_inode;
448 stack_len += *extra_stack;
449 *extra_stack = stack_len;
471 printk(
"BINFMT_FLAT: bad flat file version 0x%x (supported "
472 "0x%lx and 0x%lx)\n",
480 printk(
"BINFMT_FLAT: shared libraries are not available before rev 0x%x\n",
493 #ifndef CONFIG_BINFMT_ZFLAT
495 printk(
"Support for ZFLAT executables is not enabled.\n");
509 if (data_len + bss_len > rlim) {
530 extra =
max_t(
unsigned long, bss_len + stack_len,
531 relocs *
sizeof(
unsigned long));
543 DBG_FLT(
"BINFMT_FLAT: ROM mapping of file (we hope)\n");
550 printk(
"Unable to mmap process text, errno %d\n", (
int)-textpos);
557 realdatastart =
vm_mmap(0, 0, len,
560 if (realdatastart == 0 ||
IS_ERR_VALUE(realdatastart)) {
563 printk(
"Unable to allocate RAM for process data, errno %d\n",
564 (
int)-realdatastart);
569 datapos =
ALIGN(realdatastart +
573 DBG_FLT(
"BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n",
574 (
int)(data_len + bss_len + stack_len), (
int)datapos);
577 #ifdef CONFIG_BINFMT_ZFLAT
579 result = decompress_exec(bprm, fpos, (
char *) datapos,
580 data_len + (relocs *
sizeof(
unsigned long)), 0);
585 data_len + (relocs *
sizeof(
unsigned long)), &fpos);
588 printk(
"Unable to read data+bss, errno %d\n", (
int)-
result);
596 memp = realdatastart;
608 printk(
"Unable to allocate RAM for process text/data, errno %d\n",
615 datapos =
ALIGN(realdatastart +
619 reloc = (
unsigned long *)
623 #ifdef CONFIG_BINFMT_ZFLAT
629 (((
char *) textpos) +
sizeof (
struct flat_hdr)),
630 (text_len + data_len + (relocs *
sizeof(
unsigned long))
633 memmove((
void *) datapos, (
void *) realdatastart,
634 data_len + (relocs *
sizeof(
unsigned long)));
635 }
else if (flags & FLAT_FLAG_GZDATA) {
638 (
char *) textpos, text_len, &fpos);
640 result = decompress_exec(bprm, text_len, (
char *) datapos,
641 data_len + (relocs *
sizeof(
unsigned long)), 0);
648 (
char *) textpos, text_len, &fpos);
652 data_len + (relocs *
sizeof(
unsigned long)), &fpos);
656 printk(
"Unable to read code+data+bss, errno %d\n",(
int)-
result);
657 vm_munmap(textpos, text_len + data_len + extra +
664 if (flags & FLAT_FLAG_KTRACE)
665 printk(
"Mapping is %x, Entry point is %x, data_start is %x\n",
669 start_code = textpos +
sizeof (
struct flat_hdr);
670 end_code = textpos + text_len;
672 current->mm->start_code = start_code;
673 current->mm->end_code = end_code;
674 current->mm->start_data = datapos;
683 current->mm->start_brk = datapos + data_len + bss_len;
685 current->mm->context.end_brk = memp + memp_size - stack_len;
688 if (flags & FLAT_FLAG_KTRACE)
689 printk(
"%s %s: TEXT=%x-%x DATA=%x-%x BSS=%x-%x\n",
690 id ?
"Lib" :
"Load", bprm->
filename,
691 (
int) start_code, (
int) end_code,
693 (
int) (datapos + data_len),
694 (
int) (datapos + data_len),
695 (
int) (((datapos + data_len + bss_len) + 3) & ~3));
697 text_len -=
sizeof(
struct flat_hdr);
700 libinfo->
lib_list[
id].start_code = start_code;
702 libinfo->
lib_list[
id].start_brk = datapos + data_len + bss_len;
721 for (
rp = (
unsigned long *)datapos; *
rp != 0xffffffff;
rp++) {
724 addr = calc_reloc(*
rp, libinfo,
id, 0);
746 unsigned long persistent = 0;
747 for (i=0; i < relocs; i++) {
748 unsigned long addr, relval;
753 relval =
ntohl(reloc[i]);
757 rp = (
unsigned long *) calc_reloc(addr, libinfo,
id, 1);
771 if ((flags & FLAT_FLAG_GOTPIC) == 0)
773 addr = calc_reloc(addr, libinfo,
id, 0);
784 for (i=0; i < relocs; i++)
791 memset((
void*)(datapos + data_len), 0, bss_len +
792 (memp + memp_size - stack_len -
803 #ifdef CONFIG_BINFMT_SHARED_FLAT
810 static int load_flat_shared_library(
int id,
struct lib_info *libs)
816 memset(&bprm, 0,
sizeof(bprm));
819 sprintf(buf,
"/lib/lib%d.so",
id);
824 res = PTR_ERR(bprm.
file);
825 if (IS_ERR(bprm.
file))
842 res = load_flat_file(&bprm, libs,
id,
NULL);
847 allow_write_access(bprm.
file);
864 unsigned long p = bprm->
p;
865 unsigned long stack_len;
871 memset(&libinfo, 0,
sizeof(libinfo));
879 #define TOP_OF_ARGS (PAGE_SIZE * MAX_ARG_PAGES - sizeof(void *))
881 stack_len += (bprm->
argc + 1) *
sizeof(
char *);
882 stack_len += (bprm->
envc + 1) *
sizeof(
char *);
885 res = load_flat_file(bprm, &libinfo, 0, &stack_len);
893 (-(j+1))[(
unsigned long *)(libinfo.
lib_list[i].start_data)] =
901 p = ((
current->mm->context.end_brk + stack_len + 3) & ~3) - 4;
905 for (i = TOP_OF_ARGS - 1; i >= bprm->
p; i--)
909 sp = (
unsigned long *) create_flat_tables(p, bprm);
915 start_addr = libinfo.
lib_list[0].entry;
917 #ifdef CONFIG_BINFMT_SHARED_FLAT
918 for (i = MAX_SHARED_LIBS-1; i>0; i--) {
930 #ifdef FLAT_PLAT_INIT
933 DBG_FLT(
"start_thread(regs=0x%x, entry=0x%x, start_stack=0x%x)\n",
934 (
int)regs, (
int)start_addr, (
int)
current->mm->start_stack);
943 static int __init init_flat_binfmt(
void)
945 register_binfmt(&flat_format);