OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [fs/] [exec.c] - Blame information for rev 199

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 *  linux/fs/exec.c
3
 *
4
 *  Copyright (C) 1991, 1992  Linus Torvalds
5
 */
6
 
7
/*
8
 * #!-checking implemented by tytso.
9
 */
10
/*
11
 * Demand-loading implemented 01.12.91 - no need to read anything but
12
 * the header into memory. The inode of the executable is put into
13
 * "current->executable", and page faults do the actual loading. Clean.
14
 *
15
 * Once more I can proudly say that linux stood up to being changed: it
16
 * was less than 2 hours work to get demand-loading completely implemented.
17
 *
18
 * Demand loading changed July 1993 by Eric Youngdale.   Use mmap instead,
19
 * current->executable is only used by the procfs.  This allows a dispatch
20
 * table to check for several different types  of binary formats.  We keep
21
 * trying until we recognize the file or we run out of supported binary
22
 * formats.
23
 */
24
 
25
/*
26
 * uClinux revisions for NO_MM
27
 * Copyright (C) 1998  Kenneth Albanowski <kjahds@kjahds.com>,
28
 *                     The Silver Hammer Group, Ltd.
29
 */
30
 
31
#include <linux/fs.h>
32
#include <linux/sched.h>
33
#include <linux/kernel.h>
34
#include <linux/mm.h>
35
#include <linux/mman.h>
36
#include <linux/a.out.h>
37
#include <linux/errno.h>
38
#include <linux/signal.h>
39
#include <linux/string.h>
40
#include <linux/stat.h>
41
#include <linux/fcntl.h>
42
#include <linux/ptrace.h>
43
#include <linux/user.h>
44
#include <linux/malloc.h>
45
#include <linux/binfmts.h>
46
#include <linux/personality.h>
47
 
48
#include <asm/system.h>
49
#include <asm/segment.h>
50
#include <asm/pgtable.h>
51
 
52
#include <linux/config.h>
53
#ifdef CONFIG_KERNELD
54
#include <linux/kerneld.h>
55
#endif
56
 
57
asmlinkage int sys_exit(int exit_code);
58
asmlinkage int sys_brk(unsigned long);
59
 
60
/*
61
 * Here are the actual binaries that will be accepted:
62
 * add more with "register_binfmt()" if using modules...
63
 *
64
 * These are defined again for the 'real' modules if you are using a
65
 * module definition for these routines.
66
 */
67
 
68
static struct linux_binfmt *formats = (struct linux_binfmt *) NULL;
69
 
70
void binfmt_setup(void)
71
{
72
#ifdef CONFIG_BINFMT_FLAT
73
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
74
        init_flat_binfmt();
75
 
76
#endif
77
 
78
#ifdef CONFIG_BINFMT_ELF
79
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
80
        init_elf_binfmt();
81
#endif
82
 
83
#ifdef CONFIG_BINFMT_AOUT
84
        init_aout_binfmt();
85
#endif
86
 
87
#ifdef CONFIG_BINFMT_JAVA
88
        init_java_binfmt();
89
#endif
90
        /* This cannot be configured out of the kernel */
91
        init_script_binfmt();
92
}
93
 
94
int register_binfmt(struct linux_binfmt * fmt)
95
{
96
        struct linux_binfmt ** tmp = &formats;
97
 
98
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
99
        if (!fmt)
100
                return -EINVAL;
101
        if (fmt->next)
102
                return -EBUSY;
103
        while (*tmp) {
104
                if (fmt == *tmp)
105
                        return -EBUSY;
106
                tmp = &(*tmp)->next;
107
        }
108
        fmt->next = formats;
109
        formats = fmt;
110
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
111
        return 0;
112
}
113
 
