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 if (flat_argvp_envp_on_stack()) {
84 put_user((unsigned long) envp
, --sp
);
85 put_user((unsigned long) argv
, --sp
);
88 current
->mm
->arg_start
= (unsigned long) p
;
90 put_user((unsigned long) p
, argv
++);
92 get_user(dummy
, p
); p
++;
95 put_user((unsigned long) NULL
, argv
);
96 current
->mm
->arg_end
= current
->mm
->env_start
= (unsigned long) p
;
98 put_user((unsigned long)p
, envp
); envp
++;
100 get_user(dummy
, p
); p
++;
103 put_user((unsigned long) NULL
, envp
);
104 current
->mm
->env_end
= (unsigned long) p
;
105 return (unsigned long)sp
;
109 #ifdef CONFIG_BINFMT_ZFLAT
111 #include <linux/zlib.h>
113 #define LBUFSIZE 4000
116 #define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
117 #define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
118 #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
119 #define ORIG_NAME 0x08 /* bit 3 set: original file name present */
120 #define COMMENT 0x10 /* bit 4 set: file comment present */
121 #define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
122 #define RESERVED 0xC0 /* bit 6,7: reserved */
124 static int decompress_exec(
125 struct linux_binprm
*bprm
,
126 unsigned long offset
,
136 DBG_FLT("decompress_exec(offset=%x,buf=%x,len=%x)\n",(int)offset
, (int)dst
, (int)len
);
138 memset(&strm
, 0, sizeof(strm
));
139 strm
.workspace
= kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL
);
140 if (strm
.workspace
== NULL
) {
141 DBG_FLT("binfmt_flat: no memory for decompress workspace\n");
144 buf
= kmalloc(LBUFSIZE
, GFP_KERNEL
);
146 DBG_FLT("binfmt_flat: no memory for read buffer\n");
150 /* Read in first chunk of data and parse gzip header. */
152 ret
= bprm
->file
->f_op
->read(bprm
->file
, buf
, LBUFSIZE
, &fpos
);
158 /* Check minimum size -- gzip header */
160 DBG_FLT("binfmt_flat: file too small?\n");
164 /* Check gzip magic number */
165 if ((buf
[0] != 037) || ((buf
[1] != 0213) && (buf
[1] != 0236))) {
166 DBG_FLT("binfmt_flat: unknown compression magic?\n");
170 /* Check gzip method */
172 DBG_FLT("binfmt_flat: unknown compression method?\n");
175 /* Check gzip flags */
176 if ((buf
[3] & ENCRYPTED
) || (buf
[3] & CONTINUATION
) ||
177 (buf
[3] & RESERVED
)) {
178 DBG_FLT("binfmt_flat: unknown flags?\n");
183 if (buf
[3] & EXTRA_FIELD
) {
184 ret
+= 2 + buf
[10] + (buf
[11] << 8);
185 if (unlikely(LBUFSIZE
== ret
)) {
186 DBG_FLAT("binfmt_flat: buffer overflow (EXTRA)?\n");
190 if (buf
[3] & ORIG_NAME
) {
191 for (; ret
< LBUFSIZE
&& (buf
[ret
] != 0); ret
++)
193 if (unlikely(LBUFSIZE
== ret
)) {
194 DBG_FLAT("binfmt_flat: buffer overflow (ORIG_NAME)?\n");
198 if (buf
[3] & COMMENT
) {
199 for (; ret
< LBUFSIZE
&& (buf
[ret
] != 0); ret
++)
201 if (unlikely(LBUFSIZE
== ret
)) {
202 DBG_FLAT("binfmt_flat: buffer overflow (COMMENT)?\n");
208 strm
.avail_in
-= ret
;
211 strm
.avail_out
= len
;
214 if (zlib_inflateInit2(&strm
, -MAX_WBITS
) != Z_OK
) {
215 DBG_FLT("binfmt_flat: zlib init failed?\n");
219 while ((ret
= zlib_inflate(&strm
, Z_NO_FLUSH
)) == Z_OK
) {
220 ret
= bprm
->file
->f_op
->read(bprm
->file
, buf
, LBUFSIZE
, &fpos
);
223 if (ret
>= (unsigned long) -4096)
233 DBG_FLT("binfmt_flat: decompression failed (%d), %s\n",
238 zlib_inflateEnd(&strm
);
240 kfree(strm
.workspace
);
244 #endif /* CONFIG_BINFMT_ZFLAT */
248 calc_reloc(unsigned long r
, unsigned long text_len
)
252 if (r
> current
->mm
->start_brk
- current
->mm
->start_data
+ text_len
) {
253 printk("BINFMT_FLAT: reloc outside program 0x%x (0 - 0x%x), killing!\n",
254 (int) r
,(int)(current
->mm
->start_brk
-current
->mm
->start_code
));
255 send_sig(SIGSEGV
, current
, 0);
256 return(current
->mm
->start_brk
); /* return something safe to write to */
260 /* In text segment */
261 return r
+ current
->mm
->start_code
;
265 * we allow inclusive ranges here so that programs may do things
266 * like reference the end of data (_end) without failing these tests
268 addr
= r
- text_len
+ current
->mm
->start_data
;
269 if (addr
>= current
->mm
->start_code
&&
270 addr
<= current
->mm
->start_code
+ text_len
)
273 if (addr
>= current
->mm
->start_data
&&
274 addr
<= current
->mm
->start_brk
)
277 printk("BINFMT_FLAT: reloc addr outside text/data 0x%x "
278 "code(0x%x - 0x%x) data(0x%x - 0x%x) killing\n", (int) addr
,
279 (int) current
->mm
->start_code
,
280 (int) (current
->mm
->start_code
+ text_len
),
281 (int) current
->mm
->start_data
,
282 (int) current
->mm
->start_brk
);
283 send_sig(SIGSEGV
, current
, 0);
285 return(current
->mm
->start_brk
); /* return something safe to write to */
289 void old_reloc(unsigned long rl
)
292 char *segment
[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" };
298 #if defined(CONFIG_COLDFIRE)
299 ptr
= (unsigned long *) (current
->mm
->start_code
+ r
.reloc
.offset
);
301 ptr
= (unsigned long *) (current
->mm
->start_data
+ r
.reloc
.offset
);
305 printk("Relocation of variable at DATASEG+%x "
306 "(address %p, currently %x) into segment %s\n",
307 r
.reloc
.offset
, ptr
, (int)*ptr
, segment
[r
.reloc
.type
]);
310 switch (r
.reloc
.type
) {
311 case OLD_FLAT_RELOC_TYPE_TEXT
:
312 *ptr
+= current
->mm
->start_code
;
314 case OLD_FLAT_RELOC_TYPE_DATA
:
315 *ptr
+= current
->mm
->start_data
;
317 case OLD_FLAT_RELOC_TYPE_BSS
:
318 *ptr
+= current
->mm
->end_data
;
321 printk("BINFMT_FLAT: Unknown relocation type=%x\n", r
.reloc
.type
);
326 printk("Relocation became %x\n", (int)*ptr
);
332 * These are the functions used to load flat style executables and shared
333 * libraries. There is no binary dependent code anywhere else.
336 static int load_flat_binary(struct linux_binprm
* bprm
, struct pt_regs
* regs
)
338 struct flat_hdr
* hdr
;
339 unsigned long textpos
= 0, datapos
= 0, result
;
340 unsigned long text_len
, data_len
, bss_len
, stack_len
, flags
;
341 unsigned long memp
= 0, memkasked
= 0; /* for finding the brk area */
342 unsigned long extra
, rlim
;
343 unsigned long p
= bprm
->p
;
344 unsigned long *reloc
= 0, *rp
;
346 int i
, rev
, relocs
= 0;
349 DBG_FLT("BINFMT_FLAT: Loading file: %x\n", bprm
->file
);
351 hdr
= ((struct flat_hdr
*) bprm
->buf
); /* exec-header */
352 inode
= bprm
->file
->f_dentry
->d_inode
;
354 text_len
= ntohl(hdr
->data_start
);
355 data_len
= ntohl(hdr
->data_end
) - ntohl(hdr
->data_start
);
356 bss_len
= ntohl(hdr
->bss_end
) - ntohl(hdr
->data_end
);
357 stack_len
= ntohl(hdr
->stack_size
);
358 relocs
= ntohl(hdr
->reloc_count
);
359 flags
= ntohl(hdr
->flags
);
360 rev
= ntohl(hdr
->rev
);
363 * We have to add the size of our arguments to our stack size
364 * otherwise it's too easy for users to create stack overflows
365 * by passing in a huge argument list. And yes, we have to be
366 * pedantic and include space for the argv/envp array as it may have
369 #define TOP_OF_ARGS (PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *))
370 stack_len
+= TOP_OF_ARGS
- bprm
->p
; /* the strings */
371 stack_len
+= (bprm
->argc
+ 1) * sizeof(char *); /* the argv array */
372 stack_len
+= (bprm
->envc
+ 1) * sizeof(char *); /* the envp array */
374 if (strncmp(hdr
->magic
, "bFLT", 4) ||
375 (rev
!= FLAT_VERSION
&& rev
!= OLD_FLAT_VERSION
)) {
377 * because a lot of people do not manage to produce good
378 * flat binaries, we leave this printk to help them realise
379 * the problem. We only print the error if it's
382 if (strncmp(hdr
->magic
, "#!", 2))
383 printk("BINFMT_FLAT: bad magic/rev (0x%x, need 0x%x)\n",
384 rev
, (int) FLAT_VERSION
);
389 * fix up the flags for the older format, there were all kinds
390 * of endian hacks, this only works for the simple cases
392 if (rev
== OLD_FLAT_VERSION
&& flags
)
393 flags
= FLAT_FLAG_RAM
;
395 #ifndef CONFIG_BINFMT_ZFLAT
396 if (flags
& (FLAT_FLAG_GZIP
|FLAT_FLAG_GZDATA
)) {
397 printk("Support for ZFLAT executables is not enabled.\n");
403 * Check initial limits. This avoids letting people circumvent
404 * size limits imposed on them by creating programs with large
405 * arrays in the data or bss.
407 rlim
= current
->rlim
[RLIMIT_DATA
].rlim_cur
;
408 if (rlim
>= RLIM_INFINITY
)
410 if (data_len
+ bss_len
> rlim
)
413 /* Flush all traces of the currently running executable */
414 result
= flush_old_exec(bprm
);
418 /* OK, This is the point of no return */
419 set_personality(PER_LINUX
);
422 * there are a couple of cases here, the separate code/data
423 * case, and then the fully copied to RAM case which lumps
426 if ((flags
& (FLAT_FLAG_RAM
|FLAT_FLAG_GZIP
)) == 0) {
428 * this should give us a ROM ptr, but if it doesn't we don't
431 DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
433 down_write(¤t
->mm
->mmap_sem
);
434 textpos
= do_mmap(bprm
->file
, 0, text_len
, PROT_READ
|PROT_EXEC
, 0, 0);
435 up_write(¤t
->mm
->mmap_sem
);
436 if (!textpos
|| textpos
>= (unsigned long) -4096) {
438 textpos
= (unsigned long) -ENOMEM
;
439 printk("Unable to mmap process text, errno %d\n", (int)-textpos
);
442 extra
= max(bss_len
+ stack_len
, relocs
* sizeof(unsigned long)),
444 down_write(¤t
->mm
->mmap_sem
);
445 datapos
= do_mmap(0, 0, data_len
+ extra
,
446 PROT_READ
|PROT_WRITE
|PROT_EXEC
, 0, 0);
447 up_write(¤t
->mm
->mmap_sem
);
449 if (datapos
== 0 || datapos
>= (unsigned long)-4096) {
451 datapos
= (unsigned long) -ENOMEM
;
452 printk("Unable to allocate RAM for process data, errno %d\n",
454 do_munmap(current
->mm
, textpos
, text_len
);
458 DBG_FLT("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n",
459 data_len
+ bss_len
+ stack_len
, datapos
);
461 fpos
= ntohl(hdr
->data_start
);
462 #ifdef CONFIG_BINFMT_ZFLAT
463 if (flags
& FLAT_FLAG_GZDATA
) {
464 result
= decompress_exec(bprm
, fpos
, (char *) datapos
,
465 data_len
+ (relocs
* sizeof(unsigned long)), 0);
469 result
= bprm
->file
->f_op
->read(bprm
->file
,
470 (char *) datapos
, data_len
+ extra
, &fpos
);
472 if (result
>= (unsigned long)-4096) {
473 printk("Unable to read data+bss, errno %d\n", (int)-result
);
474 do_munmap(current
->mm
, textpos
, text_len
);
475 do_munmap(current
->mm
, datapos
, data_len
+ extra
);
479 reloc
= (unsigned long *) (datapos
+(ntohl(hdr
->reloc_start
)-text_len
));
481 memkasked
= data_len
+ extra
;
486 * calculate the extra space we need to map in
489 extra
= max(bss_len
+ stack_len
, relocs
* sizeof(unsigned long)),
491 down_write(¤t
->mm
->mmap_sem
);
492 textpos
= do_mmap(0, 0, text_len
+ data_len
+ extra
,
493 PROT_READ
| PROT_EXEC
| PROT_WRITE
, 0, 0);
494 up_write(¤t
->mm
->mmap_sem
);
495 if (!textpos
|| textpos
>= (unsigned long) -4096) {
497 textpos
= (unsigned long) -ENOMEM
;
498 printk("Unable to allocate RAM for process text/data, errno %d\n",
502 datapos
= textpos
+ ntohl (hdr
->data_start
);
503 reloc
= (unsigned long *) (textpos
+ ntohl(hdr
->reloc_start
));
505 memkasked
= text_len
+ data_len
+ extra
;
507 #ifdef CONFIG_BINFMT_ZFLAT
509 * load it all in and treat it like a RAM load from now on
511 if (flags
& FLAT_FLAG_GZIP
) {
512 result
= decompress_exec(bprm
, sizeof (struct flat_hdr
),
513 (((char *) textpos
) + sizeof (struct flat_hdr
)),
514 (text_len
+ data_len
+ (relocs
* sizeof(unsigned long))
515 - sizeof (struct flat_hdr
)),
517 } else if (flags
& FLAT_FLAG_GZDATA
) {
519 result
= bprm
->file
->f_op
->read(bprm
->file
,
520 (char *) textpos
, text_len
, &fpos
);
521 if (result
< (unsigned long) -4096)
522 result
= decompress_exec(bprm
, text_len
, (char *) datapos
,
523 data_len
+ (relocs
* sizeof(unsigned long)), 0);
529 result
= bprm
->file
->f_op
->read(bprm
->file
,
530 (char *) textpos
, text_len
+ data_len
+ extra
, &fpos
);
532 if (result
>= (unsigned long)-4096) {
533 printk("Unable to read code+data+bss, errno %d\n",(int)-result
);
534 do_munmap(current
->mm
, textpos
, text_len
+ data_len
+ extra
);
539 DBG_FLT("Mapping is %x, Entry point is %x, data_start is %x\n",
540 textpos
, ntohl(hdr
->entry
), ntohl(hdr
->data_start
));
542 current
->mm
->start_code
= textpos
+ sizeof (struct flat_hdr
);
543 current
->mm
->end_code
= textpos
+ text_len
;
544 current
->mm
->start_data
= datapos
;
545 current
->mm
->end_data
= datapos
+ data_len
;
547 * set up the brk stuff (uses any slack left in data/bss/stack allocation
548 * We put the brk after the bss (between the bss and stack) like other
551 current
->mm
->start_brk
= datapos
+ data_len
+ bss_len
;
552 current
->mm
->brk
= (current
->mm
->start_brk
+ 3) & ~3;
553 current
->mm
->context
.end_brk
= memp
+ ksize((void *) memp
) - stack_len
;
554 current
->mm
->rss
= 0;
556 DBG_FLT("Load %s: TEXT=%x-%x DATA=%x-%x BSS=%x-%x\n",
558 (int) current
->mm
->start_code
, (int) current
->mm
->end_code
,
559 (int) current
->mm
->start_data
, (int) current
->mm
->end_data
,
560 (int) current
->mm
->end_data
, (int) current
->mm
->brk
);
562 text_len
-= sizeof(struct flat_hdr
); /* the real code len */
565 * We just load the allocations into some temporary memory to
566 * help simplify all this mumbo jumbo
568 * We've got two different sections of relocation entries.
569 * The first is the GOT which resides at the begining of the data segment
570 * and is terminated with a -1. This one can be relocated in place.
571 * The second is the extra relocation entries tacked after the image's
572 * data segment. These require a little more processing as the entry is
573 * really an offset into the image which contains an offset into the
577 if (flags
& FLAT_FLAG_GOTPIC
) {
578 for (rp
= (unsigned long *)datapos
; *rp
!= 0xffffffff; rp
++)
579 *rp
= calc_reloc(*rp
, text_len
);
583 * Now run through the relocation entries.
584 * We've got to be careful here as C++ produces relocatable zero
585 * entries in the constructor and destructor tables which are then
586 * tested for being not zero (which will always occur unless we're
587 * based from address zero). This causes an endless loop as __start
588 * is at zero. The solution used is to not relocate zero addresses.
589 * This has the negative side effect of not allowing a global data
590 * reference to be statically initialised to _stext (I've moved
591 * __start to address 4 so that is okay).
594 if (rev
> OLD_FLAT_VERSION
) {
595 for (i
=0; i
< relocs
; i
++) {
598 /* Get the address of the pointer to be
599 relocated (of course, the address has to be
601 rp
= (unsigned long *) calc_reloc(ntohl(reloc
[i
]), text_len
);
603 /* Get the pointer's value. */
604 addr
= get_unaligned (rp
);
608 * Do the relocation. PIC relocs in the data section are
609 * already in target order
612 (flags
& FLAT_FLAG_GOTPIC
) ? addr
: ntohl(addr
),
614 /* Write back the relocated pointer. */
615 put_unaligned (addr
, rp
);
619 for (i
=0; i
< relocs
; i
++)
620 old_reloc(ntohl(reloc
[i
]));
623 /* zero the BSS, BRK and stack areas */
624 memset((void*)(datapos
+ data_len
), 0, bss_len
+
625 (current
->mm
->context
.end_brk
- current
->mm
->start_brk
) +
629 current
->flags
&= ~PF_FORKNOEXEC
;
631 flush_icache_range(current
->mm
->start_code
, current
->mm
->end_code
);
633 set_binfmt(&flat_format
);
635 p
= ((current
->mm
->context
.end_brk
+ stack_len
+ 3) & ~3) - 4;
636 DBG_FLT("p=%x\n", p
);
638 /* copy the arg pages onto the stack, this could be more efficient :-) */
639 for (i
= TOP_OF_ARGS
- 1; i
>= bprm
->p
; i
--)
641 ((char *) page_address(bprm
->page
[i
/PAGE_SIZE
]))[i
% PAGE_SIZE
];
643 current
->mm
->start_stack
= (unsigned long) create_flat_tables(p
, bprm
);
645 DBG_FLT("start_thread(regs=0x%x, entry=0x%x, start_stack=0x%x)\n",
646 regs
, textpos
+ ntohl(hdr
->entry
), current
->mm
->start_stack
);
648 textpos
+ ntohl(hdr
->entry
),
649 current
->mm
->start_stack
);
651 if (current
->ptrace
& PT_PTRACED
)
652 send_sig(SIGTRAP
, current
, 0);
657 static int load_flat_library(struct file
*file
)
662 static int __init
init_flat_binfmt(void)
664 return register_binfmt(&flat_format
);
667 static void __exit
exit_flat_binfmt(void)
669 unregister_binfmt(&flat_format
);
672 module_init(init_flat_binfmt
);
673 module_exit(exit_flat_binfmt
);