1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <linux/export.h>
19#include <linux/kernel.h>
20#include <linux/sched.h>
21#include <linux/mm.h>
22#include <linux/mman.h>
23#include <linux/errno.h>
24#include <linux/signal.h>
25#include <linux/string.h>
26#include <linux/fs.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>
37#include <linux/syscalls.h>
38
39#include <asm/byteorder.h>
40#include <asm/uaccess.h>
41#include <asm/unaligned.h>
42#include <asm/cacheflush.h>
43#include <asm/page.h>
44
45
46
47#if 0
48#define DEBUG 1
49#endif
50
51#ifdef DEBUG
52#define DBG_FLT(a...) printk(a)
53#else
54#define DBG_FLT(a...)
55#endif
56
57
58
59
60
61
62
63#define FLAT_DATA_ALIGN (0x20)
64
65
66
67
68
69
70#define FLAT_STACK_ALIGN max_t(unsigned long, sizeof(void *), ARCH_SLAB_MINALIGN)
71
72#define RELOC_FAILED 0xff00ff01
73#define UNLOADED_LIB 0x7ff000ff
74
75struct lib_info {
76 struct {
77 unsigned long start_code;
78 unsigned long start_data;
79 unsigned long start_brk;
80 unsigned long text_len;
81 unsigned long entry;
82 unsigned long build_date;
83 short loaded;
84 } lib_list[MAX_SHARED_LIBS];
85};
86
87#ifdef CONFIG_BINFMT_SHARED_FLAT
88static int load_flat_shared_library(int id, struct lib_info *p);
89#endif
90
91static int load_flat_binary(struct linux_binprm *, struct pt_regs * regs);
92static int flat_core_dump(struct coredump_params *cprm);
93
94static struct linux_binfmt flat_format = {
95 .module = THIS_MODULE,
96 .load_binary = load_flat_binary,
97 .core_dump = flat_core_dump,
98 .min_coredump = PAGE_SIZE
99};
100
101
102
103
104
105
106
107static int flat_core_dump(struct coredump_params *cprm)
108{
109 printk("Process %s:%d received signr %d and should have core dumped\n",
110 current->comm, current->pid, (int) cprm->signr);
111 return(1);
112}
113
114
115
116
117
118
119
120
121static unsigned long create_flat_tables(
122 unsigned long pp,
123 struct linux_binprm * bprm)
124{
125 unsigned long *argv,*envp;
126 unsigned long * sp;
127 char * p = (char*)pp;
128 int argc = bprm->argc;
129 int envc = bprm->envc;
130 char uninitialized_var(dummy);
131
132 sp = (unsigned long *)p;
133 sp -= (envc + argc + 2) + 1 + (flat_argvp_envp_on_stack() ? 2 : 0);
134 sp = (unsigned long *) ((unsigned long)sp & -FLAT_STACK_ALIGN);
135 argv = sp + 1 + (flat_argvp_envp_on_stack() ? 2 : 0);
136 envp = argv + (argc + 1);
137
138 if (flat_argvp_envp_on_stack()) {
139 put_user((unsigned long) envp, sp + 2);
140 put_user((unsigned long) argv, sp + 1);
141 }
142
143 put_user(argc, sp);
144 current->mm->arg_start = (unsigned long) p;
145 while (argc-->0) {
146 put_user((unsigned long) p, argv++);
147 do {
148 get_user(dummy, p); p++;
149 } while (dummy);
150 }
151 put_user((unsigned long) NULL, argv);
152 current->mm->arg_end = current->mm->env_start = (unsigned long) p;
153 while (envc-->0) {
154 put_user((unsigned long)p, envp); envp++;
155 do {
156 get_user(dummy, p); p++;
157 } while (dummy);
158 }
159 put_user((unsigned long) NULL, envp);
160 current->mm->env_end = (unsigned long) p;
161 return (unsigned long)sp;
162}
163
164
165
166#ifdef CONFIG_BINFMT_ZFLAT
167
168#include <linux/zlib.h>
169
170#define LBUFSIZE 4000
171
172
173#define ASCII_FLAG 0x01
174#define CONTINUATION 0x02
175#define EXTRA_FIELD 0x04
176#define ORIG_NAME 0x08
177#define COMMENT 0x10
178#define ENCRYPTED 0x20
179#define RESERVED 0xC0
180
181static int decompress_exec(
182 struct linux_binprm *bprm,
183 unsigned long offset,
184 char *dst,
185 long len,
186 int fd)
187{
188 unsigned char *buf;
189 z_stream strm;
190 loff_t fpos;
191 int ret, retval;
192
193 DBG_FLT("decompress_exec(offset=%x,buf=%x,len=%x)\n",(int)offset, (int)dst, (int)len);
194
195 memset(&strm, 0, sizeof(strm));
196 strm.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
197 if (strm.workspace == NULL) {
198 DBG_FLT("binfmt_flat: no memory for decompress workspace\n");
199 return -ENOMEM;
200 }
201 buf = kmalloc(LBUFSIZE, GFP_KERNEL);
202 if (buf == NULL) {
203 DBG_FLT("binfmt_flat: no memory for read buffer\n");
204 retval = -ENOMEM;
205 goto out_free;
206 }
207
208
209 fpos = offset;
210 ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos);
211
212 strm.next_in = buf;
213 strm.avail_in = ret;
214 strm.total_in = 0;
215
216 retval = -ENOEXEC;
217
218
219 if (ret < 10) {
220 DBG_FLT("binfmt_flat: file too small?\n");
221 goto out_free_buf;
222 }
223
224
225 if ((buf[0] != 037) || ((buf[1] != 0213) && (buf[1] != 0236))) {
226 DBG_FLT("binfmt_flat: unknown compression magic?\n");
227 goto out_free_buf;
228 }
229
230
231 if (buf[2] != 8) {
232 DBG_FLT("binfmt_flat: unknown compression method?\n");
233 goto out_free_buf;
234 }
235
236 if ((buf[3] & ENCRYPTED) || (buf[3] & CONTINUATION) ||
237 (buf[3] & RESERVED)) {
238 DBG_FLT("binfmt_flat: unknown flags?\n");
239 goto out_free_buf;
240 }
241
242 ret = 10;
243 if (buf[3] & EXTRA_FIELD) {
244 ret += 2 + buf[10] + (buf[11] << 8);
245 if (unlikely(LBUFSIZE <= ret)) {
246 DBG_FLT("binfmt_flat: buffer overflow (EXTRA)?\n");
247 goto out_free_buf;
248 }
249 }
250 if (buf[3] & ORIG_NAME) {
251 while (ret < LBUFSIZE && buf[ret++] != 0)
252 ;
253 if (unlikely(LBUFSIZE == ret)) {
254 DBG_FLT("binfmt_flat: buffer overflow (ORIG_NAME)?\n");
255 goto out_free_buf;
256 }
257 }
258 if (buf[3] & COMMENT) {
259 while (ret < LBUFSIZE && buf[ret++] != 0)
260 ;
261 if (unlikely(LBUFSIZE == ret)) {
262 DBG_FLT("binfmt_flat: buffer overflow (COMMENT)?\n");
263 goto out_free_buf;
264 }
265 }
266
267 strm.next_in += ret;
268 strm.avail_in -= ret;
269
270 strm.next_out = dst;
271 strm.avail_out = len;
272 strm.total_out = 0;
273
274 if (zlib_inflateInit2(&strm, -MAX_WBITS) != Z_OK) {
275 DBG_FLT("binfmt_flat: zlib init failed?\n");
276 goto out_free_buf;
277 }
278
279 while ((ret = zlib_inflate(&strm, Z_NO_FLUSH)) == Z_OK) {
280 ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos);
281 if (ret <= 0)
282 break;
283 len -= ret;
284
285 strm.next_in = buf;
286 strm.avail_in = ret;
287 strm.total_in = 0;
288 }
289
290 if (ret < 0) {
291 DBG_FLT("binfmt_flat: decompression failed (%d), %s\n",
292 ret, strm.msg);
293 goto out_zlib;
294 }
295
296 retval = 0;
297out_zlib:
298 zlib_inflateEnd(&strm);
299out_free_buf:
300 kfree(buf);
301out_free:
302 kfree(strm.workspace);
303 return retval;
304}
305
306#endif
307
308
309
310static unsigned long
311calc_reloc(unsigned long r, struct lib_info *p, int curid, int internalp)
312{
313 unsigned long addr;
314 int id;
315 unsigned long start_brk;
316 unsigned long start_data;
317 unsigned long text_len;
318 unsigned long start_code;
319
320#ifdef CONFIG_BINFMT_SHARED_FLAT
321 if (r == 0)
322 id = curid;
323 else {
324 id = (r >> 24) & 0xff;
325 r &= 0x00ffffff;
326 }
327 if (id >= MAX_SHARED_LIBS) {
328 printk("BINFMT_FLAT: reference 0x%x to shared library %d",
329 (unsigned) r, id);
330 goto failed;
331 }
332 if (curid != id) {
333 if (internalp) {
334 printk("BINFMT_FLAT: reloc address 0x%x not in same module "
335 "(%d != %d)", (unsigned) r, curid, id);
336 goto failed;
337 } else if ( ! p->lib_list[id].loaded &&
338 IS_ERR_VALUE(load_flat_shared_library(id, p))) {
339 printk("BINFMT_FLAT: failed to load library %d", id);
340 goto failed;
341 }
342
343 if (p->lib_list[id].build_date && p->lib_list[curid].build_date &&
344 p->lib_list[curid].build_date < p->lib_list[id].build_date) {
345 printk("BINFMT_FLAT: library %d is younger than %d", id, curid);
346 goto failed;
347 }
348 }
349#else
350 id = 0;
351#endif
352
353 start_brk = p->lib_list[id].start_brk;
354 start_data = p->lib_list[id].start_data;
355 start_code = p->lib_list[id].start_code;
356 text_len = p->lib_list[id].text_len;
357
358 if (!flat_reloc_valid(r, start_brk - start_data + text_len)) {
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);
361 goto failed;
362 }
363
364 if (r < text_len)
365 addr = r + start_code;
366 else
367 addr = r - text_len + start_data;
368
369
370 return(addr);
371
372failed:
373 printk(", killing %s!\n", current->comm);
374 send_sig(SIGSEGV, current, 0);
375
376 return RELOC_FAILED;
377}
378
379
380
381void old_reloc(unsigned long rl)
382{
383#ifdef DEBUG
384 char *segment[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" };
385#endif
386 flat_v2_reloc_t r;
387 unsigned long *ptr;
388
389 r.value = rl;
390#if defined(CONFIG_COLDFIRE)
391 ptr = (unsigned long *) (current->mm->start_code + r.reloc.offset);
392#else
393 ptr = (unsigned long *) (current->mm->start_data + r.reloc.offset);
394#endif
395
396#ifdef DEBUG
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]);
400#endif
401
402 switch (r.reloc.type) {
403 case OLD_FLAT_RELOC_TYPE_TEXT:
404 *ptr += current->mm->start_code;
405 break;
406 case OLD_FLAT_RELOC_TYPE_DATA:
407 *ptr += current->mm->start_data;
408 break;
409 case OLD_FLAT_RELOC_TYPE_BSS:
410 *ptr += current->mm->end_data;
411 break;
412 default:
413 printk("BINFMT_FLAT: Unknown relocation type=%x\n", r.reloc.type);
414 break;
415 }
416
417#ifdef DEBUG
418 printk("Relocation became %x\n", (int)*ptr);
419#endif
420}
421
422
423
424static int load_flat_file(struct linux_binprm * bprm,
425 struct lib_info *libinfo, int id, unsigned long *extra_stack)
426{
427 struct flat_hdr * hdr;
428 unsigned long textpos = 0, datapos = 0, result;
429 unsigned long realdatastart = 0;
430 unsigned long text_len, data_len, bss_len, stack_len, flags;
431 unsigned long len, memp = 0;
432 unsigned long memp_size, extra, rlim;
433 unsigned long *reloc = 0, *rp;
434 struct inode *inode;
435 int i, rev, relocs = 0;
436 loff_t fpos;
437 unsigned long start_code, end_code;
438 int ret;
439
440 hdr = ((struct flat_hdr *) bprm->buf);
441 inode = bprm->file->f_path.dentry->d_inode;
442
443 text_len = ntohl(hdr->data_start);
444 data_len = ntohl(hdr->data_end) - ntohl(hdr->data_start);
445 bss_len = ntohl(hdr->bss_end) - ntohl(hdr->data_end);
446 stack_len = ntohl(hdr->stack_size);
447 if (extra_stack) {
448 stack_len += *extra_stack;
449 *extra_stack = stack_len;
450 }
451 relocs = ntohl(hdr->reloc_count);
452 flags = ntohl(hdr->flags);
453 rev = ntohl(hdr->rev);
454
455 if (strncmp(hdr->magic, "bFLT", 4)) {
456
457
458
459
460
461
462
463 ret = -ENOEXEC;
464 goto err;
465 }
466
467 if (flags & FLAT_FLAG_KTRACE)
468 printk("BINFMT_FLAT: Loading file: %s\n", bprm->filename);
469
470 if (rev != FLAT_VERSION && rev != OLD_FLAT_VERSION) {
471 printk("BINFMT_FLAT: bad flat file version 0x%x (supported "
472 "0x%lx and 0x%lx)\n",
473 rev, FLAT_VERSION, OLD_FLAT_VERSION);
474 ret = -ENOEXEC;
475 goto err;
476 }
477
478
479 if (rev == OLD_FLAT_VERSION && id != 0) {
480 printk("BINFMT_FLAT: shared libraries are not available before rev 0x%x\n",
481 (int) FLAT_VERSION);
482 ret = -ENOEXEC;
483 goto err;
484 }
485
486
487
488
489
490 if (rev == OLD_FLAT_VERSION && flat_old_ram_flag(flags))
491 flags = FLAT_FLAG_RAM;
492
493#ifndef CONFIG_BINFMT_ZFLAT
494 if (flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) {
495 printk("Support for ZFLAT executables is not enabled.\n");
496 ret = -ENOEXEC;
497 goto err;
498 }
499#endif
500
501
502
503
504
505
506 rlim = rlimit(RLIMIT_DATA);
507 if (rlim >= RLIM_INFINITY)
508 rlim = ~0;
509 if (data_len + bss_len > rlim) {
510 ret = -ENOMEM;
511 goto err;
512 }
513
514
515 if (id == 0) {
516 result = flush_old_exec(bprm);
517 if (result) {
518 ret = result;
519 goto err;
520 }
521
522
523 set_personality(PER_LINUX_32BIT);
524 setup_new_exec(bprm);
525 }
526
527
528
529
530 extra = max_t(unsigned long, bss_len + stack_len,
531 relocs * sizeof(unsigned long));
532
533
534
535
536
537
538 if ((flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP)) == 0) {
539
540
541
542
543 DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
544
545 textpos = vm_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC,
546 MAP_PRIVATE|MAP_EXECUTABLE, 0);
547 if (!textpos || IS_ERR_VALUE(textpos)) {
548 if (!textpos)
549 textpos = (unsigned long) -ENOMEM;
550 printk("Unable to mmap process text, errno %d\n", (int)-textpos);
551 ret = textpos;
552 goto err;
553 }
554
555 len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
556 len = PAGE_ALIGN(len);
557 realdatastart = vm_mmap(0, 0, len,
558 PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
559
560 if (realdatastart == 0 || IS_ERR_VALUE(realdatastart)) {
561 if (!realdatastart)
562 realdatastart = (unsigned long) -ENOMEM;
563 printk("Unable to allocate RAM for process data, errno %d\n",
564 (int)-realdatastart);
565 vm_munmap(textpos, text_len);
566 ret = realdatastart;
567 goto err;
568 }
569 datapos = ALIGN(realdatastart +
570 MAX_SHARED_LIBS * sizeof(unsigned long),
571 FLAT_DATA_ALIGN);
572
573 DBG_FLT("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n",
574 (int)(data_len + bss_len + stack_len), (int)datapos);
575
576 fpos = ntohl(hdr->data_start);
577#ifdef CONFIG_BINFMT_ZFLAT
578 if (flags & FLAT_FLAG_GZDATA) {
579 result = decompress_exec(bprm, fpos, (char *) datapos,
580 data_len + (relocs * sizeof(unsigned long)), 0);
581 } else
582#endif
583 {
584 result = bprm->file->f_op->read(bprm->file, (char *) datapos,
585 data_len + (relocs * sizeof(unsigned long)), &fpos);
586 }
587 if (IS_ERR_VALUE(result)) {
588 printk("Unable to read data+bss, errno %d\n", (int)-result);
589 vm_munmap(textpos, text_len);
590 vm_munmap(realdatastart, len);
591 ret = result;
592 goto err;
593 }
594
595 reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len));
596 memp = realdatastart;
597 memp_size = len;
598 } else {
599
600 len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
601 len = PAGE_ALIGN(len);
602 textpos = vm_mmap(0, 0, len,
603 PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
604
605 if (!textpos || IS_ERR_VALUE(textpos)) {
606 if (!textpos)
607 textpos = (unsigned long) -ENOMEM;
608 printk("Unable to allocate RAM for process text/data, errno %d\n",
609 (int)-textpos);
610 ret = textpos;
611 goto err;
612 }
613
614 realdatastart = textpos + ntohl(hdr->data_start);
615 datapos = ALIGN(realdatastart +
616 MAX_SHARED_LIBS * sizeof(unsigned long),
617 FLAT_DATA_ALIGN);
618
619 reloc = (unsigned long *)
620 (datapos + (ntohl(hdr->reloc_start) - text_len));
621 memp = textpos;
622 memp_size = len;
623#ifdef CONFIG_BINFMT_ZFLAT
624
625
626
627 if (flags & FLAT_FLAG_GZIP) {
628 result = decompress_exec(bprm, sizeof (struct flat_hdr),
629 (((char *) textpos) + sizeof (struct flat_hdr)),
630 (text_len + data_len + (relocs * sizeof(unsigned long))
631 - sizeof (struct flat_hdr)),
632 0);
633 memmove((void *) datapos, (void *) realdatastart,
634 data_len + (relocs * sizeof(unsigned long)));
635 } else if (flags & FLAT_FLAG_GZDATA) {
636 fpos = 0;
637 result = bprm->file->f_op->read(bprm->file,
638 (char *) textpos, text_len, &fpos);
639 if (!IS_ERR_VALUE(result))
640 result = decompress_exec(bprm, text_len, (char *) datapos,
641 data_len + (relocs * sizeof(unsigned long)), 0);
642 }
643 else
644#endif
645 {
646 fpos = 0;
647 result = bprm->file->f_op->read(bprm->file,
648 (char *) textpos, text_len, &fpos);
649 if (!IS_ERR_VALUE(result)) {
650 fpos = ntohl(hdr->data_start);
651 result = bprm->file->f_op->read(bprm->file, (char *) datapos,
652 data_len + (relocs * sizeof(unsigned long)), &fpos);
653 }
654 }
655 if (IS_ERR_VALUE(result)) {
656 printk("Unable to read code+data+bss, errno %d\n",(int)-result);
657 vm_munmap(textpos, text_len + data_len + extra +
658 MAX_SHARED_LIBS * sizeof(unsigned long));
659 ret = result;
660 goto err;
661 }
662 }
663
664 if (flags & FLAT_FLAG_KTRACE)
665 printk("Mapping is %x, Entry point is %x, data_start is %x\n",
666 (int)textpos, 0x00ffffff&ntohl(hdr->entry), ntohl(hdr->data_start));
667
668
669 start_code = textpos + sizeof (struct flat_hdr);
670 end_code = textpos + text_len;
671 if (id == 0) {
672 current->mm->start_code = start_code;
673 current->mm->end_code = end_code;
674 current->mm->start_data = datapos;
675 current->mm->end_data = datapos + data_len;
676
677
678
679
680
681
682
683 current->mm->start_brk = datapos + data_len + bss_len;
684 current->mm->brk = (current->mm->start_brk + 3) & ~3;
685 current->mm->context.end_brk = memp + memp_size - stack_len;
686 }
687
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,
692 (int) datapos,
693 (int) (datapos + data_len),
694 (int) (datapos + data_len),
695 (int) (((datapos + data_len + bss_len) + 3) & ~3));
696
697 text_len -= sizeof(struct flat_hdr);
698
699
700 libinfo->lib_list[id].start_code = start_code;
701 libinfo->lib_list[id].start_data = datapos;
702 libinfo->lib_list[id].start_brk = datapos + data_len + bss_len;
703 libinfo->lib_list[id].text_len = text_len;
704 libinfo->lib_list[id].loaded = 1;
705 libinfo->lib_list[id].entry = (0x00ffffff & ntohl(hdr->entry)) + textpos;
706 libinfo->lib_list[id].build_date = ntohl(hdr->build_date);
707
708
709
710
711
712
713
714
715
716
717
718
719
720 if (flags & FLAT_FLAG_GOTPIC) {
721 for (rp = (unsigned long *)datapos; *rp != 0xffffffff; rp++) {
722 unsigned long addr;
723 if (*rp) {
724 addr = calc_reloc(*rp, libinfo, id, 0);
725 if (addr == RELOC_FAILED) {
726 ret = -ENOEXEC;
727 goto err;
728 }
729 *rp = addr;
730 }
731 }
732 }
733
734
735
736
737
738
739
740
741
742
743
744
745 if (rev > OLD_FLAT_VERSION) {
746 unsigned long persistent = 0;
747 for (i=0; i < relocs; i++) {
748 unsigned long addr, relval;
749
750
751
752
753 relval = ntohl(reloc[i]);
754 if (flat_set_persistent (relval, &persistent))
755 continue;
756 addr = flat_get_relocate_addr(relval);
757 rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1);
758 if (rp == (unsigned long *)RELOC_FAILED) {
759 ret = -ENOEXEC;
760 goto err;
761 }
762
763
764 addr = flat_get_addr_from_rp(rp, relval, flags,
765 &persistent);
766 if (addr != 0) {
767
768
769
770
771 if ((flags & FLAT_FLAG_GOTPIC) == 0)
772 addr = ntohl(addr);
773 addr = calc_reloc(addr, libinfo, id, 0);
774 if (addr == RELOC_FAILED) {
775 ret = -ENOEXEC;
776 goto err;
777 }
778
779
780 flat_put_addr_at_rp(rp, addr, relval);
781 }
782 }
783 } else {
784 for (i=0; i < relocs; i++)
785 old_reloc(ntohl(reloc[i]));
786 }
787
788 flush_icache_range(start_code, end_code);
789
790
791 memset((void*)(datapos + data_len), 0, bss_len +
792 (memp + memp_size - stack_len -
793 libinfo->lib_list[id].start_brk) +
794 stack_len);
795
796 return 0;
797err:
798 return ret;
799}
800
801
802
803#ifdef CONFIG_BINFMT_SHARED_FLAT
804
805
806
807
808
809
810static int load_flat_shared_library(int id, struct lib_info *libs)
811{
812 struct linux_binprm bprm;
813 int res;
814 char buf[16];
815
816 memset(&bprm, 0, sizeof(bprm));
817
818
819 sprintf(buf, "/lib/lib%d.so", id);
820
821
822 bprm.filename = buf;
823 bprm.file = open_exec(bprm.filename);
824 res = PTR_ERR(bprm.file);
825 if (IS_ERR(bprm.file))
826 return res;
827
828 bprm.cred = prepare_exec_creds();
829 res = -ENOMEM;
830 if (!bprm.cred)
831 goto out;
832
833
834
835
836
837 bprm.cred_prepared = 1;
838
839 res = prepare_binprm(&bprm);
840
841 if (!IS_ERR_VALUE(res))
842 res = load_flat_file(&bprm, libs, id, NULL);
843
844 abort_creds(bprm.cred);
845
846out:
847 allow_write_access(bprm.file);
848 fput(bprm.file);
849
850 return(res);
851}
852
853#endif
854
855
856
857
858
859
860
861static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
862{
863 struct lib_info libinfo;
864 unsigned long p = bprm->p;
865 unsigned long stack_len;
866 unsigned long start_addr;
867 unsigned long *sp;
868 int res;
869 int i, j;
870
871 memset(&libinfo, 0, sizeof(libinfo));
872
873
874
875
876
877
878
879#define TOP_OF_ARGS (PAGE_SIZE * MAX_ARG_PAGES - sizeof(void *))
880 stack_len = TOP_OF_ARGS - bprm->p;
881 stack_len += (bprm->argc + 1) * sizeof(char *);
882 stack_len += (bprm->envc + 1) * sizeof(char *);
883 stack_len += FLAT_STACK_ALIGN - 1;
884
885 res = load_flat_file(bprm, &libinfo, 0, &stack_len);
886 if (IS_ERR_VALUE(res))
887 return res;
888
889
890 for (i=0; i<MAX_SHARED_LIBS; i++)
891 if (libinfo.lib_list[i].loaded)
892 for (j=0; j<MAX_SHARED_LIBS; j++)
893 (-(j+1))[(unsigned long *)(libinfo.lib_list[i].start_data)] =
894 (libinfo.lib_list[j].loaded)?
895 libinfo.lib_list[j].start_data:UNLOADED_LIB;
896
897 install_exec_creds(bprm);
898
899 set_binfmt(&flat_format);
900
901 p = ((current->mm->context.end_brk + stack_len + 3) & ~3) - 4;
902 DBG_FLT("p=%x\n", (int)p);
903
904
905 for (i = TOP_OF_ARGS - 1; i >= bprm->p; i--)
906 * (char *) --p =
907 ((char *) page_address(bprm->page[i/PAGE_SIZE]))[i % PAGE_SIZE];
908
909 sp = (unsigned long *) create_flat_tables(p, bprm);
910
911
912
913
914
915 start_addr = libinfo.lib_list[0].entry;
916
917#ifdef CONFIG_BINFMT_SHARED_FLAT
918 for (i = MAX_SHARED_LIBS-1; i>0; i--) {
919 if (libinfo.lib_list[i].loaded) {
920
921 --sp; put_user(start_addr, sp);
922 start_addr = libinfo.lib_list[i].entry;
923 }
924 }
925#endif
926
927
928 current->mm->start_stack = (unsigned long )sp;
929
930#ifdef FLAT_PLAT_INIT
931 FLAT_PLAT_INIT(regs);
932#endif
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);
935
936 start_thread(regs, start_addr, current->mm->start_stack);
937
938 return 0;
939}
940
941
942
943static int __init init_flat_binfmt(void)
944{
945 register_binfmt(&flat_format);
946 return 0;
947}
948
949
950
951core_initcall(init_flat_binfmt);
952
953
954