114
#ifdef CONFIG_MODULES
115
int unregister_binfmt(struct linux_binfmt * fmt)
116
{
117
        struct linux_binfmt ** tmp = &formats;
118
 
119
        while (*tmp) {
120
                if (fmt == *tmp) {
121
                        *tmp = fmt->next;
122
                        return 0;
123
                }
124
                tmp = &(*tmp)->next;
125
        }
126
        return -EINVAL;
127
}
128
#endif  /* CONFIG_MODULES */
129
 
130
int open_inode(struct inode * inode, int mode)
131
{
132
        int fd;
133
 
134
        if (!inode->i_op || !inode->i_op->default_file_ops)
135
                return -EINVAL;
136
        fd = get_unused_fd();
137
        if (fd >= 0) {
138
                struct file * f = get_empty_filp();
139
                if (!f) {
140
                        put_unused_fd(fd);
141
                        return -ENFILE;
142
                }
143
                f->f_flags = mode;
144
                f->f_mode = (mode+1) & O_ACCMODE;
145
                f->f_inode = inode;
146
                f->f_pos = 0;
147
                f->f_reada = 0;
148
                f->f_op = inode->i_op->default_file_ops;
149
                if (f->f_op->open) {
150
                        int error = f->f_op->open(inode,f);
151
                        if (error) {
152
                                f->f_count--;
153
                                put_unused_fd(fd);
154
                                return error;
155
                        }
156
                }
157
                current->files->fd[fd] = f;
158
                inode->i_count++;
159
        }
160
        return fd;
161
}
162
 
163
/*
164
 * Note that a shared library must be both readable and executable due to
165
 * security reasons.
166
 *
167
 * Also note that we take the address to load from from the file itself.
168
 */
169
asmlinkage int sys_uselib(const char * library)
170
{
171
        int fd, retval;
172
        struct file * file;
173
        struct linux_binfmt * fmt;
174
 
175
        fd = sys_open(library, 0, 0);
176
        if (fd < 0)
177
                return fd;
178
        file = current->files->fd[fd];
179
        retval = -ENOEXEC;
180
        if (file && file->f_inode && file->f_op && file->f_op->read) {
181
                for (fmt = formats ; fmt ; fmt = fmt->next) {
182
                        int (*fn)(int) = fmt->load_shlib;
183
                        if (!fn)
184
                                continue;
185
                        retval = fn(fd);
186
                        if (retval != -ENOEXEC)
187
                                break;
188
                }
189
        }
190
        sys_close(fd);
191
        return retval;
192
}
193
 
194
/*
195
 * count() counts the number of arguments/envelopes
196
 *
197
 * We also do some limited EFAULT checking: this isn't complete, but
198
 * it does cover most cases. I'll have to do this correctly some day..
199
 */
200
static int count(char ** argv)
201
{
202
        int error, i = 0;
203
        char ** tmp, *p;
204
 
205
        if ((tmp = argv) != NULL) {
206
                error = verify_area(VERIFY_READ, tmp, sizeof(char *));
207
                if (error)
208
                        return error;
209
                while ((p = get_user(tmp++)) != NULL) {
210
                        i++;
211
                        error = verify_area(VERIFY_READ, p, 1);
212
                        if (error)
213
                                return error;
214
                }
215
        }
216
        return i;
217
}
218
 
219
#ifndef NO_MM
220
/*
221
 * 'copy_string()' copies argument/envelope strings from user
222
 * memory to free pages in kernel mem. These are in a format ready
223
 * to be put directly into the top of new user memory.
224
 *
225
 * Modified by TYT, 11/24/91 to add the from_kmem argument, which specifies
226
 * whether the string and the string array are from user or kernel segments:
227
 *
228
 * from_kmem     argv *        argv **
229
 *    0          user space    user space
230
 *    1          kernel space  user space
231
 *    2          kernel space  kernel space
232
 *
233
 * We do this by playing games with the fs segment register.  Since it
234
 * is expensive to load a segment register, we try to avoid calling
235
 * set_fs() unless we absolutely have to.
236
 */
