This source file includes following definitions.
- is_properly_aligned
- clear_memory
- load_object
- preload_this_library
- preload_library
- load_coff_binary
- load_coff_library
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #include <linux/fs.h>
19 #include <linux/sched.h>
20 #include <linux/mm.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/binfmts.h>
26 #include <asm/segment.h>
27 #include <linux/string.h>
28 #include <linux/fcntl.h>
29 #include <linux/ptrace.h>
30 #include <linux/coff.h>
31 #include <linux/malloc.h>
32
33 asmlinkage int sys_exit (int exit_code);
34 asmlinkage int sys_close (unsigned fd);
35 asmlinkage int sys_open (const char *, int, int);
36 asmlinkage int sys_uselib(const char * library);
37
38 static int preload_library (struct linux_binprm *exe_bprm,
39 COFF_SCNHDR * sect,
40 struct file *fp);
41
42 static int load_object (struct linux_binprm *bprm,
43 struct pt_regs *regs,
44 int lib_ok);
45
46
47
48
49
50 static inline int
51 is_properly_aligned (COFF_SCNHDR *sect)
52 {
53 long scnptr = COFF_LONG (sect->s_scnptr);
54 long vaddr = COFF_LONG (sect->s_vaddr);
55
56
57
58
59 #ifdef COFF_DEBUG
60 printk ("%s, scnptr = %d, vaddr = %d\n",
61 sect->s_name,
62 scnptr, vaddr);
63 #endif
64
65
66
67
68
69 #ifdef COFF_DEBUG
70 if (((vaddr - scnptr) & ~PAGE_MASK) != 0)
71 printk ("bad alignment in %s\n", sect->s_name);
72 #endif
73 return ((((vaddr - scnptr) & ~PAGE_MASK) != 0) ? -ENOEXEC : 0);
74 }
75
76
77
78
79
80 static
81 int clear_memory (unsigned long addr, unsigned long size)
82 {
83 int status;
84
85 size = (PAGE_SIZE - (addr & ~PAGE_MASK)) & ~PAGE_MASK;
86 if (size == 0)
87 status = 0;
88 else {
89
90 #ifdef COFF_DEBUG
91 printk ("un-initialized storage in last page %d\n", size);
92 #endif
93
94 status = verify_area (VERIFY_WRITE,
95 (void *) addr, size);
96 #ifdef COFF_DEBUG
97 printk ("result from verify_area = %d\n", status);
98 #endif
99
100 if (status >= 0)
101 while (size-- != 0)
102 put_fs_byte (0, addr++);
103 }
104 return status;
105 }
106
107
108
109
110
111 static int
112 load_object (struct linux_binprm * bprm, struct pt_regs *regs, int lib_ok)
113 {
114 COFF_FILHDR *coff_hdr = (COFF_FILHDR *) bprm->buf;
115 COFF_SCNHDR *sect_bufr;
116 COFF_SCNHDR *text_sect;
117 COFF_SCNHDR *data_sect;
118 COFF_SCNHDR *bss_sect;
119 int text_count;
120 int data_count;
121 int bss_count;
122 int lib_count;
123 unsigned int start_addr = 0;
124 int status = 0;
125 int fd = -1;
126 struct file *fp = NULL;
127 short int sections = 0;
128 short int aout_size = 0;
129 short int flags;
130
131 #ifdef COFF_DEBUG
132 printk ("binfmt_coff entry: %s\n", bprm->filename);
133 #endif
134
135
136
137
138 do {
139 if (COFF_I386BADMAG (*coff_hdr)) {
140 #ifdef COFF_DEBUG
141 printk ("bad filehdr magic\n");
142 #endif
143 status = -ENOEXEC;
144 break;
145 }
146
147
148
149
150
151 flags = COFF_SHORT (coff_hdr->f_flags);
152 if ((flags & (COFF_F_AR32WR | COFF_F_AR16WR)) != COFF_F_AR32WR) {
153 #ifdef COFF_DEBUG
154 printk ("invalid f_flags bits\n");
155 #endif
156 status = -ENOEXEC;
157 break;
158 }
159
160
161
162 sections = COFF_SHORT (coff_hdr->f_nscns);
163 aout_size = COFF_SHORT (coff_hdr->f_opthdr);
164
165
166
167
168 if ((flags & COFF_F_EXEC) == 0) {
169 #ifdef COFF_DEBUG
170 printk ("not executable bit\n");
171 #endif
172 status = -ENOEXEC;
173 break;
174 }
175
176
177
178 if (sections == 0) {
179 #ifdef COFF_DEBUG
180 printk ("no sections\n");
181 #endif
182 status = -ENOEXEC;
183 break;
184 }
185
186
187
188
189
190 if (!bprm->inode->i_op ||
191 !bprm->inode->i_op->default_file_ops->mmap) {
192 #ifdef COFF_DEBUG
193 printk ("no mmap in fs\n");
194 #endif
195 status = -ENOEXEC;
196 }
197 }
198 while (0);
199
200
201
202 if (status >= 0) {
203 int nbytes = sections * COFF_SCNHSZ;
204
205 sect_bufr = (COFF_SCNHDR *) kmalloc (nbytes, GFP_KERNEL);
206 if (0 == sect_bufr) {
207 #ifdef COFF_DEBUG
208 printk ("kmalloc failed\n");
209 #endif
210 status = -ENOEXEC;
211 }
212
213
214
215 else {
216 int old_fs = get_fs ();
217 set_fs (get_ds ());
218 status = read_exec (bprm->inode,
219 aout_size + COFF_FILHSZ,
220 (char *) sect_bufr,
221 nbytes);
222 set_fs (old_fs);
223 #ifdef COFF_DEBUG
224 if (status < 0)
225 printk ("read aout hdr, status = %d\n", status);
226 #endif
227 }
228 }
229 else
230 sect_bufr = NULL;
231
232
233
234
235 text_count = 0;
236 data_count = 0;
237 bss_count = 0;
238 lib_count = 0;
239
240 text_sect = NULL;
241 data_sect = NULL;
242 bss_sect = NULL;
243
244
245
246 if (status >= 0) {
247 int nIndex;
248 COFF_SCNHDR *sect_ptr = sect_bufr;
249
250 for (nIndex = 0; nIndex < sections; ++nIndex) {
251 long int sect_flags = COFF_LONG (sect_ptr->s_flags);
252
253 switch (sect_flags) {
254 case COFF_STYP_TEXT:
255 text_sect = sect_ptr;
256 ++text_count;
257 status = is_properly_aligned (sect_ptr);
258 break;
259
260 case COFF_STYP_DATA:
261 data_sect = sect_ptr;
262 ++data_count;
263 status = is_properly_aligned (sect_ptr);
264 break;
265
266 case COFF_STYP_BSS:
267 bss_sect = sect_ptr;
268 ++bss_count;
269 break;
270
271 case COFF_STYP_LIB:
272 #ifdef COFF_DEBUG
273 printk (".lib section found\n");
274 #endif
275 ++lib_count;
276 break;
277
278 default:
279 break;
280 }
281 sect_ptr = (COFF_SCNHDR *) & ((char *) sect_ptr)[COFF_SCNHSZ];
282 }
283
284
285
286
287
288 if (text_count != 1) {
289 status = -ENOEXEC;
290 #ifdef COFF_DEBUG
291 printk ("no text sections\n");
292 #endif
293 }
294 else {
295 if (lib_ok) {
296 if (data_count != 1 || bss_count != 1) {
297 status = -ENOEXEC;
298 #ifdef COFF_DEBUG
299 printk ("no .data nor .bss sections\n");
300 #endif
301 }
302 }
303 }
304 }
305
306
307
308
309
310
311 if (status >= 0) {
312 if (aout_size == 0) {
313 if (!lib_ok) {
314 status = -ENOEXEC;
315 #ifdef COFF_DEBUG
316 printk ("no header in library\n");
317 #endif
318 }
319 start_addr = COFF_LONG (text_sect->s_vaddr);
320 }
321
322
323
324 else {
325 if (aout_size < COFF_AOUTSZ) {
326 status = -ENOEXEC;
327 #ifdef COFF_DEBUG
328 printk ("header too small\n");
329 #endif
330 }
331 else {
332 COFF_AOUTHDR *aout_hdr =
333 (COFF_AOUTHDR *) & ((char *) coff_hdr)[COFF_FILHSZ];
334 short int aout_magic = COFF_SHORT (aout_hdr->magic);
335
336
337
338
339
340 switch (aout_magic) {
341 case COFF_OMAGIC:
342 case COFF_ZMAGIC:
343 case COFF_STMAGIC:
344 if (!lib_ok) {
345 status = -ENOEXEC;
346 #ifdef COFF_DEBUG
347 printk ("wrong a.out header magic\n");
348 #endif
349 }
350 start_addr = (unsigned int) COFF_LONG (aout_hdr->entry);
351 break;
352
353
354
355
356 case COFF_SHMAGIC:
357 if (lib_ok) {
358 #ifdef COFF_DEBUG
359 printk ("wrong a.out header magic\n");
360 #endif
361 status = -ENOEXEC;
362 }
363 break;
364
365 default:
366 #ifdef COFF_DEBUG
367 printk ("wrong a.out header magic\n");
368 #endif
369 status = -ENOEXEC;
370 break;
371 }
372 }
373 }
374 }
375
376
377
378 if (status >= 0) {
379 fd = open_inode (bprm->inode, O_RDONLY);
380 if (fd < 0) {
381 #ifdef COFF_DEBUG
382 printk ("can not open inode, result = %d\n", fd);
383 #endif
384 status = fd;
385 }
386 else
387 fp = current->filp[fd];
388 }
389 else
390 fd = -1;
391
392
393
394
395
396
397 if (status >= 0) {
398 long text_scnptr = COFF_LONG (text_sect->s_scnptr);
399 long text_size = COFF_LONG (text_sect->s_size);
400 long text_vaddr = COFF_LONG (text_sect->s_vaddr);
401
402 long data_scnptr;
403 long data_size;
404 long data_vaddr;
405
406 long bss_size;
407 long bss_vaddr;
408
409
410
411 if (data_sect != NULL) {
412 data_scnptr = COFF_LONG (data_sect->s_scnptr);
413 data_size = COFF_LONG (data_sect->s_size);
414 data_vaddr = COFF_LONG (data_sect->s_vaddr);
415 }
416 else {
417 data_scnptr = 0;
418 data_size = 0;
419 data_vaddr = 0;
420 }
421
422
423
424 if (bss_sect != NULL) {
425 bss_size = COFF_LONG (bss_sect->s_size);
426 bss_vaddr = COFF_LONG (bss_sect->s_vaddr);
427 }
428 else {
429 bss_size = 0;
430 bss_vaddr = 0;
431 }
432
433
434
435
436 if (lib_ok) {
437 #ifdef COFF_DEBUG
438 printk ("flushing executable\n");
439 #endif
440 flush_old_exec (bprm);
441
442
443
444 current->mmap = NULL;
445 current->rss = 0;
446
447
448
449 bprm->p += change_ldt (0, bprm->page);
450 bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
451 bprm->p = (unsigned long) create_tables ((char *) bprm->p,
452 bprm->argc,
453 bprm->envc,
454 1);
455
456
457
458 current->start_code = text_vaddr & PAGE_MASK;
459 current->end_code = text_vaddr + text_size;
460 current->end_data = data_vaddr + data_size;
461 current->start_brk =
462 current->brk = bss_vaddr + bss_size;
463 current->suid =
464 current->euid = bprm->e_uid;
465 current->sgid =
466 current->egid = bprm->e_gid;
467 current->executable = bprm->inode;
468 ++bprm->inode->i_count;
469 regs->eip = start_addr;
470 regs->esp =
471 current->start_stack = bprm->p;
472 }
473
474
475
476
477 #ifdef COFF_DEBUG
478 printk (".text: vaddr = %d, size = %d, scnptr = %d\n",
479 text_vaddr,
480 text_size,
481 text_scnptr);
482 #endif
483 status = do_mmap (fp,
484 text_vaddr & PAGE_MASK,
485 text_size + (text_vaddr & ~PAGE_MASK),
486 PROT_READ | PROT_EXEC,
487 MAP_FIXED | MAP_SHARED,
488 text_scnptr & PAGE_MASK);
489
490 status = (status == (text_vaddr & PAGE_MASK)) ? 0 : -ENOEXEC;
491
492
493
494 if (status >= 0 && data_size != 0) {
495 #ifdef COFF_DEBUG
496 printk (".data: vaddr = %d, size = %d, scnptr = %d\n",
497 data_vaddr,
498 data_size,
499 data_scnptr);
500 #endif
501 status = do_mmap (fp,
502 data_vaddr & PAGE_MASK,
503 data_size + (data_vaddr & ~PAGE_MASK),
504 PROT_READ | PROT_WRITE | PROT_EXEC,
505 MAP_FIXED | MAP_PRIVATE,
506 data_scnptr & PAGE_MASK);
507
508 status = (status == (data_vaddr & PAGE_MASK)) ? 0 : -ENOEXEC;
509 }
510
511
512
513
514
515 if (status >= 0 && bss_size != 0) {
516 #ifdef COFF_DEBUG
517 printk (".bss: vaddr = %d, size = %d\n",
518 bss_vaddr,
519 bss_size);
520 #endif
521 zeromap_page_range (PAGE_ALIGN (bss_vaddr),
522 PAGE_ALIGN (bss_size),
523 PAGE_COPY);
524
525 status = clear_memory (bss_vaddr, bss_size);
526 }
527
528
529
530 if (status >= 0 && lib_ok && lib_count != 0) {
531 int nIndex;
532 COFF_SCNHDR *sect_ptr = sect_bufr;
533
534
535
536
537
538 for (nIndex = 0; nIndex < sections; ++nIndex) {
539 long int sect_flags = COFF_LONG (sect_ptr->s_flags);
540 if (sect_flags == COFF_STYP_LIB) {
541 status = preload_library (bprm, sect_ptr, fp);
542 if (status != 0)
543 break;
544 }
545 sect_ptr = (COFF_SCNHDR *) &((char *) sect_ptr) [COFF_SCNHSZ];
546 }
547 }
548
549
550
551
552
553
554
555 if (lib_ok) {
556 if (status < 0)
557 send_sig (SIGSEGV, current, 0);
558 else {
559 if (current->flags & PF_PTRACED)
560 send_sig (SIGTRAP, current, 0);
561 }
562 status = 0;
563 }
564 }
565
566
567
568 if (fd >= 0)
569 sys_close (fd);
570
571 if (sect_bufr != NULL)
572 kfree (sect_bufr);
573
574
575
576 #ifdef COFF_DEBUG
577 printk ("binfmt_coff: result = %d\n", status);
578 #endif
579 return (status);
580 }
581
582
583
584
585
586
587
588 static int
589 preload_this_library (struct linux_binprm *exe_bprm, char *lib_name)
590 {
591 int status;
592 int old_fs = get_fs();
593
594
595
596 #ifdef COFF_DEBUG
597 printk ("%s loading shared library %s\n",
598 exe_bprm->filename,
599 lib_name);
600 #endif
601
602
603
604
605
606 set_fs (get_ds ());
607 status = sys_uselib (lib_name);
608 set_fs (old_fs);
609
610
611
612 return (status);
613 }
614
615
616
617
618
619
620 static int
621 preload_library (struct linux_binprm *exe_bprm,
622 COFF_SCNHDR * sect, struct file *fp)
623 {
624 int status = 0;
625 long nbytes;
626
627
628
629
630 nbytes = COFF_LONG (sect->s_size);
631 if (nbytes < COFF_SLIBSZ) {
632 status = -ENOEXEC;
633 #ifdef COFF_DEBUG
634 printk ("library section too small\n");
635 #endif
636 }
637
638
639
640 else {
641 COFF_SLIBHD *phdr;
642 char *buffer = (char *) kmalloc (nbytes, GFP_KERNEL);
643
644 if (0 == buffer) {
645 status = -ENOEXEC;
646 #ifdef COFF_DEBUG
647 printk ("kmalloc failed\n");
648 #endif
649 }
650 else {
651 int old_fs = get_fs ();
652
653
654
655 set_fs (get_ds ());
656 status = read_exec (exe_bprm->inode,
657 COFF_LONG (sect->s_scnptr),
658 buffer,
659 nbytes);
660 set_fs (old_fs);
661
662
663
664 if (status >= 0 && status != nbytes) {
665 #ifdef COFF_DEBUG
666 printk ("read of lib section was short\n");
667 #endif
668 status = -ENOEXEC;
669 }
670 }
671
672
673
674 phdr = (COFF_SLIBHD *) buffer;
675 while (status >= 0 && nbytes > COFF_SLIBSZ) {
676 int entry_size = COFF_LONG (phdr->sl_entsz) * sizeof (long);
677 int header_size = COFF_LONG (phdr->sl_pathndx) * sizeof (long);
678
679
680
681 if ((unsigned) header_size >= (unsigned) nbytes ||
682 entry_size <= 0 ||
683 (unsigned) entry_size <= (unsigned) header_size) {
684 status = -ENOEXEC;
685 #ifdef COFF_DEBUG
686 printk ("header count is invalid\n");
687 #endif
688 }
689
690
691
692 else {
693 status = preload_this_library (exe_bprm,
694 &((char *) phdr)[header_size]);
695 #ifdef COFF_DEBUG
696 printk ("preload_this_library result = %d\n", status);
697 #endif
698 }
699
700
701
702 nbytes -= entry_size;
703 phdr = (COFF_SLIBHD *) &((char *) phdr)[entry_size];
704 }
705
706
707
708 if (buffer != NULL)
709 kfree (buffer);
710 }
711
712
713
714 return (status);
715 }
716
717
718
719
720
721
722
723
724 int
725 load_coff_binary (struct linux_binprm *bprm, struct pt_regs *regs)
726 {
727 return (load_object (bprm, regs, 1));
728 }
729
730
731
732
733
734
735
736 int
737 load_coff_library (int fd)
738 {
739 struct linux_binprm *bprm;
740 int status;
741
742
743
744 bprm = (struct linux_binprm *) kmalloc (sizeof (struct linux_binprm),
745 GFP_KERNEL);
746 if (0 == bprm) {
747 #ifdef COFF_DEBUG
748 printk ("kmalloc failed\n");
749 #endif
750 status = -ENOEXEC;
751 }
752 else {
753 struct file *file;
754 struct pt_regs regs;
755 int old_fs = get_fs ();
756
757 memset (bprm, '\0', sizeof (struct linux_binprm));
758
759 file = current->filp[fd];
760 bprm->inode = file->f_inode;
761 bprm->filename = "";
762
763
764
765 set_fs (get_ds ());
766 status = read_exec (bprm->inode,
767 0L,
768 bprm->buf,
769 sizeof (bprm->buf));
770 set_fs (old_fs);
771
772
773
774 status = load_object (bprm, ®s, 0);
775
776
777
778 kfree (bprm);
779 }
780
781
782
783 return (status);
784 }