2 * linux/fs/binfmt_flat.c
4 * Copyright (C) 2000, 2001 Lineo, by David McCullough <davidm@uclinux.org>
5 * Copyright (C) 2002 Greg Ungerer <gerg@snapgear.com>
9 * linux/fs/binfmt_aout.c:
10 * Copyright (C) 1991, 1992, 1996 Linus Torvalds
11 * linux/fs/binfmt_flat.c for 2.0 kernel
12 * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
13 * JAN/99 -- coded full program relocation (gerg@snapgear.com)
16 #include <linux/module.h>
17 #include <linux/config.h>
18 #include <linux/kernel.h>
19 #include <linux/sched.h>
21 #include <linux/mman.h>
22 #include <linux/a.out.h>
23 #include <linux/errno.h>
24 #include <linux/signal.h>
25 #include <linux/string.h>
27 #include <linux/file.h>
28 #include <linux/stat.h>
29 #include <linux/fcntl.h>
30 #include <linux/ptrace.h>
31 #include <linux/user.h>
32 #include <linux/slab.h>
33 #include <linux/binfmts.h>
34 #include <linux/personality.h>
35 #include <linux/init.h>
36 #include <linux/flat.h>
38 #include <asm/byteorder.h>
39 #include <asm/system.h>
40 #include <asm/uaccess.h>
41 #include <asm/pgalloc.h>
42 #include <asm/unaligned.h>
43 #include <asm/cacheflush.h>
47 #define DBG_FLT(a...) printk(##a)
52 static int load_flat_binary(struct linux_binprm
*, struct pt_regs
* regs
);
53 static int load_flat_library(struct file
*);
54 extern void dump_thread(struct pt_regs
*, struct user
*);
56 static struct linux_binfmt flat_format
= {
57 NULL
, THIS_MODULE
, load_flat_binary
, load_flat_library
, NULL
, PAGE_SIZE
62 * create_flat_tables() parses the env- and arg-strings in new user
63 * memory and creates the pointer tables from them, and puts their
64 * addresses on the "stack", returning the new stack pointer value.
66 static unsigned long create_flat_tables(
68 struct linux_binprm
* bprm
)
70 unsigned long *argv
,*envp
;
73 int argc
= bprm
->argc
;
74 int envc
= bprm
->envc
;
77 sp
= (unsigned long *) ((-(unsigned long)sizeof(char *))&(unsigned long) p
);
83 put_user((unsigned long) envp
, --sp
);
84 put_user((unsigned long) argv
, --sp
);
86 current
->mm
->arg_start
= (unsigned long) p
;
88 put_user((unsigned long) p
, argv
++);
90 get_user(dummy
, p
); p
++;
93 put_user((unsigned long) NULL
, argv
);
94 current
->mm
->arg_end
= current
->mm
->env_start
= (unsigned long) p
;
96 put_user((unsigned long)p
, envp
); envp
++;
98 get_user(dummy
, p
); p
++;
101 put_user((unsigned long) NULL
, envp
);
102 current
->mm
->env_end
= (unsigned long) p
;
103 return (unsigned long)sp
;
107 #ifdef CONFIG_BINFMT_ZFLAT
109 #include <linux/zlib.h>
111 #define LBUFSIZE 4000
114 #define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
115 #define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
116 #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
117 #define ORIG_NAME 0x08 /* bit 3 set: original file name present */
118 #define COMMENT 0x10 /* bit 4 set: file comment present */
119 #define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
120 #define RESERVED 0xC0 /* bit 6,7: reserved */
122 static int decompress_exec(
123 struct linux_binprm
*bprm
,
124 unsigned long offset
,
134 DBG_FLT("decompress_exec(offset=%x,buf=%x,len=%x)\n",(int)offset
, (int)dst
, (int)len
);
136 memset(&strm
, 0, sizeof(strm
));
137 strm
.workspace
= kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL
);
138 if (strm
.workspace
== NULL
) {
139 DBG_FLT("binfmt_flat: no memory for decompress workspace\n");
142 buf
= kmalloc(LBUFSIZE
, GFP_KERNEL
);
144 DBG_FLT("binfmt_flat: no memory for read buffer\n");
148 /* Read in first chunk of data and parse gzip header. */
150 ret
= bprm
->file
->f_op
->read(bprm
->file
, buf
, LBUFSIZE
, &fpos
);
156 /* Check minimum size -- gzip header */
158 DBG_FLT("binfmt_flat: file too small?\n");
162 /* Check gzip magic number */
163 if ((buf
[0] != 037) || ((buf
[1] != 0213) && (buf
[1] != 0236))) {
164 DBG_FLT("binfmt_flat: unknown compression magic?\n");
168 /* Check gzip method */
170 DBG_FLT("binfmt_flat: unknown compression method?\n");
173 /* Check gzip flags */
174 if ((buf
[3] & ENCRYPTED
) || (buf
[3] & CONTINUATION
) ||
175 (buf
[3] & RESERVED
)) {
176 DBG_FLT("binfmt_flat: unknown flags?\n");
181 if (buf
[3] & EXTRA_FIELD
)
182 ret
+= 2 + buf
[10] + (buf
[11] << 8);
183 if (buf
[3] & ORIG_NAME
) {
184 for (; (buf
[ret
] != 0); ret
++)
187 if (buf
[3] & COMMENT
) {
188 for (; (buf
[ret
] != 0); ret
++)
193 strm
.avail_in
-= ret
;
196 strm
.avail_out
= len
;
199 if (zlib_inflateInit2(&strm
, -MAX_WBITS
) != Z_OK
) {
200 DBG_FLT("binfmt_flat: zlib init failed?\n");
204 while ((ret
= zlib_inflate(&strm
, Z_NO_FLUSH
)) == Z_OK
) {
205 ret
= bprm
->file
->f_op
->read(bprm
->file
, buf
, LBUFSIZE
, &fpos
);
208 if (ret
>= (unsigned long) -4096)
218 DBG_FLT("binfmt_flat: decompression failed (%d), %s\n",
223 zlib_inflateEnd(&strm
);
225 kfree(strm
.workspace
);
229 #endif /* CONFIG_BINFMT_ZFLAT */
233 calc_reloc(unsigned long r
, unsigned long text_len
)
237 if (r
> current
->mm
->start_brk
- current
->mm
->start_data
+ text_len
) {
238 printk("BINFMT_FLAT: reloc outside program 0x%x (0 - 0x%x), killing!\n",
239 (int) r
,(int)(current
->mm
->start_brk
-current
->mm
->start_code
));
240 send_sig(SIGSEGV
, current
, 0);
241 return(current
->mm
->start_brk
); /* return something safe to write to */
245 /* In text segment */
246 return r
+ current
->mm
->start_code
;
250 * we allow inclusive ranges here so that programs may do things
251 * like reference the end of data (_end) without failing these tests
253 addr
= r
- text_len
+ current
->mm
->start_data
;
254 if (addr
>= current
->mm
->start_code
&&
255 addr
<= current
->mm
->start_code
+ text_len
)
258 if (addr
>= current
->mm
->start_data
&&
259 addr
<= current
->mm
->start_brk
)
262 printk("BINFMT_FLAT: reloc addr outside text/data 0x%x "
263 "code(0x%x - 0x%x) data(0x%x - 0x%x) killing\n", (int) addr
,
264 (int) current
->mm
->start_code
,
265 (int) (current
->mm
->start_code
+ text_len
),
266 (int) current
->mm
->start_data
,
267 (int) current
->mm
->start_brk
);
268 send_sig(SIGSEGV
, current
, 0);
270 return(current
->mm
->start_brk
); /* return something safe to write to */
274 void old_reloc(unsigned long rl
)
277 char *segment
[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" };
283 #if defined(CONFIG_COLDFIRE)
284 ptr
= (unsigned long *) (current
->mm
->start_code
+ r
.reloc
.offset
);
286 ptr
= (unsigned long *) (current
->mm
->start_data
+ r
.reloc
.offset
);
290 printk("Relocation of variable at DATASEG+%x "
291 "(address %p, currently %x) into segment %s\n",
292 r
.reloc
.offset
, ptr
, (int)*ptr
, segment
[r
.reloc
.type
]);
295 switch (r
.reloc
.type
) {
296 case OLD_FLAT_RELOC_TYPE_TEXT
:
297 *ptr
+= current
->mm
->start_code
;
299 case OLD_FLAT_RELOC_TYPE_DATA
:
300 *ptr
+= current
->mm
->start_data
;
302 case OLD_FLAT_RELOC_TYPE_BSS
:
303 *ptr
+= current
->mm
->end_data
;
306 printk("BINFMT_FLAT: Unknown relocation type=%x\n", r
.reloc
.type
);
311 printk("Relocation became %x\n", (int)*ptr
);
317 * These are the functions used to load flat style executables and shared
318 * libraries. There is no binary dependent code anywhere else.
321 static int load_flat_binary(struct linux_binprm
* bprm
, struct pt_regs
* regs
)
323 struct flat_hdr
* hdr
;
324 unsigned long textpos
= 0, datapos
= 0, result
;
325 unsigned long text_len
, data_len
, bss_len
, stack_len
, flags
;
326 unsigned long memp
= 0, memkasked
= 0; /* for finding the brk area */
327 unsigned long extra
, rlim
;
328 unsigned long p
= bprm
->p
;
329 unsigned long *reloc
= 0, *rp
;
331 int i
, rev
, relocs
= 0;
334 DBG_FLT("BINFMT_FLAT: Loading file: %x\n", bprm
->file
);
336 hdr
= ((struct flat_hdr
*) bprm
->buf
); /* exec-header */
337 inode
= bprm
->file
->f_dentry
->d_inode
;
339 text_len
= ntohl(hdr
->data_start
);
340 data_len
= ntohl(hdr
->data_end
) - ntohl(hdr
->data_start
);
341 bss_len
= ntohl(hdr
->bss_end
) - ntohl(hdr
->data_end
);
342 stack_len
= ntohl(hdr
->stack_size
);
343 relocs
= ntohl(hdr
->reloc_count
);
344 flags
= ntohl(hdr
->flags
);
345 rev
= ntohl(hdr
->rev
);
348 * We have to add the size of our arguments to our stack size
349 * otherwise it's too easy for users to create stack overflows
350 * by passing in a huge argument list. And yes, we have to be
351 * pedantic and include space for the argv/envp array as it may have
354 #define TOP_OF_ARGS (PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *))
355 stack_len
+= TOP_OF_ARGS
- bprm
->p
; /* the strings */
356 stack_len
+= (bprm
->argc
+ 1) * sizeof(char *); /* the argv array */
357 stack_len
+= (bprm
->envc
+ 1) * sizeof(char *); /* the envp array */
359 if (strncmp(hdr
->magic
, "bFLT", 4) ||
360 (rev
!= FLAT_VERSION
&& rev
!= OLD_FLAT_VERSION
)) {
362 * because a lot of people do not manage to produce good
363 * flat binaries, we leave this printk to help them realise
364 * the problem. We only print the error if its * not a script file
366 if (strncmp(hdr
->magic
, "#!", 2))
367 printk("BINFMT_FLAT: bad magic/rev (0x%x, need 0x%x)\n",
368 rev
, (int) FLAT_VERSION
);
373 * fix up the flags for the older format, there were all kinds
374 * of endian hacks, this only works for the simple cases
376 if (rev
== OLD_FLAT_VERSION
&& flags
)
377 flags
= FLAT_FLAG_RAM
;
379 #ifndef CONFIG_BINFMT_ZFLAT
380 if (flags
& (FLAT_FLAG_GZIP
|FLAT_FLAG_GZDATA
)) {
381 printk("Support for ZFLAT executables is not enabled.\n");
387 * Check initial limits. This avoids letting people circumvent
388 * size limits imposed on them by creating programs with large
389 * arrays in the data or bss.
391 rlim
= current
->rlim
[RLIMIT_DATA
].rlim_cur
;
392 if (rlim
>= RLIM_INFINITY
)
394 if (data_len
+ bss_len
> rlim
)
397 /* Flush all traces of the currently running executable */
398 result
= flush_old_exec(bprm
);
402 /* OK, This is the point of no return */
403 set_personality(PER_LINUX
);
406 * there are a couple of cases here, the seperate code/data
407 * case, and then the fully copied to RAM case which lumps
410 if ((flags
& (FLAT_FLAG_RAM
|FLAT_FLAG_GZIP
)) == 0) {
412 * this should give us a ROM ptr, but if it doesn't we don't
415 DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
417 down_write(¤t
->mm
->mmap_sem
);
418 textpos
= do_mmap(bprm
->file
, 0, text_len
, PROT_READ
|PROT_EXEC
, 0, 0);
419 up_write(¤t
->mm
->mmap_sem
);
420 if (!textpos
|| textpos
>= (unsigned long) -4096) {
422 textpos
= (unsigned long) -ENOMEM
;
423 printk("Unable to mmap process text, errno %d\n", (int)-textpos
);
426 extra
= max(bss_len
+ stack_len
, relocs
* sizeof(unsigned long)),
428 down_write(¤t
->mm
->mmap_sem
);
429 datapos
= do_mmap(0, 0, data_len
+ extra
,
430 PROT_READ
|PROT_WRITE
|PROT_EXEC
, 0, 0);
431 up_write(¤t
->mm
->mmap_sem
);
433 if (datapos
== 0 || datapos
>= (unsigned long)-4096) {
435 datapos
= (unsigned long) -ENOMEM
;
436 printk("Unable to allocate RAM for process data, errno %d\n",
438 do_munmap(current
->mm
, textpos
, text_len
);
442 DBG_FLT("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n",
443 data_len
+ bss_len
+ stack_len
, datapos
);
445 fpos
= ntohl(hdr
->data_start
);
446 #ifdef CONFIG_BINFMT_ZFLAT
447 if (flags
& FLAT_FLAG_GZDATA
) {
448 result
= decompress_exec(bprm
, fpos
, (char *) datapos
,
449 data_len
+ (relocs
* sizeof(unsigned long)), 0);
453 result
= bprm
->file
->f_op
->read(bprm
->file
,
454 (char *) datapos
, data_len
+ extra
, &fpos
);
456 if (result
>= (unsigned long)-4096) {
457 printk("Unable to read data+bss, errno %d\n", (int)-result
);
458 do_munmap(current
->mm
, textpos
, text_len
);
459 do_munmap(current
->mm
, datapos
, data_len
+ extra
);
463 reloc
= (unsigned long *) (datapos
+(ntohl(hdr
->reloc_start
)-text_len
));
465 memkasked
= data_len
+ extra
;
470 * calculate the extra space we need to map in
473 extra
= max(bss_len
+ stack_len
, relocs
* sizeof(unsigned long)),
475 down_write(¤t
->mm
->mmap_sem
);
476 textpos
= do_mmap(0, 0, text_len
+ data_len
+ extra
,
477 PROT_READ
| PROT_EXEC
| PROT_WRITE
, 0, 0);
478 up_write(¤t
->mm
->mmap_sem
);
479 if (!textpos
|| textpos
>= (unsigned long) -4096) {
481 textpos
= (unsigned long) -ENOMEM
;
482 printk("Unable to allocate RAM for process text/data, errno %d\n",
486 datapos
= textpos
+ ntohl (hdr
->data_start
);
487 reloc
= (unsigned long *) (textpos
+ ntohl(hdr
->reloc_start
));
489 memkasked
= text_len
+ data_len
+ extra
;
491 #ifdef CONFIG_BINFMT_ZFLAT
493 * load it all in and treat it like a RAM load from now on
495 if (flags
& FLAT_FLAG_GZIP
) {
496 result
= decompress_exec(bprm
, sizeof (struct flat_hdr
),
497 (((char *) textpos
) + sizeof (struct flat_hdr
)),
498 (text_len
+ data_len
+ (relocs
* sizeof(unsigned long))
499 - sizeof (struct flat_hdr
)),
501 } else if (flags
& FLAT_FLAG_GZDATA
) {
503 result
= bprm
->file
->f_op
->read(bprm
->file
,
504 (char *) textpos
, text_len
, &fpos
);
505 if (result
< (unsigned long) -4096)
506 result
= decompress_exec(bprm
, text_len
, (char *) datapos
,
507 data_len
+ (relocs
* sizeof(unsigned long)), 0);
513 result
= bprm
->file
->f_op
->read(bprm
->file
,
514 (char *) textpos
, text_len
+ data_len
+ extra
, &fpos
);
516 if (result
>= (unsigned long)-4096) {
517 printk("Unable to read code+data+bss, errno %d\n",(int)-result
);
518 do_munmap(current
->mm
, textpos
, text_len
+ data_len
+ extra
);
523 DBG_FLT("Mapping is %x, Entry point is %x, data_start is %x\n",
524 textpos
, ntohl(hdr
->entry
), ntohl(hdr
->data_start
));
526 current
->mm
->start_code
= textpos
+ sizeof (struct flat_hdr
);
527 current
->mm
->end_code
= textpos
+ text_len
;
528 current
->mm
->start_data
= datapos
;
529 current
->mm
->end_data
= datapos
+ data_len
;
531 * set up the brk stuff (uses any slack left in data/bss/stack allocation
532 * We put the brk after the bss (between the bss and stack) like other
535 current
->mm
->start_brk
= datapos
+ data_len
+ bss_len
;
536 current
->mm
->brk
= (current
->mm
->start_brk
+ 3) & ~3;
537 current
->mm
->context
.end_brk
= memp
+ ksize((void *) memp
) - stack_len
;
538 current
->mm
->rss
= 0;
540 DBG_FLT("Load %s: TEXT=%x-%x DATA=%x-%x BSS=%x-%x\n",
542 (int) current
->mm
->start_code
, (int) current
->mm
->end_code
,
543 (int) current
->mm
->start_data
, (int) current
->mm
->end_data
,
544 (int) current
->mm
->end_data
, (int) current
->mm
->brk
);
546 text_len
-= sizeof(struct flat_hdr
); /* the real code len */
549 * We just load the allocations into some temporary memory to
550 * help simplify all this mumbo jumbo
552 * We've got two different sections of relocation entries.
553 * The first is the GOT which resides at the begining of the data segment
554 * and is terminated with a -1. This one can be relocated in place.
555 * The second is the extra relocation entries tacked after the image's
556 * data segment. These require a little more processing as the entry is
557 * really an offset into the image which contains an offset into the
561 if (flags
& FLAT_FLAG_GOTPIC
) {
562 for (rp
= (unsigned long *)datapos
; *rp
!= 0xffffffff; rp
++)
563 *rp
= calc_reloc(*rp
, text_len
);
567 * Now run through the relocation entries.
568 * We've got to be careful here as C++ produces relocatable zero
569 * entries in the constructor and destructor tables which are then
570 * tested for being not zero (which will always occur unless we're
571 * based from address zero). This causes an endless loop as __start
572 * is at zero. The solution used is to not relocate zero addresses.
573 * This has the negative side effect of not allowing a global data
574 * reference to be statically initialised to _stext (I've moved
575 * __start to address 4 so that is okay).
578 if (rev
> OLD_FLAT_VERSION
) {
579 for (i
=0; i
< relocs
; i
++) {
582 /* Get the address of the pointer to be
583 relocated (of course, the address has to be
585 rp
= (unsigned long *) calc_reloc(ntohl(reloc
[i
]), text_len
);
587 /* Get the pointer's value. */
588 addr
= get_unaligned (rp
);
592 * Do the relocation. PIC relocs in the data section are
593 * already in target order
596 (flags
& FLAT_FLAG_GOTPIC
) ? addr
: ntohl(addr
),
598 /* Write back the relocated pointer. */
599 put_unaligned (addr
, rp
);
603 for (i
=0; i
< relocs
; i
++)
604 old_reloc(ntohl(reloc
[i
]));
607 /* zero the BSS, BRK and stack areas */
608 memset((void*)(datapos
+ data_len
), 0, bss_len
+
609 (current
->mm
->context
.end_brk
- current
->mm
->start_brk
) +
613 current
->flags
&= ~PF_FORKNOEXEC
;
615 flush_icache_range(current
->mm
->start_code
, current
->mm
->end_code
);
617 set_binfmt(&flat_format
);
619 p
= ((current
->mm
->context
.end_brk
+ stack_len
+ 3) & ~3) - 4;
620 DBG_FLT("p=%x\n", p
);
622 /* copy the arg pages onto the stack, this could be more efficient :-) */
623 for (i
= TOP_OF_ARGS
- 1; i
>= bprm
->p
; i
--)
625 ((char *) page_address(bprm
->page
[i
/PAGE_SIZE
]))[i
% PAGE_SIZE
];
627 current
->mm
->start_stack
= (unsigned long) create_flat_tables(p
, bprm
);
629 DBG_FLT("start_thread(regs=0x%x, entry=0x%x, start_stack=0x%x)\n",
630 regs
, textpos
+ ntohl(hdr
->entry
), current
->mm
->start_stack
);
632 textpos
+ ntohl(hdr
->entry
),
633 current
->mm
->start_stack
);
635 if (current
->ptrace
& PT_PTRACED
)
636 send_sig(SIGTRAP
, current
, 0);
641 static int load_flat_library(struct file
*file
)
646 static int __init
init_flat_binfmt(void)
648 return register_binfmt(&flat_format
);
651 static void __exit
exit_flat_binfmt(void)
653 unregister_binfmt(&flat_format
);
658 module_init(init_flat_binfmt
);
659 module_exit(exit_flat_binfmt
);