237
unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
238
                unsigned long p, int from_kmem)
239
{
240
        char *tmp, *tmp1, *pag = NULL;
241
        int len, offset = 0;
242
        unsigned long old_fs, new_fs;
243
 
244
        if (!p)
245
                return 0;        /* bullet-proofing */
246
        new_fs = get_ds();
247
        old_fs = get_fs();
248
        if (from_kmem==2)
249
                set_fs(new_fs);
250
        while (argc-- > 0) {
251
                if (from_kmem == 1)
252
                        set_fs(new_fs);
253
                if (!(tmp1 = tmp = get_user(argv+argc)))
254
                        panic("VFS: argc is wrong");
255
                if (from_kmem == 1)
256
                        set_fs(old_fs);
257
                while (get_user(tmp++));
258
                len = tmp - tmp1;
259
                if (p < len) {  /* this shouldn't happen - 128kB */
260
                        set_fs(old_fs);
261
                        return 0;
262
                }
263
                while (len) {
264
                        --p; --tmp; --len;
265
                        if (--offset < 0) {
266
                                offset = p % PAGE_SIZE;
267
                                if (from_kmem==2)
268
                                        set_fs(old_fs);
269
                                if (!(pag = (char *) page[p/PAGE_SIZE]) &&
270
                                    !(pag = (char *) page[p/PAGE_SIZE] =
271
                                      (unsigned long *) get_free_page(GFP_USER)))
272
                                        return 0;
273
                                if (from_kmem==2)
274
                                        set_fs(new_fs);
275
 
276
                        }
277
                        if (len == 0 || offset == 0)
278
                          *(pag + offset) = get_user(tmp);
279
                        else {
280
                          int bytes_to_copy = (len > offset) ? offset : len;
281
                          tmp -= bytes_to_copy;
282
                          p -= bytes_to_copy;
283
                          offset -= bytes_to_copy;
284
                          len -= bytes_to_copy;
285
                          memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
286
                        }
287
                }
288
        }
289
        if (from_kmem==2)
290
                set_fs(old_fs);
291
        return p;
292
}
293
 
294
unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm)
295
{
296
        unsigned long stack_base;
297
        struct vm_area_struct *mpnt;
298
        int i;
299
 
300
        stack_base = STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE;
301
 
302
        p += stack_base;
303
        if (bprm->loader)
304
                bprm->loader += stack_base;
305
        bprm->exec += stack_base;
306
 
307
        mpnt = (struct vm_area_struct *)kmalloc(sizeof(*mpnt), GFP_KERNEL);
308
        if (mpnt) {
309
                mpnt->vm_mm = current->mm;
310
                mpnt->vm_start = PAGE_MASK & (unsigned long) p;
311
                mpnt->vm_end = STACK_TOP;
312
                mpnt->vm_page_prot = PAGE_COPY;
313
                mpnt->vm_flags = VM_STACK_FLAGS;
314
                mpnt->vm_ops = NULL;
315
                mpnt->vm_offset = 0;
316
                mpnt->vm_inode = NULL;
317
                mpnt->vm_pte = 0;
318
                insert_vm_struct(current->mm, mpnt);
319
                current->mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
320
 
321
                for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
322
                        if (bprm->page[i]) {
323
                                current->mm->rss++;
324
                                put_dirty_page(current,bprm->page[i],stack_base);
325
                        }
326
                        stack_base += PAGE_SIZE;
327
                }
328
        } else {
329
                /*
330
                 * This one is tricky. We are already in the new context, so we cannot
331
                 * return with -ENOMEM. So we _have_ to deallocate argument pages here,
332
                 * if there is no VMA, they wont be freed at exit_mmap() -> memory leak.
333
                 *
334
                 * User space then gets a SIGSEGV when it tries to access argument pages.
335
                 */
336
                for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
337
                        if (bprm->page[i]) {
338
                                free_page(bprm->page[i]);
339
                                bprm->page[i] = 0;
340
                        }
341
                }
