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