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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [exec.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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