342
        }
343
 
344
        return p;
345
}
346
#endif /* !NO_MM */
347
 
348
/*
349
 * Read in the complete executable. This is used for "-N" files
350
 * that aren't on a block boundary, and for files on filesystems
351
 * without bmap support.
352
 */
353
int read_exec(struct inode *inode, unsigned long offset,
354
        char * addr, unsigned long count, int to_kmem)
355
{
356
        struct file file;
357
        int result = -ENOEXEC;
358
 
359
        if (!inode->i_op || !inode->i_op->default_file_ops)
360
                goto end_readexec;
361
        file.f_mode = 1;
362
        file.f_flags = 0;
363
        file.f_count = 1;
364
        file.f_inode = inode;
365
        file.f_pos = 0;
366
        file.f_reada = 0;
367
        file.f_op = inode->i_op->default_file_ops;
368
        if (file.f_op->open)
369
                if (file.f_op->open(inode,&file))
370
                        goto end_readexec;
371
        if (!file.f_op || !file.f_op->read)
372
                goto close_readexec;
373
        if (file.f_op->lseek) {
374
                if (file.f_op->lseek(inode,&file,offset,0) != offset)
375
                        goto close_readexec;
376
        } else
377
                file.f_pos = offset;
378
        if (to_kmem) {
379
                unsigned long old_fs = get_fs();
380
                set_fs(get_ds());
381
                result = file.f_op->read(inode, &file, addr, count);
382
                set_fs(old_fs);
383
        } else {
384
                result = verify_area(VERIFY_WRITE, addr, count);
385
                if (result)
386
                        goto close_readexec;
387
                result = file.f_op->read(inode, &file, addr, count);
388
        }
389
close_readexec:
390
        if (file.f_op->release)
391
                file.f_op->release(inode,&file);
392
end_readexec:
393
        return result;
394
}
395
 
396
#ifndef NO_MM
397
static int exec_mmap(void)
398
{
399
        /*
400
         * The clear_page_tables done later on exec does the right thing
401
         * to the page directory when shared, except for graceful abort
402
         */
403
        if (current->mm->count > 1) {
404
                struct mm_struct *old_mm, *mm = kmalloc(sizeof(*mm), GFP_KERNEL);
405
                if (!mm)
406
                        return -ENOMEM;
407
 
408
                *mm = *current->mm;
409
                mm->def_flags = 0;       /* should future lockings be kept? */
410
                mm->count = 1;
411
                mm->mmap = NULL;
412
                mm->mmap_avl = NULL;
413
                mm->total_vm = 0;
414
                mm->rss = 0;
415
 
416
                old_mm = current->mm;
417
                current->mm = mm;
418
                if (new_page_tables(current)) {
419
                        /* The pgd belongs to the parent ... don't free it! */
420
                        mm->pgd = NULL;
421
                        current->mm = old_mm;
422
                        exit_mmap(mm);
423
                        kfree(mm);
424
                        return -ENOMEM;
425
                }
426
 
427
                if ((old_mm != &init_mm) && (!--old_mm->count)) {
428
                        /*
429
                         * all threads exited while we were sleeping, 'old_mm' is held
430
                         * by us exclusively, lets get rid of it:
431
                         */
432
                        exit_mmap(old_mm);
433
                        free_page_tables(old_mm);
434
                        kfree(old_mm);
435
                }
436
 
437
                return 0;
438
        }
439
        flush_cache_mm(current->mm);
440
        exit_mmap(current->mm);
441
        clear_page_tables(current);
442
        flush_tlb_mm(current->mm);
443
 
444
        return 0;
445
}
446
#else /* NO_MM */
447
static int exec_mmap(void)
448
{
449
        if (current->mm->count > 1) {
450
                struct mm_struct *old_mm, *mm = kmalloc(sizeof(*mm), GFP_KERNEL);
451
                if (!mm)
452
                        return -ENOMEM;
453
 
454
                *mm = *current->mm;
455
                mm->def_flags = 0;       /* should future lockings be kept? */
456
                mm->count = 1;
457
                mm->total_vm = 0;
458
                mm->rss = 0;
459
                mm->executable = 0;
460
                mm->tblock.rblock = 0;
461
                mm->tblock.next = 0;
462
 
463
                old_mm = current->mm;
464
                current->mm = mm;
465
 
466
                if ((old_mm != &init_mm) && (!--old_mm->count)) {
467
                        /*
468
                         * all threads exited while we were sleeping, 'old_mm' is held
469
                         * by us exclusively, lets get rid of it:
470
                         */
471
                        exit_mmap(old_mm);
472
                        kfree(old_mm);
473
                }
474
 
475
                return 0;
476
        }
477
        exit_mmap(current->mm);
478
 
479
        return 0;
480
}
481
 
