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 continue;
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, *tmp1, *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 (!(tmp1 = tmp = get_user(argv+argc)))
307 panic("VFS: argc is wrong");
308 if (from_kmem == 1)
309 set_fs(old_fs);
310 while (get_user(tmp++));
311 len = tmp - tmp1;
312 if (p < len) {
313 set_fs(old_fs);
314 return 0;
315 }
316 while (len) {
317 --p; --tmp; --len;
318 if (--offset < 0) {
319 offset = p % PAGE_SIZE;
320 if (from_kmem==2)
321 set_fs(old_fs);
322 if (!(pag = (char *) page[p/PAGE_SIZE]) &&
323 !(pag = (char *) page[p/PAGE_SIZE] =
324 (unsigned long *) get_free_page(GFP_USER)))
325 return 0;
326 if (from_kmem==2)
327 set_fs(new_fs);
328
329 }
330 if (len == 0 || offset == 0)
331 *(pag + offset) = get_user(tmp);
332 else {
333 int bytes_to_copy = (len > offset) ? offset : len;
334 tmp -= bytes_to_copy;
335 p -= bytes_to_copy;
336 offset -= bytes_to_copy;
337 len -= bytes_to_copy;
338 memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
339 }
340 }
341 }
342 if (from_kmem==2)
343 set_fs(old_fs);
344 return p;
345 }
346
347 unsigned long setup_arg_pages(unsigned long text_size, unsigned long * page)
348 {
349 unsigned long data_base;
350 int i;
351
352 data_base = STACK_TOP;
353 for (i=MAX_ARG_PAGES-1 ; i>=0 ; i--) {
354 data_base -= PAGE_SIZE;
355 if (page[i]) {
356 current->mm->rss++;
357 put_dirty_page(current,page[i],data_base);
358 }
359 }
360 return STACK_TOP;
361 }
362
363
364
365
366
367
368 int read_exec(struct inode *inode, unsigned long offset,
369 char * addr, unsigned long count, int to_kmem)
370 {
371 struct file file;
372 int result = -ENOEXEC;
373
374 if (!inode->i_op || !inode->i_op->default_file_ops)
375 goto end_readexec;
376 file.f_mode = 1;
377 file.f_flags = 0;
378 file.f_count = 1;
379 file.f_inode = inode;
380 file.f_pos = 0;
381 file.f_reada = 0;
382 file.f_op = inode->i_op->default_file_ops;
383 if (file.f_op->open)
384 if (file.f_op->open(inode,&file))
385 goto end_readexec;
386 if (!file.f_op || !file.f_op->read)
387 goto close_readexec;
388 if (file.f_op->lseek) {
389 if (file.f_op->lseek(inode,&file,offset,0) != offset)
390 goto close_readexec;
391 } else
392 file.f_pos = offset;
393 if (to_kmem) {
394 unsigned long old_fs = get_fs();
395 set_fs(get_ds());
396 result = file.f_op->read(inode, &file, addr, count);
397 set_fs(old_fs);
398 } else {
399 result = verify_area(VERIFY_WRITE, addr, count);
400 if (result)
401 goto close_readexec;
402 result = file.f_op->read(inode, &file, addr, count);
403 }
404 close_readexec:
405 if (file.f_op->release)
406 file.f_op->release(inode,&file);
407 end_readexec:
408 return result;
409 }
410
411 static void exec_mmap(void)
412 {
413
414
415
416
417
418 if (current->mm->count > 1) {
419 struct mm_struct *mm = kmalloc(sizeof(*mm), GFP_KERNEL);
420 if (!mm) {
421
422 oom(current);
423 return;
424 }
425 *mm = *current->mm;
426 mm->def_flags = 0;
427 mm->count = 1;
428 mm->mmap = NULL;
429 mm->mmap_avl = NULL;
430 mm->total_vm = 0;
431 mm->rss = 0;
432 current->mm->count--;
433 current->mm = mm;
434 new_page_tables(current);
435 return;
436 }
437 exit_mmap(current->mm);
438 clear_page_tables(current);
439 }
440
441
442
443
444
445
446 void flush_old_exec(struct linux_binprm * bprm)
447 {
448 int i;
449 int ch;
450 char * name;
451
452 if (current->euid == current->uid && current->egid == current->gid)
453 current->dumpable = 1;
454 name = bprm->filename;
455 for (i=0; (ch = *(name++)) != '\0';) {
456 if (ch == '/')
457 i = 0;
458 else
459 if (i < 15)
460 current->comm[i++] = ch;
461 }
462 current->comm[i] = '\0';
463
464
465 exec_mmap();
466
467 flush_thread();
468
469 if (bprm->e_uid != current->euid || bprm->e_gid != current->egid ||
470 permission(bprm->inode,MAY_READ))
471 current->dumpable = 0;
472 current->signal = 0;
473 for (i=0 ; i<32 ; i++) {
474 current->sig->action[i].sa_mask = 0;
475 current->sig->action[i].sa_flags = 0;
476 if (current->sig->action[i].sa_handler != SIG_IGN)
477 current->sig->action[i].sa_handler = NULL;
478 }
479 for (i=0 ; i<NR_OPEN ; i++)
480 if (FD_ISSET(i,¤t->files->close_on_exec))
481 sys_close(i);
482 FD_ZERO(¤t->files->close_on_exec);
483 if (last_task_used_math == current)
484 last_task_used_math = NULL;
485 current->used_math = 0;
486 }
487
488
489
490
491 int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs)
492 {
493 struct linux_binprm bprm;
494 struct linux_binfmt * fmt;
495 int i;
496 int retval;
497 int sh_bang = 0;
498 int try;
499 #ifdef __alpha__
500 int loader = 0;
501 #endif
502
503 bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
504 for (i=0 ; i<MAX_ARG_PAGES ; i++)
505 bprm.page[i] = 0;
506 retval = open_namei(filename, 0, 0, &bprm.inode, NULL);
507 if (retval)
508 return retval;
509 bprm.filename = filename;
510 bprm.loader = 0;
511 bprm.exec = 0;
512 if ((bprm.argc = count(argv)) < 0)
513 return bprm.argc;
514 if ((bprm.envc = count(envp)) < 0)
515 return bprm.envc;
516
517 restart_interp:
518 if (!S_ISREG(bprm.inode->i_mode)) {
519 retval = -EACCES;
520 goto exec_error2;
521 }
522 if (IS_NOEXEC(bprm.inode)) {
523 retval = -EPERM;
524 goto exec_error2;
525 }
526 if (!bprm.inode->i_sb) {
527 retval = -EACCES;
528 goto exec_error2;
529 }
530 i = bprm.inode->i_mode;
531 if (IS_NOSUID(bprm.inode) && (((i & S_ISUID) && bprm.inode->i_uid != current->
532 euid) || ((i & S_ISGID) && !in_group_p(bprm.inode->i_gid))) && !suser()) {
533 retval = -EPERM;
534 goto exec_error2;
535 }
536
537 if (current->flags & PF_PTRACED) {
538 bprm.e_uid = current->euid;
539 bprm.e_gid = current->egid;
540 } else {
541 bprm.e_uid = (i & S_ISUID) ? bprm.inode->i_uid : current->euid;
542 bprm.e_gid = (i & S_ISGID) ? bprm.inode->i_gid : current->egid;
543 }
544 if ((retval = permission(bprm.inode, MAY_EXEC)) != 0)
545 goto exec_error2;
546 if (!(bprm.inode->i_mode & 0111) && fsuser()) {
547 retval = -EACCES;
548 goto exec_error2;
549 }
550
551 if (bprm.inode->i_writecount > 0) {
552 retval = -ETXTBSY;
553 goto exec_error2;
554 }
555 memset(bprm.buf,0,sizeof(bprm.buf));
556 retval = read_exec(bprm.inode,0,bprm.buf,128,1);
557 if (retval < 0)
558 goto exec_error2;
559 if ((bprm.buf[0] == '#') && (bprm.buf[1] == '!') && (!sh_bang)) {
560
561
562
563
564
565 char *cp, *interp, *i_name, *i_arg;
566
567 iput(bprm.inode);
568 bprm.buf[127] = '\0';
569 if ((cp = strchr(bprm.buf, '\n')) == NULL)
570 cp = bprm.buf+127;
571 *cp = '\0';
572 while (cp > bprm.buf) {
573 cp--;
574 if ((*cp == ' ') || (*cp == '\t'))
575 *cp = '\0';
576 else
577 break;
578 }
579 for (cp = bprm.buf+2; (*cp == ' ') || (*cp == '\t'); cp++);
580 if (!cp || *cp == '\0') {
581 retval = -ENOEXEC;
582 goto exec_error1;
583 }
584 interp = i_name = cp;
585 i_arg = 0;
586 for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) {
587 if (*cp == '/')
588 i_name = cp+1;
589 }
590 while ((*cp == ' ') || (*cp == '\t'))
591 *cp++ = '\0';
592 if (*cp)
593 i_arg = cp;
594
595
596
597
598 if (sh_bang++ == 0) {
599 bprm.p = copy_strings(bprm.envc, envp, bprm.page, bprm.p, 0);
600 bprm.p = copy_strings(--bprm.argc, argv+1, bprm.page, bprm.p, 0);
601 }
602
603
604
605
606
607
608
609
610 bprm.p = copy_strings(1, &bprm.filename, bprm.page, bprm.p, 2);
611 bprm.argc++;
612 if (i_arg) {
613 bprm.p = copy_strings(1, &i_arg, bprm.page, bprm.p, 2);
614 bprm.argc++;
615 }
616 bprm.p = copy_strings(1, &i_name, bprm.page, bprm.p, 2);
617 bprm.argc++;
618 if (!bprm.p) {
619 retval = -E2BIG;
620 goto exec_error1;
621 }
622
623
624
625
626
627 retval = open_namei(interp, 0, 0, &bprm.inode, NULL);
628 if (retval)
629 goto exec_error1;
630 goto restart_interp;
631 }
632 #ifdef __alpha__
633
634 {
635 struct exec * eh = (struct exec *) bprm.buf;
636
637 if (!loader && eh->fh.f_magic == 0x183 &&
638 (eh->fh.f_flags & 0x3000) == 0x3000)
639 {
640 char * dynloader[] = { "/sbin/loader" };
641 iput(bprm.inode);
642 loader = 1;
643 bprm.p = copy_strings(1, dynloader, bprm.page, bprm.p, 2);
644 bprm.loader = bprm.p;
645 retval = open_namei(dynloader[0], 0, 0, &bprm.inode, NULL);
646 if (retval)
647 goto exec_error1;
648 goto restart_interp;
649 }
650 }
651 #endif
652 if (!sh_bang) {
653 bprm.p = copy_strings(1, &bprm.filename, bprm.page, bprm.p, 2);
654 bprm.exec = bprm.p;
655 bprm.p = copy_strings(bprm.envc,envp,bprm.page,bprm.p,0);
656 bprm.p = copy_strings(bprm.argc,argv,bprm.page,bprm.p,0);
657 if (!bprm.p) {
658 retval = -E2BIG;
659 goto exec_error2;
660 }
661 }
662
663 bprm.sh_bang = sh_bang;
664 for (try=0; try<2; try++) {
665 for (fmt = formats ; fmt ; fmt = fmt->next) {
666 int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary;
667 if (!fn)
668 continue;
669 retval = fn(&bprm, regs);
670 if (retval >= 0) {
671 iput(bprm.inode);
672 current->did_exec = 1;
673 return retval;
674 }
675 if (retval != -ENOEXEC)
676 break;
677 }
678 if (retval != -ENOEXEC) {
679 break;
680 #ifdef CONFIG_KERNELD
681 }else{
682 #define printable(c) (((c)=='\t') || ((c)=='\n') || (0x20<=(c) && (c)<=0x7e))
683 char modname[20];
684 if (printable(bprm.buf[0]) &&
685 printable(bprm.buf[1]) &&
686 printable(bprm.buf[2]) &&
687 printable(bprm.buf[3]))
688 break;
689 sprintf(modname, "binfmt-%hd", *(short*)(&bprm.buf));
690 request_module(modname);
691 #endif
692 }
693 }
694 exec_error2:
695 iput(bprm.inode);
696 exec_error1:
697 for (i=0 ; i<MAX_ARG_PAGES ; i++)
698 free_page(bprm.page[i]);
699 return(retval);
700 }