This source file includes following definitions.
- binfmt_setup
- register_binfmt
- unregister_binfmt
- open_inode
- sys_uselib
- create_tables
- count
- copy_strings
- setup_arg_pages
- read_exec
- exec_mmap
- flush_old_exec
- do_execve
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 #include <linux/fs.h>
26 #include <linux/sched.h>
27 #include <linux/kernel.h>
28 #include <linux/mm.h>
29 #include <linux/mman.h>
30 #include <linux/a.out.h>
31 #include <linux/errno.h>
32 #include <linux/signal.h>
33 #include <linux/string.h>
34 #include <linux/stat.h>
35 #include <linux/fcntl.h>
36 #include <linux/ptrace.h>
37 #include <linux/user.h>
38 #include <linux/malloc.h>
39 #include <linux/binfmts.h>
40 #include <linux/personality.h>
41
42 #include <asm/system.h>
43 #include <asm/segment.h>
44 #include <asm/pgtable.h>
45
46 #include <linux/config.h>
47 #ifdef CONFIG_KERNELD
48 #include <linux/kerneld.h>
49 #endif
50
51 asmlinkage int sys_exit(int exit_code);
52 asmlinkage int sys_brk(unsigned long);
53
54
55
56
57
58
59
60
61
62 static struct linux_binfmt *formats = (struct linux_binfmt *) NULL;
63
64 void binfmt_setup(void)
65 {
66 #ifdef CONFIG_BINFMT_ELF
67 init_elf_binfmt();
68 #endif
69
70 #ifdef CONFIG_BINFMT_AOUT
71 init_aout_binfmt();
72 #endif
73 }
74
75 int register_binfmt(struct linux_binfmt * fmt)
76 {
77 struct linux_binfmt ** tmp = &formats;
78
79 if (!fmt)
80 return -EINVAL;
81 if (fmt->next)
82 return -EBUSY;
83 while (*tmp) {
84 if (fmt == *tmp)
85 return -EBUSY;
86 tmp = &(*tmp)->next;
87 }
88 fmt->next = formats;
89 formats = fmt;
90 return 0;
91 }
92
93 #ifdef CONFIG_MODULES
94 int unregister_binfmt(struct linux_binfmt * fmt)
95 {
96 struct linux_binfmt ** tmp = &formats;
97
98 while (*tmp) {
99 if (fmt == *tmp) {
100 *tmp = fmt->next;
101 return 0;
102 }
103 tmp = &(*tmp)->next;
104 }
105 return -EINVAL;
106 }
107 #endif
108
109 int open_inode(struct inode * inode, int mode)
110 {
111 int error, fd;
112 struct file *f, **fpp;
113
114 if (!inode->i_op || !inode->i_op->default_file_ops)
115 return -EINVAL;
116 f = get_empty_filp();
117 if (!f)
118 return -ENFILE;
119 fd = 0;
120 fpp = current->files->fd;
121 for (;;) {
122 if (!*fpp)
123 break;
124 if (++fd >= NR_OPEN) {
125 f->f_count--;
126 return -EMFILE;
127 }
128 fpp++;
129 }
130 *fpp = f;
131 f->f_flags = mode;
132 f->f_mode = (mode+1) & O_ACCMODE;
133 f->f_inode = inode;
134 f->f_pos = 0;
135 f->f_reada = 0;
136 f->f_op = inode->i_op->default_file_ops;
137 if (f->f_op->open) {
138 error = f->f_op->open(inode,f);
139 if (error) {
140 *fpp = NULL;
141 f->f_count--;
142 return error;
143 }
144 }
145 inode->i_count++;
146 return fd;
147 }
148
149
150
151
152
153
154
155 asmlinkage int sys_uselib(const char * library)
156 {
157 int fd, retval;
158 struct file * file;
159 struct linux_binfmt * fmt;
160
161 fd = sys_open(library, 0, 0);
162 if (fd < 0)
163 return fd;
164 file = current->files->fd[fd];
165 retval = -ENOEXEC;
166 if (file && file->f_inode && file->f_op && file->f_op->read) {
167 for (fmt = formats ; fmt ; fmt = fmt->next) {
168 int (*fn)(int) = fmt->load_shlib;
169 if (!fn)
170 break;
171 retval = fn(fd);
172 if (retval != -ENOEXEC)
173 break;
174 }
175 }
176 sys_close(fd);
177 return retval;
178 }
179
180
181
182
183
184
185 unsigned long * create_tables(char * p, struct linux_binprm * bprm, int ibcs)
186 {
187 unsigned long *argv,*envp;
188 unsigned long * sp;
189 struct vm_area_struct *mpnt;
190 int argc = bprm->argc;
191 int envc = bprm->envc;
192
193 mpnt = (struct vm_area_struct *)kmalloc(sizeof(*mpnt), GFP_KERNEL);
194 if (mpnt) {
195 mpnt->vm_mm = current->mm;
196 mpnt->vm_start = PAGE_MASK & (unsigned long) p;
197 mpnt->vm_end = STACK_TOP;
198 mpnt->vm_page_prot = PAGE_COPY;
199 mpnt->vm_flags = VM_STACK_FLAGS;
200 mpnt->vm_ops = NULL;
201 mpnt->vm_offset = 0;
202 mpnt->vm_inode = NULL;
203 mpnt->vm_pte = 0;
204 insert_vm_struct(current, mpnt);
205 current->mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
206 }
207 sp = (unsigned long *) ((-(unsigned long)sizeof(char *)) & (unsigned long) p);
208 #ifdef __alpha__
209
210 put_user(0, --sp);
211 put_user(0, --sp);
212 if (bprm->loader) {
213 put_user(0, --sp);
214 put_user(0x3eb, --sp);
215 put_user(bprm->loader, --sp);
216 put_user(0x3ea, --sp);
217 }
218 put_user(bprm->exec, --sp);
219 put_user(0x3e9, --sp);
220 #endif
221 sp -= envc+1;
222 envp = sp;
223 sp -= argc+1;
224 argv = sp;
225 #ifdef __i386__
226 if (!ibcs) {
227 put_user(envp,--sp);
228 put_user(argv,--sp);
229 }
230 #endif
231 put_user(argc,--sp);
232 current->mm->arg_start = (unsigned long) p;
233 while (argc-->0) {
234 put_user(p,argv++);
235 while (get_user(p++)) ;
236 }
237 put_user(NULL,argv);
238 current->mm->arg_end = current->mm->env_start = (unsigned long) p;
239 while (envc-->0) {
240 put_user(p,envp++);
241 while (get_user(p++)) ;
242 }
243 put_user(NULL,envp);
244 current->mm->env_end = (unsigned long) p;
245 return sp;
246 }
247
248
249
250
251
252
253
254 static int count(char ** argv)
255 {
256 int error, i = 0;
257 char ** tmp, *p;
258
259 if ((tmp = argv) != NULL) {
260 error = verify_area(VERIFY_READ, tmp, sizeof(char *));
261 if (error)
262 return error;
263 while ((p = get_user(tmp++)) != NULL) {
264 i++;
265 error = verify_area(VERIFY_READ, p, 1);
266 if (error)
267 return error;
268 }
269 }
270 return i;
271 }
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290 unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
291 unsigned long p, int from_kmem)
292 {
293 char *tmp, *pag = NULL;
294 int len, offset = 0;
295 unsigned long old_fs, new_fs;
296
297 if (!p)
298 return 0;
299 new_fs = get_ds();
300 old_fs = get_fs();
301 if (from_kmem==2)
302 set_fs(new_fs);
303 while (argc-- > 0) {
304 if (from_kmem == 1)
305 set_fs(new_fs);
306 if (!(tmp = get_user(argv+argc)))
307 panic("VFS: argc is wrong");
308 if (from_kmem == 1)
309 set_fs(old_fs);
310 len=0;
311 do {
312 len++;
313 } while (get_user(tmp++));
314 if (p < len) {
315 set_fs(old_fs);
316 return 0;
317 }
318 while (len) {
319 --p; --tmp; --len;
320 if (--offset < 0) {
321 offset = p % PAGE_SIZE;
322 if (from_kmem==2)
323 set_fs(old_fs);
324 if (!(pag = (char *) page[p/PAGE_SIZE]) &&
325 !(pag = (char *) page[p/PAGE_SIZE] =
326 (unsigned long *) get_free_page(GFP_USER)))
327 return 0;
328 if (from_kmem==2)
329 set_fs(new_fs);
330
331 }
332 *(pag + offset) = get_user(tmp);
333 }
334 }
335 if (from_kmem==2)
336 set_fs(old_fs);
337 return p;
338 }
339
340 unsigned long setup_arg_pages(unsigned long text_size, unsigned long * page)
341 {
342 unsigned long data_base;
343 int i;
344
345 data_base = STACK_TOP;
346 for (i=MAX_ARG_PAGES-1 ; i>=0 ; i--) {
347 data_base -= PAGE_SIZE;
348 if (page[i]) {
349 current->mm->rss++;
350 put_dirty_page(current,page[i],data_base);
351 }
352 }
353 return STACK_TOP;
354 }
355
356
357
358
359
360
361 int read_exec(struct inode *inode, unsigned long offset,
362 char * addr, unsigned long count, int to_kmem)
363 {
364 struct file file;
365 int result = -ENOEXEC;
366
367 if (!inode->i_op || !inode->i_op->default_file_ops)
368 goto end_readexec;
369 file.f_mode = 1;
370 file.f_flags = 0;
371 file.f_count = 1;
372 file.f_inode = inode;
373 file.f_pos = 0;
374 file.f_reada = 0;
375 file.f_op = inode->i_op->default_file_ops;
376 if (file.f_op->open)
377 if (file.f_op->open(inode,&file))
378 goto end_readexec;
379 if (!file.f_op || !file.f_op->read)
380 goto close_readexec;
381 if (file.f_op->lseek) {
382 if (file.f_op->lseek(inode,&file,offset,0) != offset)
383 goto close_readexec;
384 } else
385 file.f_pos = offset;
386 if (to_kmem) {
387 unsigned long old_fs = get_fs();
388 set_fs(get_ds());
389 result = file.f_op->read(inode, &file, addr, count);
390 set_fs(old_fs);
391 } else {
392 result = verify_area(VERIFY_WRITE, addr, count);
393 if (result)
394 goto close_readexec;
395 result = file.f_op->read(inode, &file, addr, count);
396 }
397 close_readexec:
398 if (file.f_op->release)
399 file.f_op->release(inode,&file);
400 end_readexec:
401 return result;
402 }
403
404 static void exec_mmap(void)
405 {
406
407
408
409
410
411 if (current->mm->count > 1) {
412 struct mm_struct *mm = kmalloc(sizeof(*mm), GFP_KERNEL);
413 if (!mm) {
414
415 oom(current);
416 return;
417 }
418 *mm = *current->mm;
419 mm->def_flags = 0;
420 mm->count = 1;
421 mm->mmap = NULL;
422 mm->mmap_avl = NULL;
423 mm->total_vm = 0;
424 mm->rss = 0;
425 current->mm->count--;
426 current->mm = mm;
427 new_page_tables(current);
428 return;
429 }
430 exit_mmap(current->mm);
431 clear_page_tables(current);
432 }
433
434
435
436
437
438
439 void flush_old_exec(struct linux_binprm * bprm)
440 {
441 int i;
442 int ch;
443 char * name;
444
445 if (current->euid == current->uid && current->egid == current->gid)
446 current->dumpable = 1;
447 name = bprm->filename;
448 for (i=0; (ch = *(name++)) != '\0';) {
449 if (ch == '/')
450 i = 0;
451 else
452 if (i < 15)
453 current->comm[i++] = ch;
454 }
455 current->comm[i] = '\0';
456
457
458 exec_mmap();
459
460 flush_thread();
461
462 if (bprm->e_uid != current->euid || bprm->e_gid != current->egid ||
463 permission(bprm->inode,MAY_READ))
464 current->dumpable = 0;
465 current->signal = 0;
466 for (i=0 ; i<32 ; i++) {
467 current->sig->action[i].sa_mask = 0;
468 current->sig->action[i].sa_flags = 0;
469 if (current->sig->action[i].sa_handler != SIG_IGN)
470 current->sig->action[i].sa_handler = NULL;
471 }
472 for (i=0 ; i<NR_OPEN ; i++)
473 if (FD_ISSET(i,¤t->files->close_on_exec))
474 sys_close(i);
475 FD_ZERO(¤t->files->close_on_exec);
476 if (last_task_used_math == current)
477 last_task_used_math = NULL;
478 current->used_math = 0;
479 }
480
481
482
483
484 int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs)
485 {
486 struct linux_binprm bprm;
487 struct linux_binfmt * fmt;
488 int i;
489 int retval;
490 int sh_bang = 0;
491 int try;
492 #ifdef __alpha__
493 int loader = 0;
494 #endif
495
496 bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
497 for (i=0 ; i<MAX_ARG_PAGES ; i++)
498 bprm.page[i] = 0;
499 retval = open_namei(filename, 0, 0, &bprm.inode, NULL);
500 if (retval)
501 return retval;
502 bprm.filename = filename;
503 bprm.loader = 0;
504 bprm.exec = 0;
505 if ((bprm.argc = count(argv)) < 0)
506 return bprm.argc;
507 if ((bprm.envc = count(envp)) < 0)
508 return bprm.envc;
509
510 restart_interp:
511 if (!S_ISREG(bprm.inode->i_mode)) {
512 retval = -EACCES;
513 goto exec_error2;
514 }
515 if (IS_NOEXEC(bprm.inode)) {
516 retval = -EPERM;
517 goto exec_error2;
518 }
519 if (!bprm.inode->i_sb) {
520 retval = -EACCES;
521 goto exec_error2;
522 }
523 i = bprm.inode->i_mode;
524 if (IS_NOSUID(bprm.inode) && (((i & S_ISUID) && bprm.inode->i_uid != current->
525 euid) || ((i & S_ISGID) && !in_group_p(bprm.inode->i_gid))) && !suser()) {
526 retval = -EPERM;
527 goto exec_error2;
528 }
529
530 if (current->flags & PF_PTRACED) {
531 bprm.e_uid = current->euid;
532 bprm.e_gid = current->egid;
533 } else {
534 bprm.e_uid = (i & S_ISUID) ? bprm.inode->i_uid : current->euid;
535 bprm.e_gid = (i & S_ISGID) ? bprm.inode->i_gid : current->egid;
536 }
537 if ((retval = permission(bprm.inode, MAY_EXEC)) != 0)
538 goto exec_error2;
539 if (!(bprm.inode->i_mode & 0111) && fsuser()) {
540 retval = -EACCES;
541 goto exec_error2;
542 }
543
544 if (bprm.inode->i_writecount > 0) {
545 retval = -ETXTBSY;
546 goto exec_error2;
547 }
548 memset(bprm.buf,0,sizeof(bprm.buf));
549 retval = read_exec(bprm.inode,0,bprm.buf,128,1);
550 if (retval < 0)
551 goto exec_error2;
552 if ((bprm.buf[0] == '#') && (bprm.buf[1] == '!') && (!sh_bang)) {
553
554
555
556
557
558 char *cp, *interp, *i_name, *i_arg;
559
560 iput(bprm.inode);
561 bprm.buf[127] = '\0';
562 if ((cp = strchr(bprm.buf, '\n')) == NULL)
563 cp = bprm.buf+127;
564 *cp = '\0';
565 while (cp > bprm.buf) {
566 cp--;
567 if ((*cp == ' ') || (*cp == '\t'))
568 *cp = '\0';
569 else
570 break;
571 }
572 for (cp = bprm.buf+2; (*cp == ' ') || (*cp == '\t'); cp++);
573 if (!cp || *cp == '\0') {
574 retval = -ENOEXEC;
575 goto exec_error1;
576 }
577 interp = i_name = cp;
578 i_arg = 0;
579 for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) {
580 if (*cp == '/')
581 i_name = cp+1;
582 }
583 while ((*cp == ' ') || (*cp == '\t'))
584 *cp++ = '\0';
585 if (*cp)
586 i_arg = cp;
587
588
589
590
591 if (sh_bang++ == 0) {
592 bprm.p = copy_strings(bprm.envc, envp, bprm.page, bprm.p, 0);
593 bprm.p = copy_strings(--bprm.argc, argv+1, bprm.page, bprm.p, 0);
594 }
595
596
597
598
599
600
601
602
603 bprm.p = copy_strings(1, &bprm.filename, bprm.page, bprm.p, 2);
604 bprm.argc++;
605 if (i_arg) {
606 bprm.p = copy_strings(1, &i_arg, bprm.page, bprm.p, 2);
607 bprm.argc++;
608 }
609 bprm.p = copy_strings(1, &i_name, bprm.page, bprm.p, 2);
610 bprm.argc++;
611 if (!bprm.p) {
612 retval = -E2BIG;
613 goto exec_error1;
614 }
615
616
617
618
619
620 retval = open_namei(interp, 0, 0, &bprm.inode, NULL);
621 if (retval)
622 goto exec_error1;
623 goto restart_interp;
624 }
625 #ifdef __alpha__
626
627 {
628 struct exec * eh = (struct exec *) bprm.buf;
629
630 if (!loader && eh->fh.f_magic == 0x183 &&
631 (eh->fh.f_flags & 0x3000) == 0x3000)
632 {
633 char * dynloader[] = { "/sbin/loader" };
634 iput(bprm.inode);
635 loader = 1;
636 bprm.p = copy_strings(1, dynloader, bprm.page, bprm.p, 2);
637 bprm.loader = bprm.p;
638 retval = open_namei(dynloader[0], 0, 0, &bprm.inode, NULL);
639 if (retval)
640 goto exec_error1;
641 goto restart_interp;
642 }
643 }
644 #endif
645 if (!sh_bang) {
646 bprm.p = copy_strings(1, &bprm.filename, bprm.page, bprm.p, 2);
647 bprm.exec = bprm.p;
648 bprm.p = copy_strings(bprm.envc,envp,bprm.page,bprm.p,0);
649 bprm.p = copy_strings(bprm.argc,argv,bprm.page,bprm.p,0);
650 if (!bprm.p) {
651 retval = -E2BIG;
652 goto exec_error2;
653 }
654 }
655
656 bprm.sh_bang = sh_bang;
657 for (try=0; try<2; try++) {
658 for (fmt = formats ; fmt ; fmt = fmt->next) {
659 int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary;
660 if (!fn)
661 break;
662 retval = fn(&bprm, regs);
663 if (retval >= 0) {
664 iput(bprm.inode);
665 current->did_exec = 1;
666 return retval;
667 }
668 if (retval != -ENOEXEC)
669 break;
670 }
671 if (retval != -ENOEXEC) {
672 break;
673 #ifdef CONFIG_KERNELD
674 }else{
675 #define printable(c) (((c)=='\t') || ((c)=='\n') || (0x20<=(c) && (c)<=0x7e))
676 char modname[20];
677 if (printable(bprm.buf[0]) &&
678 printable(bprm.buf[1]) &&
679 printable(bprm.buf[2]) &&
680 printable(bprm.buf[3]))
681 break;
682 sprintf(modname, "binfmt-%hd", *(short*)(&bprm.buf));
683 request_module(modname);
684 #endif
685 }
686 }
687 exec_error2:
688 iput(bprm.inode);
689 exec_error1:
690 for (i=0 ; i<MAX_ARG_PAGES ; i++)
691 free_page(bprm.page[i]);
692 return(retval);
693 }