482
#endif /* NO_MM */
483
 
484
/*
485
 * These functions flushes out all traces of the currently running executable
486
 * so that a new one can be started
487
 */
488
 
489
static inline void flush_old_signals(struct signal_struct *sig)
490
{
491
        int i;
492
        struct sigaction * sa = sig->action;
493
 
494
        for (i=32 ; i != 0 ; i--) {
495
                sa->sa_mask = 0;
496
                sa->sa_flags = 0;
497
                if (sa->sa_handler != SIG_IGN)
498
                        sa->sa_handler = NULL;
499
                sa++;
500
        }
501
}
502
 
503
static inline void flush_old_files(struct files_struct * files)
504
{
505
        unsigned long j;
506
 
507
        j = 0;
508
        for (;;) {
509
                unsigned long set, i;
510
 
511
                i = j * __NFDBITS;
512
                if (i >= NR_OPEN)
513
                        break;
514
                set = files->close_on_exec.fds_bits[j];
515
                files->close_on_exec.fds_bits[j] = 0;
516
                j++;
517
                for ( ; set ; i++,set >>= 1) {
518
                        if (set & 1)
519
                                sys_close(i);
520
                }
521
        }
522
}
523
 
524
int flush_old_exec(struct linux_binprm * bprm)
525
{
526
        int i;
527
        int ch;
528
        char * name;
529
 
530
        if (current->euid == current->uid && current->egid == current->gid)
531
                current->dumpable = 1;
532
        name = bprm->filename;
533
        for (i=0; (ch = *(name++)) != '\0';) {
534
                if (ch == '/')
535
                        i = 0;
536
                else
537
                        if (i < 15)
538
                                current->comm[i++] = ch;
539
        }
540
        current->comm[i] = '\0';
541
 
542
        /* Release all of the old mmap stuff. */
543
        if (exec_mmap())
544
                return -ENOMEM;
545
 
546
        flush_thread();
547
 
548
        if (bprm->e_uid != current->euid || bprm->e_gid != current->egid ||
549
            permission(bprm->inode,MAY_READ))
550
                current->dumpable = 0;
551
 
552
        flush_old_signals(current->sig);
553
        flush_old_files(current->files);
554
 
555
        return 0;
556
}
557
 
558
/*
559
 * Fill the binprm structure from the inode.
560
 * Check permissions, then read the first 512 bytes
561
 */
