Пример #1
0
/* push argv into user stack, returns argc.
 * note: vm_verify() may override proc's address space, take care.
 * */
int upush_argv(uint *esp, char **tmp){
    uint arglen, argc, tmp_esp;
    int i,r;
    char *str, **uargv;

    argc = 0;
    if (tmp != NULL) {
        for (i=0; (str=tmp[i])!=NULL; i++) {
            arglen += strlen(str)+1;
            argc++;
        }
    }
    arglen += sizeof(char*) * argc;
    // note: vm_verify may modify proc's address space.
    if (vm_verify(*esp-arglen, arglen) < 0){
        syserr(EINVAL);
        return -1;
    }
    // push to ustack finally
    uargv = *esp - arglen;
    for (i=argc-1; i>=0; i--){
        str = tmp[i];
        upush(esp, str, strlen(str)+1);
        uargv[i] = (char *) *esp;
    }
    *esp = uargv;
    // push argv[]
    upush(esp, &uargv, sizeof(uint));
    return argc;
}
Пример #2
0
/*
 * perform the action specified by the current signal.
 * the usual sequence is:
 * if (issig())
 *      psig();
 * */
void psig(){
    uint n, esp, usr;
    struct trap *tf;
    struct sigaction *sa;
    struct jmp_buf jbuf, *ujbuf;
    void *ufunc;

    n = cu->p_cursig;
    if (n==0 || n>NSIG)
        return;
    cu->p_sig &= ~(1<<(n-1));
    sa = &(cu->p_sigact[n-1]);
    // check blocked signal
    cu->p_cursig = 0;
    if (sa->sa_handler != SIG_DFL) {
        tf = cu->p_trap;
        // save registers and the old sa_mask
        usigsav(&jbuf, tf, cu->p_sigmask);
        // store the new sa_mask
        if ((sa->sa_flags & SA_NOMASK)==0) {
            cu->p_sigmask |= sa->sa_mask;
        }
        // push to the user stack, with a "shellcode"
        esp = tf->esp;
        usr = upush(&esp, (char*)&_usigret, 16);
        ujbuf = (struct jmp_buf*)upush(&esp, (char*)&jbuf, sizeof(struct jmp_buf));
        upush(&esp, (char*)&n, sizeof(uint));
        upush(&esp, (char*)&usr, sizeof(uint));
        ufunc = sa->sa_handler;
        if (sa->sa_flags & SA_ONESHOT) {
            sa->sa_handler = NULL;
        }
        _retu((uint)ufunc, esp);
        return;
    }
    // on SIG_DFL
    switch(n){
        // ignored on default
        case SIGCHLD:
        case SIGCONT:
            return;
            // exited on default
        case SIGSEGV:
            printk("seg fault.\n");
        case SIGINT:
        case SIGKILL:
        default:
            do_exit(1);
    }
}
Пример #3
0
/* initialize a new struct vm according to an a.out executable 
 * image.
 * returns NULL on fail.
 * the user stack initialized like this:
 *   |--------------- esp
 *   | argc
 *   |---------------
 *   | argv
 *   |---------------
 *   | argv[0] "..."
 *   | argv[1] "..."
 *   | ...
 *   | argv[n] "..."
 *   --------------- VM_STACK
 * note: ignored envp yet.
 * */
int do_exec(char *path, char **argv){
    struct inode *ip;
    struct buf *bp;
    struct sigaction *sa;
    struct ahead *ah;
    struct page *pg;
    struct vm *vm;
    struct vma *vp;
    struct file *fp;
    uint bn, fd, argc, esp, nr;
    char **tmp;

    ip = namei(path, 0);
    if (ip==NULL) {
        return syserr(ENOENT);
    }
    // read the first block of file to get the a.out header.
    bn = bmap(ip, 0, 0);
    if (bn == 0) {
        syserr(EINVAL);
        goto _badf;
    }
    bp = bread(ip->i_dev, bn);
    ah = (struct ahead*)bp->b_data;
    // check this a.out header.
    if (ah->a_magic != NMAGIC) {
        syserr(EINVAL);
        goto _badf;
    }
    // restore the path and argv temporarily
    tmp = store_argv(path, argv);
    // dettach the previous address space, and initialize a new one
    vm = &cu->p_vm;
    vm_clear(vm);
    vm_renew(vm, ah, ip);
    // push arguments to the end of user stack, which always the same address.
    esp = VM_STACK;
    argc = upush_argv(&esp, tmp);
    if (argc<0)
        panic("exec(): bad mem");
    upush(&esp, &argc, sizeof(uint));
    //
    free_argv(tmp);
    // close all the file descriptors with FD_CLOEXEC
    for (fd=0; fd<NOFILE; fd++) {
        fp = cu->p_ofile[fd];
        if ((fp!=NULL) && (fp->f_fdflag & FD_CLOEXEC)) {
            do_close(fd);
        }
    }
    // clear all sigactions
    for (nr=0; nr<NSIG; nr++){
        sa = &cu->p_sigact[nr];
        sa->sa_handler = SIG_DFL;
        sa->sa_mask = 0;
        sa->sa_flags = 0;
        sa->sa_restorer = NULL;
    }
    // never forget this:
    brelse(bp);
    iput(ip);
    // enter user mode
    _retu(vm->vm_entry, esp);
    return 0;

_badf:
    brelse(bp);
    iput(ip);
    return -1;
}