This source file includes following definitions.
- register_binfmt
- unregister_binfmt
- open_inode
- core_dump
- sys_uselib
- create_tables
- count
- copy_strings
- change_ldt
- read_exec
- flush_old_exec
- do_execve
- sys_execve
- no_lcall7
- set_brk
- load_aout_binary
- load_aout_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 #include <linux/fs.h>
27 #include <linux/sched.h>
28 #include <linux/kernel.h>
29 #include <linux/mm.h>
30 #include <linux/mman.h>
31 #include <linux/a.out.h>
32 #include <linux/errno.h>
33 #include <linux/signal.h>
34 #include <linux/string.h>
35 #include <linux/stat.h>
36 #include <linux/fcntl.h>
37 #include <linux/ptrace.h>
38 #include <linux/user.h>
39 #include <linux/segment.h>
40 #include <linux/malloc.h>
41
42 #include <asm/system.h>
43
44 #include <linux/binfmts.h>
45
46 #include <asm/segment.h>
47 #include <asm/system.h>
48
49 asmlinkage int sys_exit(int exit_code);
50 asmlinkage int sys_close(unsigned fd);
51 asmlinkage int sys_open(const char *, int, int);
52 asmlinkage int sys_brk(unsigned long);
53
54 extern void shm_exit (void);
55
56 static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
57 static int load_aout_library(int fd);
58
59
60
61
62
63 static struct linux_binfmt aout_format = { NULL, load_aout_binary, load_aout_library };
64 static struct linux_binfmt *formats = &aout_format;
65
66 int register_binfmt(struct linux_binfmt * fmt)
67 {
68 struct linux_binfmt ** tmp = &formats;
69
70 if (!fmt)
71 return -EINVAL;
72 if (fmt->next)
73 return -EBUSY;
74 while (*tmp) {
75 if (fmt == *tmp)
76 return -EBUSY;
77 tmp = &(*tmp)->next;
78 }
79 *tmp = fmt;
80 return 0;
81 }
82
83 int unregister_binfmt(struct linux_binfmt * fmt)
84 {
85 struct linux_binfmt ** tmp = &formats;
86
87 while (*tmp) {
88 if (fmt == *tmp) {
89 *tmp = fmt->next;
90 return 0;
91 }
92 tmp = &(*tmp)->next;
93 }
94 return -EINVAL;
95 }
96
97 int open_inode(struct inode * inode, int mode)
98 {
99 int error, fd;
100 struct file *f, **fpp;
101
102 if (!inode->i_op || !inode->i_op->default_file_ops)
103 return -EINVAL;
104 f = get_empty_filp();
105 if (!f)
106 return -EMFILE;
107 fd = 0;
108 fpp = current->files->fd;
109 for (;;) {
110 if (!*fpp)
111 break;
112 if (++fd > NR_OPEN)
113 return -ENFILE;
114 fpp++;
115 }
116 *fpp = f;
117 f->f_flags = mode;
118 f->f_mode = (mode+1) & O_ACCMODE;
119 f->f_inode = inode;
120 f->f_pos = 0;
121 f->f_reada = 0;
122 f->f_op = inode->i_op->default_file_ops;
123 if (f->f_op->open) {
124 error = f->f_op->open(inode,f);
125 if (error) {
126 *fpp = NULL;
127 f->f_count--;
128 return error;
129 }
130 }
131 inode->i_count++;
132 return fd;
133 }
134
135
136
137
138
139 #define DUMP_WRITE(addr,nr) \
140 while (file.f_op->write(inode,&file,(char *)(addr),(nr)) != (nr)) goto close_coredump
141
142 #define DUMP_SEEK(offset) \
143 if (file.f_op->lseek) { \
144 if (file.f_op->lseek(inode,&file,(offset),0) != (offset)) \
145 goto close_coredump; \
146 } else file.f_pos = (offset)
147
148
149
150
151
152
153
154
155
156
157 int core_dump(long signr, struct pt_regs * regs)
158 {
159 struct inode * inode = NULL;
160 struct file file;
161 unsigned short fs;
162 int has_dumped = 0;
163 char corefile[6+sizeof(current->comm)];
164 int i;
165 register int dump_start, dump_size;
166 struct user dump;
167
168 if (!current->dumpable)
169 return 0;
170 current->dumpable = 0;
171
172
173 if (current->rlim[RLIMIT_CORE].rlim_cur < PAGE_SIZE)
174 return 0;
175 fs = get_fs();
176 set_fs(KERNEL_DS);
177 memcpy(corefile,"core.",5);
178 #if 0
179 memcpy(corefile+5,current->comm,sizeof(current->comm));
180 #else
181 corefile[4] = '\0';
182 #endif
183 if (open_namei(corefile,O_CREAT | 2 | O_TRUNC,0600,&inode,NULL)) {
184 inode = NULL;
185 goto end_coredump;
186 }
187 if (!S_ISREG(inode->i_mode))
188 goto end_coredump;
189 if (!inode->i_op || !inode->i_op->default_file_ops)
190 goto end_coredump;
191 file.f_mode = 3;
192 file.f_flags = 0;
193 file.f_count = 1;
194 file.f_inode = inode;
195 file.f_pos = 0;
196 file.f_reada = 0;
197 file.f_op = inode->i_op->default_file_ops;
198 if (file.f_op->open)
199 if (file.f_op->open(inode,&file))
200 goto end_coredump;
201 if (!file.f_op->write)
202 goto close_coredump;
203 has_dumped = 1;
204
205 dump.magic = CMAGIC;
206 dump.start_code = 0;
207 dump.start_stack = regs->esp & ~(PAGE_SIZE - 1);
208 dump.u_tsize = ((unsigned long) current->mm->end_code) >> 12;
209 dump.u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> 12;
210 dump.u_dsize -= dump.u_tsize;
211 dump.u_ssize = 0;
212 for(i=0; i<8; i++) dump.u_debugreg[i] = current->debugreg[i];
213 if (dump.start_stack < TASK_SIZE)
214 dump.u_ssize = ((unsigned long) (TASK_SIZE - dump.start_stack)) >> 12;
215
216
217 if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE >
218 current->rlim[RLIMIT_CORE].rlim_cur)
219 dump.u_dsize = 0;
220
221 if ((dump.u_ssize+1) * PAGE_SIZE >
222 current->rlim[RLIMIT_CORE].rlim_cur)
223 dump.u_ssize = 0;
224 strncpy(dump.u_comm, current->comm, sizeof(current->comm));
225 dump.u_ar0 = (struct pt_regs *)(((int)(&dump.regs)) -((int)(&dump)));
226 dump.signal = signr;
227 dump.regs = *regs;
228
229
230 if (hard_math) {
231 if ((dump.u_fpvalid = current->used_math) != 0) {
232 if (last_task_used_math == current)
233 __asm__("clts ; fnsave %0": :"m" (dump.i387));
234 else
235 memcpy(&dump.i387,¤t->tss.i387.hard,sizeof(dump.i387));
236 }
237 } else {
238
239
240 dump.u_fpvalid = 0;
241 }
242 set_fs(KERNEL_DS);
243
244 DUMP_WRITE(&dump,sizeof(dump));
245
246 DUMP_SEEK(PAGE_SIZE);
247
248 set_fs(USER_DS);
249
250 if (dump.u_dsize != 0) {
251 dump_start = dump.u_tsize << 12;
252 dump_size = dump.u_dsize << 12;
253 DUMP_WRITE(dump_start,dump_size);
254 };
255
256 if (dump.u_ssize != 0) {
257 dump_start = dump.start_stack;
258 dump_size = dump.u_ssize << 12;
259 DUMP_WRITE(dump_start,dump_size);
260 };
261
262 set_fs(KERNEL_DS);
263 DUMP_WRITE(current,sizeof(*current));
264 close_coredump:
265 if (file.f_op->release)
266 file.f_op->release(inode,&file);
267 end_coredump:
268 set_fs(fs);
269 iput(inode);
270 return has_dumped;
271 }
272
273
274
275
276
277
278
279 asmlinkage int sys_uselib(const char * library)
280 {
281 int fd, retval;
282 struct file * file;
283 struct linux_binfmt * fmt;
284
285 fd = sys_open(library, 0, 0);
286 if (fd < 0)
287 return fd;
288 file = current->files->fd[fd];
289 retval = -ENOEXEC;
290 if (file && file->f_inode && file->f_op && file->f_op->read) {
291 for (fmt = formats ; fmt ; fmt = fmt->next) {
292 int (*fn)(int) = fmt->load_shlib;
293 if (!fn)
294 break;
295 retval = fn(fd);
296 if (retval != -ENOEXEC)
297 break;
298 }
299 }
300 sys_close(fd);
301 return retval;
302 }
303
304
305
306
307
308
309 unsigned long * create_tables(char * p,int argc,int envc,int ibcs)
310 {
311 unsigned long *argv,*envp;
312 unsigned long * sp;
313 struct vm_area_struct *mpnt;
314
315 mpnt = (struct vm_area_struct *)kmalloc(sizeof(*mpnt), GFP_KERNEL);
316 if (mpnt) {
317 mpnt->vm_task = current;
318 mpnt->vm_start = PAGE_MASK & (unsigned long) p;
319 mpnt->vm_end = TASK_SIZE;
320 mpnt->vm_page_prot = PAGE_PRIVATE|PAGE_DIRTY;
321 mpnt->vm_share = NULL;
322 mpnt->vm_inode = NULL;
323 mpnt->vm_offset = 0;
324 mpnt->vm_ops = NULL;
325 insert_vm_struct(current, mpnt);
326 current->mm->stk_vma = mpnt;
327 }
328 sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
329 sp -= envc+1;
330 envp = sp;
331 sp -= argc+1;
332 argv = sp;
333 if (!ibcs) {
334 put_fs_long((unsigned long)envp,--sp);
335 put_fs_long((unsigned long)argv,--sp);
336 }
337 put_fs_long((unsigned long)argc,--sp);
338 current->mm->arg_start = (unsigned long) p;
339 while (argc-->0) {
340 put_fs_long((unsigned long) p,argv++);
341 while (get_fs_byte(p++)) ;
342 }
343 put_fs_long(0,argv);
344 current->mm->arg_end = current->mm->env_start = (unsigned long) p;
345 while (envc-->0) {
346 put_fs_long((unsigned long) p,envp++);
347 while (get_fs_byte(p++)) ;
348 }
349 put_fs_long(0,envp);
350 current->mm->env_end = (unsigned long) p;
351 return sp;
352 }
353
354
355
356
357 static int count(char ** argv)
358 {
359 int i=0;
360 char ** tmp;
361
362 if ((tmp = argv) != 0)
363 while (get_fs_long((unsigned long *) (tmp++)))
364 i++;
365
366 return i;
367 }
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386 unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
387 unsigned long p, int from_kmem)
388 {
389 char *tmp, *pag = NULL;
390 int len, offset = 0;
391 unsigned long old_fs, new_fs;
392
393 if (!p)
394 return 0;
395 new_fs = get_ds();
396 old_fs = get_fs();
397 if (from_kmem==2)
398 set_fs(new_fs);
399 while (argc-- > 0) {
400 if (from_kmem == 1)
401 set_fs(new_fs);
402 if (!(tmp = (char *)get_fs_long(((unsigned long *)argv)+argc)))
403 panic("VFS: argc is wrong");
404 if (from_kmem == 1)
405 set_fs(old_fs);
406 len=0;
407 do {
408 len++;
409 } while (get_fs_byte(tmp++));
410 if (p < len) {
411 set_fs(old_fs);
412 return 0;
413 }
414 while (len) {
415 --p; --tmp; --len;
416 if (--offset < 0) {
417 offset = p % PAGE_SIZE;
418 if (from_kmem==2)
419 set_fs(old_fs);
420 if (!(pag = (char *) page[p/PAGE_SIZE]) &&
421 !(pag = (char *) page[p/PAGE_SIZE] =
422 (unsigned long *) get_free_page(GFP_USER)))
423 return 0;
424 if (from_kmem==2)
425 set_fs(new_fs);
426
427 }
428 *(pag + offset) = get_fs_byte(tmp);
429 }
430 }
431 if (from_kmem==2)
432 set_fs(old_fs);
433 return p;
434 }
435
436 unsigned long change_ldt(unsigned long text_size,unsigned long * page)
437 {
438 unsigned long code_limit,data_limit,code_base,data_base;
439 int i;
440
441 code_limit = TASK_SIZE;
442 data_limit = TASK_SIZE;
443 code_base = data_base = 0;
444 current->mm->start_code = code_base;
445 data_base += data_limit;
446 for (i=MAX_ARG_PAGES-1 ; i>=0 ; i--) {
447 data_base -= PAGE_SIZE;
448 if (page[i]) {
449 current->mm->rss++;
450 put_dirty_page(current,page[i],data_base);
451 }
452 }
453 return data_limit;
454 }
455
456
457
458
459
460
461 int read_exec(struct inode *inode, unsigned long offset,
462 char * addr, unsigned long count)
463 {
464 struct file file;
465 int result = -ENOEXEC;
466
467 if (!inode->i_op || !inode->i_op->default_file_ops)
468 goto end_readexec;
469 file.f_mode = 1;
470 file.f_flags = 0;
471 file.f_count = 1;
472 file.f_inode = inode;
473 file.f_pos = 0;
474 file.f_reada = 0;
475 file.f_op = inode->i_op->default_file_ops;
476 if (file.f_op->open)
477 if (file.f_op->open(inode,&file))
478 goto end_readexec;
479 if (!file.f_op || !file.f_op->read)
480 goto close_readexec;
481 if (file.f_op->lseek) {
482 if (file.f_op->lseek(inode,&file,offset,0) != offset)
483 goto close_readexec;
484 } else
485 file.f_pos = offset;
486 if (get_fs() == USER_DS) {
487 result = verify_area(VERIFY_WRITE, addr, count);
488 if (result)
489 goto close_readexec;
490 }
491 result = file.f_op->read(inode, &file, addr, count);
492 close_readexec:
493 if (file.f_op->release)
494 file.f_op->release(inode,&file);
495 end_readexec:
496 return result;
497 }
498
499
500
501
502
503
504
505 void flush_old_exec(struct linux_binprm * bprm)
506 {
507 int i;
508 int ch;
509 char * name;
510 struct vm_area_struct * mpnt, *mpnt1;
511
512 current->dumpable = 1;
513 name = bprm->filename;
514 for (i=0; (ch = *(name++)) != '\0';) {
515 if (ch == '/')
516 i = 0;
517 else
518 if (i < 15)
519 current->comm[i++] = ch;
520 }
521 current->comm[i] = '\0';
522 if (current->shm)
523 shm_exit();
524 if (current->executable) {
525 iput(current->executable);
526 current->executable = NULL;
527 }
528
529
530 mpnt = current->mm->mmap;
531 current->mm->mmap = NULL;
532 current->mm->stk_vma = NULL;
533 while (mpnt) {
534 mpnt1 = mpnt->vm_next;
535 if (mpnt->vm_ops && mpnt->vm_ops->close)
536 mpnt->vm_ops->close(mpnt);
537 kfree(mpnt);
538 mpnt = mpnt1;
539 }
540
541
542 if (current->ldt) {
543 free_page((unsigned long) current->ldt);
544 current->ldt = NULL;
545 for (i=1 ; i<NR_TASKS ; i++) {
546 if (task[i] == current) {
547 set_ldt_desc(gdt+(i<<1)+
548 FIRST_LDT_ENTRY,&default_ldt, 1);
549 load_ldt(i);
550 }
551 }
552 }
553
554 for (i=0 ; i<8 ; i++) current->debugreg[i] = 0;
555
556 if (bprm->e_uid != current->euid || bprm->e_gid != current->egid ||
557 !permission(bprm->inode,MAY_READ))
558 current->dumpable = 0;
559 current->signal = 0;
560 for (i=0 ; i<32 ; i++) {
561 current->sigaction[i].sa_mask = 0;
562 current->sigaction[i].sa_flags = 0;
563 if (current->sigaction[i].sa_handler != SIG_IGN)
564 current->sigaction[i].sa_handler = NULL;
565 }
566 for (i=0 ; i<NR_OPEN ; i++)
567 if (FD_ISSET(i,¤t->files->close_on_exec))
568 sys_close(i);
569 FD_ZERO(¤t->files->close_on_exec);
570 clear_page_tables(current);
571 if (last_task_used_math == current)
572 last_task_used_math = NULL;
573 current->used_math = 0;
574 current->personality = 0;
575 current->lcall7 = no_lcall7;
576 current->signal_map = current->signal_invmap = ident_map;
577 }
578
579
580
581
582 int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs)
583 {
584 struct linux_binprm bprm;
585 struct linux_binfmt * fmt;
586 unsigned long old_fs;
587 int i;
588 int retval;
589 int sh_bang = 0;
590
591 if (regs->cs != USER_CS)
592 return -EINVAL;
593 bprm.p = PAGE_SIZE*MAX_ARG_PAGES-4;
594 for (i=0 ; i<MAX_ARG_PAGES ; i++)
595 bprm.page[i] = 0;
596 retval = open_namei(filename, 0, 0, &bprm.inode, NULL);
597 if (retval)
598 return retval;
599 bprm.filename = filename;
600 bprm.argc = count(argv);
601 bprm.envc = count(envp);
602
603 restart_interp:
604 if (!S_ISREG(bprm.inode->i_mode)) {
605 retval = -EACCES;
606 goto exec_error2;
607 }
608 if (IS_NOEXEC(bprm.inode)) {
609 retval = -EPERM;
610 goto exec_error2;
611 }
612 if (!bprm.inode->i_sb) {
613 retval = -EACCES;
614 goto exec_error2;
615 }
616 i = bprm.inode->i_mode;
617 if (IS_NOSUID(bprm.inode) && (((i & S_ISUID) && bprm.inode->i_uid != current->
618 euid) || ((i & S_ISGID) && !in_group_p(bprm.inode->i_gid))) &&
619 !suser()) {
620 retval = -EPERM;
621 goto exec_error2;
622 }
623
624 if (current->flags & PF_PTRACED) {
625 bprm.e_uid = current->euid;
626 bprm.e_gid = current->egid;
627 } else {
628 bprm.e_uid = (i & S_ISUID) ? bprm.inode->i_uid : current->euid;
629 bprm.e_gid = (i & S_ISGID) ? bprm.inode->i_gid : current->egid;
630 }
631 if (current->euid == bprm.inode->i_uid)
632 i >>= 6;
633 else if (in_group_p(bprm.inode->i_gid))
634 i >>= 3;
635 if (!(i & 1) &&
636 !((bprm.inode->i_mode & 0111) && suser())) {
637 retval = -EACCES;
638 goto exec_error2;
639 }
640 memset(bprm.buf,0,sizeof(bprm.buf));
641 old_fs = get_fs();
642 set_fs(get_ds());
643 retval = read_exec(bprm.inode,0,bprm.buf,128);
644 set_fs(old_fs);
645 if (retval < 0)
646 goto exec_error2;
647 if ((bprm.buf[0] == '#') && (bprm.buf[1] == '!') && (!sh_bang)) {
648
649
650
651
652
653 char *cp, *interp, *i_name, *i_arg;
654
655 iput(bprm.inode);
656 bprm.buf[127] = '\0';
657 if ((cp = strchr(bprm.buf, '\n')) == NULL)
658 cp = bprm.buf+127;
659 *cp = '\0';
660 while (cp > bprm.buf) {
661 cp--;
662 if ((*cp == ' ') || (*cp == '\t'))
663 *cp = '\0';
664 else
665 break;
666 }
667 for (cp = bprm.buf+2; (*cp == ' ') || (*cp == '\t'); cp++);
668 if (!cp || *cp == '\0') {
669 retval = -ENOEXEC;
670 goto exec_error1;
671 }
672 interp = i_name = cp;
673 i_arg = 0;
674 for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) {
675 if (*cp == '/')
676 i_name = cp+1;
677 }
678 while ((*cp == ' ') || (*cp == '\t'))
679 *cp++ = '\0';
680 if (*cp)
681 i_arg = cp;
682
683
684
685
686 if (sh_bang++ == 0) {
687 bprm.p = copy_strings(bprm.envc, envp, bprm.page, bprm.p, 0);
688 bprm.p = copy_strings(--bprm.argc, argv+1, bprm.page, bprm.p, 0);
689 }
690
691
692
693
694
695
696
697
698 bprm.p = copy_strings(1, &bprm.filename, bprm.page, bprm.p, 2);
699 bprm.argc++;
700 if (i_arg) {
701 bprm.p = copy_strings(1, &i_arg, bprm.page, bprm.p, 2);
702 bprm.argc++;
703 }
704 bprm.p = copy_strings(1, &i_name, bprm.page, bprm.p, 2);
705 bprm.argc++;
706 if (!bprm.p) {
707 retval = -E2BIG;
708 goto exec_error1;
709 }
710
711
712
713
714
715 retval = open_namei(interp, 0, 0, &bprm.inode, NULL);
716 if (retval)
717 goto exec_error1;
718 goto restart_interp;
719 }
720 if (!sh_bang) {
721 bprm.p = copy_strings(bprm.envc,envp,bprm.page,bprm.p,0);
722 bprm.p = copy_strings(bprm.argc,argv,bprm.page,bprm.p,0);
723 if (!bprm.p) {
724 retval = -E2BIG;
725 goto exec_error2;
726 }
727 }
728
729 bprm.sh_bang = sh_bang;
730 for (fmt = formats ; fmt ; fmt = fmt->next) {
731 int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary;
732 if (!fn)
733 break;
734 retval = fn(&bprm, regs);
735 if (retval == 0) {
736 iput(bprm.inode);
737 current->did_exec = 1;
738 return 0;
739 }
740 if (retval != -ENOEXEC)
741 break;
742 }
743 exec_error2:
744 iput(bprm.inode);
745 exec_error1:
746 for (i=0 ; i<MAX_ARG_PAGES ; i++)
747 free_page(bprm.page[i]);
748 return(retval);
749 }
750
751
752
753
754 asmlinkage int sys_execve(struct pt_regs regs)
755 {
756 int error;
757 char * filename;
758
759 error = getname((char *) regs.ebx, &filename);
760 if (error)
761 return error;
762 error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, ®s);
763 putname(filename);
764 return error;
765 }
766
767
768
769
770
771 unsigned long ident_map[33] = {
772 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
773 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
774 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
775 };
776
777
778
779
780
781 asmlinkage void no_lcall7(struct pt_regs * regs)
782 {
783 send_sig(SIGSEGV, current, 1);
784 }
785
786 static void set_brk(unsigned long start, unsigned long end)
787 {
788 start = PAGE_ALIGN(start);
789 end = PAGE_ALIGN(end);
790 if (end <= start)
791 return;
792 do_mmap(NULL, start, end - start,
793 PROT_READ | PROT_WRITE | PROT_EXEC,
794 MAP_FIXED | MAP_PRIVATE, 0);
795 }
796
797
798
799
800
801
802 static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
803 {
804 struct exec ex;
805 struct file * file;
806 int fd, error;
807 unsigned long p = bprm->p;
808
809 ex = *((struct exec *) bprm->buf);
810 if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
811 N_MAGIC(ex) != QMAGIC) ||
812 ex.a_trsize || ex.a_drsize ||
813 bprm->inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
814 return -ENOEXEC;
815 }
816
817 if (N_MAGIC(ex) == ZMAGIC &&
818 (N_TXTOFF(ex) < bprm->inode->i_sb->s_blocksize)) {
819 printk("N_TXTOFF < BLOCK_SIZE. Please convert binary.");
820 return -ENOEXEC;
821 }
822
823 if (N_TXTOFF(ex) != BLOCK_SIZE && N_MAGIC(ex) == ZMAGIC) {
824 printk("N_TXTOFF != BLOCK_SIZE. See a.out.h.");
825 return -ENOEXEC;
826 }
827
828
829 flush_old_exec(bprm);
830
831 current->mm->brk = ex.a_bss +
832 (current->mm->start_brk =
833 (current->mm->end_data = ex.a_data +
834 (current->mm->end_code = ex.a_text +
835 (current->mm->start_code = N_TXTADDR(ex)))));
836 current->mm->rss = 0;
837 current->mm->mmap = NULL;
838 current->executable = NULL;
839 current->suid = current->euid = bprm->e_uid;
840 current->sgid = current->egid = bprm->e_gid;
841 if (N_MAGIC(ex) == OMAGIC) {
842 do_mmap(NULL, 0, ex.a_text+ex.a_data,
843 PROT_READ|PROT_WRITE|PROT_EXEC,
844 MAP_FIXED|MAP_PRIVATE, 0);
845 read_exec(bprm->inode, 32, (char *) 0, ex.a_text+ex.a_data);
846 } else {
847 if (ex.a_text & 0xfff || ex.a_data & 0xfff)
848 printk("%s: executable not page aligned\n", current->comm);
849
850 fd = open_inode(bprm->inode, O_RDONLY);
851
852 if (fd < 0)
853 return fd;
854 file = current->files->fd[fd];
855 if (!file->f_op || !file->f_op->mmap) {
856 sys_close(fd);
857 do_mmap(NULL, 0, ex.a_text+ex.a_data,
858 PROT_READ|PROT_WRITE|PROT_EXEC,
859 MAP_FIXED|MAP_PRIVATE, 0);
860 read_exec(bprm->inode, N_TXTOFF(ex),
861 (char *) N_TXTADDR(ex), ex.a_text+ex.a_data);
862 goto beyond_if;
863 }
864 error = do_mmap(file, N_TXTADDR(ex), ex.a_text,
865 PROT_READ | PROT_EXEC,
866 MAP_FIXED | MAP_SHARED, N_TXTOFF(ex));
867
868 if (error != N_TXTADDR(ex)) {
869 sys_close(fd);
870 send_sig(SIGSEGV, current, 0);
871 return 0;
872 };
873
874 error = do_mmap(file, N_TXTADDR(ex) + ex.a_text, ex.a_data,
875 PROT_READ | PROT_WRITE | PROT_EXEC,
876 MAP_FIXED | MAP_PRIVATE, N_TXTOFF(ex) + ex.a_text);
877 sys_close(fd);
878 if (error != N_TXTADDR(ex) + ex.a_text) {
879 send_sig(SIGSEGV, current, 0);
880 return 0;
881 };
882 current->executable = bprm->inode;
883 bprm->inode->i_count++;
884 }
885 beyond_if:
886 set_brk(current->mm->start_brk, current->mm->brk);
887
888 p += change_ldt(ex.a_text,bprm->page);
889 p -= MAX_ARG_PAGES*PAGE_SIZE;
890 p = (unsigned long) create_tables((char *)p,bprm->argc,bprm->envc,0);
891 current->mm->start_stack = p;
892 regs->eip = ex.a_entry;
893 regs->esp = p;
894 if (current->flags & PF_PTRACED)
895 send_sig(SIGTRAP, current, 0);
896 return 0;
897 }
898
899
900 static int load_aout_library(int fd)
901 {
902 struct file * file;
903 struct exec ex;
904 struct inode * inode;
905 unsigned int len;
906 unsigned int bss;
907 unsigned int start_addr;
908 int error;
909
910 file = current->files->fd[fd];
911 inode = file->f_inode;
912
913 set_fs(KERNEL_DS);
914 if (file->f_op->read(inode, file, (char *) &ex, sizeof(ex)) != sizeof(ex)) {
915 return -EACCES;
916 }
917 set_fs(USER_DS);
918
919
920 if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || ex.a_trsize ||
921 ex.a_drsize || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
922 inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
923 return -ENOEXEC;
924 }
925 if (N_MAGIC(ex) == ZMAGIC && N_TXTOFF(ex) &&
926 (N_TXTOFF(ex) < inode->i_sb->s_blocksize)) {
927 printk("N_TXTOFF < BLOCK_SIZE. Please convert library\n");
928 return -ENOEXEC;
929 }
930
931 if (N_FLAGS(ex)) return -ENOEXEC;
932
933
934
935
936 start_addr = ex.a_entry & 0xfffff000;
937
938
939 error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
940 PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE,
941 N_TXTOFF(ex));
942 if (error != start_addr)
943 return error;
944 len = PAGE_ALIGN(ex.a_text + ex.a_data);
945 bss = ex.a_text + ex.a_data + ex.a_bss;
946 if (bss > len)
947 do_mmap(NULL, start_addr + len, bss-len,
948 PROT_READ|PROT_WRITE|PROT_EXEC,
949 MAP_PRIVATE|MAP_FIXED, 0);
950 return 0;
951 }