562
int prepare_binprm(struct linux_binprm *bprm)
563
{
564
        int mode;
565
        int retval,id_change;
566
 
567
        mode = bprm->inode->i_mode;
568
        if (!S_ISREG(mode))                     /* must be regular file */
569
                return -EACCES;
570
        if (!(mode & 0111))                     /* with at least _one_ execute bit set */
571
                return -EACCES;
572
        if (IS_NOEXEC(bprm->inode))             /* FS mustn't be mounted noexec */
573
                return -EACCES;
574
        if (!bprm->inode->i_sb)
575
                return -EACCES;
576
        if ((retval = permission(bprm->inode, MAY_EXEC)) != 0)
577
                return retval;
578
        /* better not execute files which are being written to */
579
        if (bprm->inode->i_writecount > 0)
580
                return -ETXTBSY;
581
 
582
        bprm->e_uid = current->euid;
583
        bprm->e_gid = current->egid;
584
        id_change = 0;
585
 
586
        /* Set-uid? */
587
        if (mode & S_ISUID) {
588
                bprm->e_uid = bprm->inode->i_uid;
589
                if (bprm->e_uid != current->euid)
590
                        id_change = 1;
591
        }
592
 
593
        /* Set-gid? */
594
        /*
595
         * If setgid is set but no group execute bit then this
596
         * is a candidate for mandatory locking, not a setgid
597
         * executable.
598
         */
599
        if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
600
                bprm->e_gid = bprm->inode->i_gid;
601
                if (!in_group_p(bprm->e_gid))
602
                        id_change = 1;
603
        }
604
 
605
        if (id_change) {
606
                /* We can't suid-execute if we're sharing parts of the executable */
607
                /* or if we're being traced (or if suid execs are not allowed)    */
608
                /* (current->mm->count > 1 is ok, as we'll get a new mm anyway)   */
609
                if (IS_NOSUID(bprm->inode)
610
                    || (current->flags & PF_PTRACED)
611
                    || (current->fs->count > 1)
612
                    || (current->sig->count > 1)
613
                    || (current->files->count > 1)) {
614
                        if (!suser())
615
                                return -EPERM;
616
                }
617
        }
618
 
619
        memset(bprm->buf,0,sizeof(bprm->buf));
620
        return read_exec(bprm->inode,0,bprm->buf,128,1);
621
}
622
 
623
#ifndef NO_MM
624
void remove_arg_zero(struct linux_binprm *bprm)
625
{
626
        if (bprm->argc) {
627
                unsigned long offset;
628
                char * page;
629
                offset = bprm->p % PAGE_SIZE;
630
                page = (char*)bprm->page[bprm->p/PAGE_SIZE];
631
                while(bprm->p++,*(page+offset++))
632
                        if(offset==PAGE_SIZE){
633
                                offset=0;
634
                                page = (char*)bprm->page[bprm->p/PAGE_SIZE];
635
                        }
636
                bprm->argc--;
637
        }
638
}
639
#endif /* !NO_MM */
640
 
641
/*
642
 * cycle the list of binary formats handler, until one recognizes the image
643
 */
644
int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
645
{
646
        int try,retval=0;
647
        struct linux_binfmt *fmt;
648
#ifdef __alpha__
649
        /* handle /sbin/loader.. */
650
        {
651
            struct exec * eh = (struct exec *) bprm->buf;
652
 
653
            if (!bprm->loader && eh->fh.f_magic == 0x183 &&
654
                (eh->fh.f_flags & 0x3000) == 0x3000)
655
            {
656
                char * dynloader[] = { "/sbin/loader" };
657
                iput(bprm->inode);
658
                bprm->dont_iput = 1;
659
                remove_arg_zero(bprm);
660
                bprm->p = copy_strings(1, dynloader, bprm->page, bprm->p, 2);
661
                bprm->argc++;
662
                bprm->loader = bprm->p;
663
                retval = open_namei(dynloader[0], 0, 0, &bprm->inode, NULL);
664
                if (retval)
665
                        return retval;
666
                bprm->dont_iput = 0;
667
                retval = prepare_binprm(bprm);
668
                if (retval<0)
669
                        return retval;
670
                /* should call search_binary_handler recursively here,
671
                   but it does not matter */
672
            }
673
        }
674
#endif
675
        for (try=0; try<2; try++) {
676
                for (fmt = formats ; fmt ; fmt = fmt->next) {
677
                        int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary;
678
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
679
                        if (!fn)
680
                                continue;
681
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
682
                        retval = fn(bprm, regs);
683
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
684
                        if (retval >= 0) {
685
                                if(!bprm->dont_iput)
686
                                        iput(bprm->inode);
687
                                bprm->dont_iput=1;
688
                                current->did_exec = 1;
689
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
690
                                return retval;
691
                        }
692
                        if (retval != -ENOEXEC)
693
                                break;
694
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
695
                        if (bprm->dont_iput) /* We don't have the inode anymore*/
696
                                return retval;
697
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
698
                }
699
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
700
                if (retval != -ENOEXEC) {
701
                        break;
702
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
703
#ifdef CONFIG_KERNELD
704
                }else{
705
#define printable(c) (((c)=='\t') || ((c)=='\n') || (0x20<=(c) && (c)<=0x7e))
706
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
707
                        char modname[20];
708
                        if (printable(bprm->buf[0]) &&
709
                            printable(bprm->buf[1]) &&
710
                            printable(bprm->buf[2]) &&
711
                            printable(bprm->buf[3]))
712
                                break; /* -ENOEXEC */
713
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
714
                        sprintf(modname, "binfmt-%hd", *(short*)(&bprm->buf));
715
                        request_module(modname);
716
#endif
717
                }
718
        }
719
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
720
        return retval;
721
}
722
 
