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