723
 
724
/*
725
 * sys_execve() executes a new program.
726
 */
727
int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs)
728
{
729
        struct linux_binprm bprm;
730
        int retval;
731
#ifndef NO_MM
732
        int i;
733
#endif /* !NO_MM */
734
 
735
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
736
 
737
#ifndef NO_MM
738
        bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
739
        for (i=0 ; i<MAX_ARG_PAGES ; i++)        /* clear page-table */
740
                bprm.page[i] = 0;
741
#endif /* !NO_MM */
742
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
743
        retval = open_namei(filename, 0, 0, &bprm.inode, NULL);
744
        if (retval)
745
                return retval;
746
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
747
        bprm.filename = filename;
748
        bprm.sh_bang = 0;
749
        bprm.loader = 0;
750
        bprm.exec = 0;
751
        bprm.dont_iput = 0;
752
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
753
        if ((bprm.argc = count(argv)) < 0)
754
                return bprm.argc;
755
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
756
        if ((bprm.envc = count(envp)) < 0)
757
                return bprm.envc;
758
 
759
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
760
        retval = prepare_binprm(&bprm);
761
 
762
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
763
#ifndef NO_MM
764
        if(retval>=0) {
765
                bprm.p = copy_strings(1, &bprm.filename, bprm.page, bprm.p, 2);
766
                bprm.exec = bprm.p;
767
                bprm.p = copy_strings(bprm.envc,envp,bprm.page,bprm.p,0);
768
                bprm.p = copy_strings(bprm.argc,argv,bprm.page,bprm.p,0);
769
                if (!bprm.p)
770
                        retval = -E2BIG;
771
        }
772
#else /* NO_MM */
773
        bprm.envp = envp;
774
        bprm.argv = argv;
775
#endif /* NO_MM */
776
 
777
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
778
        if(retval>=0)
779
                retval = search_binary_handler(&bprm,regs);
780
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
781
        if(retval>=0) {
782
#ifdef NO_MM
783
                /* Wake up parent that vforked me */
784
                wake_up(&current->p_opptr->mm->vforkwait);
785
#endif /* NO_MM */
786
                /* execve success */
787
                return retval;
788
        }
789
 
790
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
791
        /* Something went wrong, return the inode and free the argument pages*/
792
        if(!bprm.dont_iput)
793
                iput(bprm.inode);
794
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
795
#ifndef NO_MM
796
        for (i=0 ; i<MAX_ARG_PAGES ; i++)
797
                free_page(bprm.page[i]);
798
#endif /* !NO_MM */
799
printk("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
800
        return(retval);
801
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.