예제 #1
0
파일: waitpid06.c 프로젝트: CSU-GH/okl4_3.0
/*
 * do_child_1()
 */
void
do_child_1(void)
{
	int kid_count, fork_kid_pid[MAXKIDS];
	int ret_val;
	int i, j, k, found;
	int group1, group2;
	int wait_kid_pid[MAXKIDS], status;

	setup_sigint();

	group1 = getpgrp();
	for (kid_count = 0; kid_count < MAXKIDS; kid_count++) {
		if (kid_count == (MAXKIDS / 2)) {
			group2 = setpgrp();
		}
		intintr = 0;
		ret_val = FORK_OR_VFORK();
		if (ret_val == 0) {	/* child */
#ifdef UCLINUX
			if (self_exec(argv0, "n", 2) < 0) {
				tst_resm(TFAIL, "Fork kid %d failed. "
					 "errno = %d", kid_count,
					 errno);
				exit(ret_val);
			}
#else
			do_exit();
#endif
			/*NOTREACHED*/
		} else if (ret_val < 0) {
			tst_resm(TFAIL, "Fork kid %d failed. "
				 "errno = %d", kid_count,
				 errno);
			exit(ret_val);
		}

		/* parent */
		fork_kid_pid[kid_count] = ret_val;
	}

#ifdef UCLINUX
	/* Give the kids a chance to setup SIGINT again, since this is
	 * cleared by exec().
	 */
	sleep(3);
#endif

	/* Now send all the kids a SIGINT to tell them to
	 * proceed
	 */
	for (i = 0; i < MAXKIDS; i++) {
		if (kill(fork_kid_pid[i], SIGINT) < 0) {
			tst_resm(TFAIL, "Kill of child %d "
				 "failed, errno = %d", i, errno);
			exit(-1);
		}
	}

	/*
	 * Wait till all kids have terminated.  Stash away their
	 * pid's in an array.
	 */
	kid_count = 0;
	errno = 0;
	while (((ret_val = waitpid(-1, &status, 0)) != -1) ||
	       (errno == EINTR)) {
		if (ret_val == -1) {
			continue;
		}

		if (!WIFEXITED(status)) {
			tst_resm(TFAIL, "Child %d did not exit "
				 "normally", ret_val);
			flag = FAILED;
			printf("status: %d\n", status);
		} else {
			if (WEXITSTATUS(status) != 3) {
				tst_resm(TFAIL, "Child %d"
					 "exited with wrong "
					 "status", ret_val);
				tst_resm(TFAIL, "Expected 3 "
					 "got %d ",
					 WEXITSTATUS(status));
				flag = FAILED;
			}
		}
		wait_kid_pid[kid_count++] = ret_val;
	}

	/*
	 * Check that for every entry in the fork_kid_pid array,
	 * there is a matching pid in the wait_kid_pid array. If
	 * not, it's an error.
	 */
	for (i = 0; i < kid_count; i++) {
		found = 0;
		for (j = 0; j < MAXKIDS; j++) {
			if (fork_kid_pid[j] == wait_kid_pid[i]){
				found = 1;
				break;
			}
		}

		if (!found) {
			tst_resm(TFAIL, "Did not find a "
				 "wait_kid_pid for the "
				 "fork_kid_pid of %d",
				 fork_kid_pid[j]);
			for (k = 0; k < MAXKIDS; k++) {
				tst_resm(TFAIL,
					 "fork_kid_pid[%d] = "
					 "%d", k,
					 fork_kid_pid[k]);
			}
			for (k = 0; k < kid_count; k++) {
				tst_resm(TFAIL,
					 "wait_kid_pid[%d] = "
					 "%d", k,
					 wait_kid_pid[k]);
			}
			flag = FAILED;
		}
	}

	if (flag) {
		exit(1);
	} else {
		exit(0);
	}
}
예제 #2
0
/**
  * Execute a command.
  * @var argc The number of arguments
  * @var argv The array of arguments
  * @var should_background Whether or not to run it as a background process
  */
int execute_cmd(int argc, char** argv, int* should_background) {
    if (argv[0] && strcmp(argv[0], "exit") == 0) {
        do_exit();
    }

    pid_t pid  = fork();

    if (pid < 0) {
        // Uh oh, an error with forking
        fprintf(stderr, "Fork Failed");
        return 1;
    } else if (pid == 0) { // Child process
        char* stdin_fname = NULL;
        char* stdout_fname = NULL;
        char* stderr_fname = NULL;
        int bad_syntax = 0;

        // Checking for stdin/stdout redirection
        for (int i = 0; i < argc; i++) {
            char* arg = argv[i];
            // redirection check
            if (is_redirection(arg)) {
                char* next_arg = argv[i+1];

                if (next_arg == NULL || is_redirection(next_arg) || strcmp(next_arg, "&") == 0) {
                    bad_syntax = 1;
                    break;
                }
                
                if ((i + 2) < argc) {
                    char* next_next_arg = argv[i+2];
                    if (next_next_arg != NULL) {
                        if (!is_redirection(next_next_arg) && strcmp(next_next_arg, "&") != 0) {
                            bad_syntax = 1;
                            break;
                        }
                    }
                }

                if (strcmp(arg, ">") == 0) {
                    stdout_fname = argv[i+1];
                } else if (strcmp(arg, "<") == 0) {
                    stdin_fname = argv[i+1];
                } else if (strcmp(arg, "2>") == 0) {
                    stderr_fname = argv[i+1];
                }

                argv[i] = NULL;
            }
        }

        if (bad_syntax == 1) {
            printf("Error: Invalid syntax.\n");
            exit(3);
        }

        // Redirect stdout
        if (stdout_fname != NULL) {
            if (!is_redirection(stdout_fname)
                    && !(strcmp(stdout_fname, "&") == 0)) {

                FILE* stdout_file;
                stdout_file= freopen(stdout_fname, "w", stdout);
                if (stdout_file == NULL) {
                    printf("Error: Unable to open redirection file.\n");
                    exit(errno);
                }
            } else {
                printf("Error: Invalid syntax.\n");
                exit(3);
            }
        }

        // stdin redirection
        if (stdin_fname != NULL) {
            if (!is_redirection(stdin_fname)
                    && !(strcmp(stdin_fname, "&") == 0)) {

                FILE* stdin_file;
                stdin_file = freopen(stdin_fname, "r", stdin);

                if (stdin_file == NULL) {
                    printf("Error: Unable to open redirection file.\n");
                    exit(errno);
                }
            } else {
                printf("Error: Invalid syntax.\n");
                exit(3);
            }
        }

        // stderr redirection
        if (stderr_fname != NULL) {
            if (!is_redirection(stderr_fname)
                    && !(strcmp(stderr_fname, "&") == 0)) {

                FILE* stderr_file;
                stderr_file = freopen(stderr_fname, "w", stderr);
                if (stderr_file == NULL) {
                    printf("Error: Unable to open redirection file.\n");
                    exit(errno);
                }
            } else {
                printf("Error: Invalid syntax.\n");
                exit(3);
            }
        }

        execvp(argv[0], argv);

        if (errno == ENOENT) {
            printf("Error: Command not found.\n");
        } else if (errno == EACCES) {
            printf("Error: Permission denied.\n");
        } else {
            printf("Error: Exit code %d\n", errno);
        }
        exit(-1);
    } else {
        if (*should_background == 0) {
            // Wait for the child
            waitpid(pid, NULL, 0);
        }
    }

    return 0;
}
예제 #3
0
/*
 * Create a kernel thread
 */
ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *))
{
	do_exit(fn(arg));
}
예제 #4
0
/*
 * Make pt_pfn a new 'level' page table frame and hook it into the page
 * table at offset in previous level MFN (pref_l_mfn). pt_pfn is a guest
 * PFN.
 */
static void new_pt_frame(unsigned long *pt_pfn, unsigned long prev_l_mfn, 
                         unsigned long offset, unsigned long level)
{   
    pgentry_t *tab = (pgentry_t *)start_info.pt_base;
    unsigned long pt_page = (unsigned long)pfn_to_virt(*pt_pfn); 
    pgentry_t prot_e, prot_t;
    mmu_update_t mmu_updates[1];
    int rc;
    
    prot_e = prot_t = 0;
    DEBUG("Allocating new L%d pt frame for pfn=%lx, "
          "prev_l_mfn=%lx, offset=%lx", 
          level, *pt_pfn, prev_l_mfn, offset);

    /* We need to clear the page, otherwise we might fail to map it
       as a page table page */
    memset((void*) pt_page, 0, PAGE_SIZE);  
 
    switch ( level )
    {
    case L1_FRAME:
        prot_e = L1_PROT;
        prot_t = L2_PROT;
        break;
    case L2_FRAME:
        prot_e = L2_PROT;
        prot_t = L3_PROT;
        break;
    case L3_FRAME:
        prot_e = L3_PROT;
        prot_t = L4_PROT;
        break;
    default:
        printk("new_pt_frame() called with invalid level number %d\n", level);
        do_exit();
        break;
    }

    /* Make PFN a page table page */
    tab = pte_to_virt(tab[l4_table_offset(pt_page)]);
    tab = pte_to_virt(tab[l3_table_offset(pt_page)]);

    mmu_updates[0].ptr = (tab[l2_table_offset(pt_page)] & PAGE_MASK) + 
        sizeof(pgentry_t) * l1_table_offset(pt_page);
    mmu_updates[0].val = (pgentry_t)pfn_to_mfn(*pt_pfn) << PAGE_SHIFT | 
        (prot_e & ~_PAGE_RW);
    
    if ( (rc = HYPERVISOR_mmu_update(mmu_updates, 1, NULL, DOMID_SELF)) < 0 )
    {
        printk("ERROR: PTE for new page table page could not be updated\n");
        printk("       mmu_update failed with rc=%d\n", rc);
        do_exit();
    }

    /* Hook the new page table page into the hierarchy */
    mmu_updates[0].ptr =
        ((pgentry_t)prev_l_mfn << PAGE_SHIFT) + sizeof(pgentry_t) * offset;
    mmu_updates[0].val = (pgentry_t)pfn_to_mfn(*pt_pfn) << PAGE_SHIFT | prot_t;

    if ( (rc = HYPERVISOR_mmu_update(mmu_updates, 1, NULL, DOMID_SELF)) < 0 ) 
    {
        printk("ERROR: mmu_update failed with rc=%d\n", rc);
        do_exit();
    }

    *pt_pfn += 1;
}
예제 #5
0
// STATUS 1 = End of line, execute command
// STATUS 2 = Background the process
char* get_arg(int* status, int* is_eof) {
    char* buffer = (char*) calloc(10, 1);
    char c;
    char next;
    int bufsz = 0;
    int count = 0;
    int do_loop = 1;
    c = getchar();

    // Read through any whitespace
    while (is_white_space(c) && c != '\n') {
        c = getchar();
    }

    // Check for redirection
    if (c == '>' || c == '<') {
        buffer[0] = c;
        count = 1;
        do_loop = 0;
    } else if (c == '2') {
        next = getchar();
        if (next == '>') {
            do_loop = 0;
        } 
        buffer[0] = c;
        count = 1;
        if (!is_white_space(next)) {
            buffer[1] = next;
            count = 2;
        }
        c = next;
    }

    // Parse the argument
    while (c != EOF && !is_white_space(c) && do_loop) {
        if  (c == '\\') {
            next = getchar();
            if (next == EOF) {
                *is_eof = 1;
            }
            // Handle escape cases
            if (next == 't') {
                c = '\t';
            } else if (next == '\\') {
                c = '\\';
            } else if (next == ' ') {
                c = ' ';
            } else if (next == '&') {
                c = '&';
            } else {
                printf("Error: Unrecognized escape sequence.\n");
                if (next == '\n') {
                    *status = 1;
                } else {
                    empty_input(is_eof);
                }
                free(buffer);
                return NULL;
            }
        } else if (c == '&') {
            *status = 2;
            c = getchar();

            while (is_white_space(c) && c != '\n' && c != EOF) {
                c = getchar();
            }

            if (c != '\n' && c != EOF) {
                printf("Error: Invalid syntax.\n");
                empty_input(is_eof);
                free(buffer);
                return NULL;
            }

            if (c == EOF) {
                *is_eof = 1;
            }

            break;
        }

        if (count + 1 > bufsz) {
            buffer = realloc(buffer, bufsz + 10);
            if (buffer == NULL) {
                perror("Error resizing buffer for arg.");
                do_exit();
            }
            bufsz += 10;
        }
        buffer[count] = c;
        count++;
        c = getchar();
    }


    // Check to see if we've read in the full line
    if ((c == '\n' || c == EOF) && (*status != 2)) {
        *status= 1;
    }

    if (c == EOF) {
        *is_eof = 1;
    }

    // Save the argument to memory
    char* ret = (char*) calloc(count + 1, 1);
    strncpy(ret, buffer, count);
    free(buffer);

    return ret;
}
예제 #6
0
static int syscall_dispatch(uint32_t sysnum, uint32_t args, regs_t *regs)
{
        switch (sysnum) {
                case SYS_waitpid:
                        return sys_waitpid((waitpid_args_t *)args);

                case SYS_exit:
                        do_exit((int)args);
                        panic("exit failed!\n");
                        return 0;

                case SYS_thr_exit:
                        kthread_exit((void *)args);
                        panic("thr_exit failed!\n");
                        return 0;

                case SYS_thr_yield:
                        sched_make_runnable(curthr);
                        sched_switch();
                        return 0;

                case SYS_fork:
                        return sys_fork(regs);

                case SYS_getpid:
                        return curproc->p_pid;

                case SYS_sync:
                        sys_sync();
                        return 0;

#ifdef __MOUNTING__
                case SYS_mount:
                        return sys_mount((mount_args_t *) args);

                case SYS_umount:
                        return sys_umount((argstr_t *) args);
#endif

                case SYS_mmap:
                        return (int) sys_mmap((mmap_args_t *) args);

                case SYS_munmap:
                        return sys_munmap((munmap_args_t *) args);

                case SYS_open:
                        return sys_open((open_args_t *) args);

                case SYS_close:
                        return sys_close((int)args);

                case SYS_read:
                        return sys_read((read_args_t *)args);

                case SYS_write:
                        return sys_write((write_args_t *)args);

                case SYS_dup:
                        return sys_dup((int)args);

                case SYS_dup2:
                        return sys_dup2((dup2_args_t *)args);

                case SYS_mkdir:
                        return sys_mkdir((mkdir_args_t *)args);

                case SYS_rmdir:
                        return sys_rmdir((argstr_t *)args);

                case SYS_unlink:
                        return sys_unlink((argstr_t *)args);

                case SYS_link:
                        return sys_link((link_args_t *)args);

                case SYS_rename:
                        return sys_rename((rename_args_t *)args);

                case SYS_chdir:
                        return sys_chdir((argstr_t *)args);

                case SYS_getdents:
                        return sys_getdents((getdents_args_t *)args);

                case SYS_brk:
                        return (int) sys_brk((void *)args);

                case SYS_lseek:
                        return sys_lseek((lseek_args_t *)args);

                case SYS_halt:
                        sys_halt();
                        return -1;

                case SYS_set_errno:
                        curthr->kt_errno = (int)args;
                        return 0;

                case SYS_errno:
                        return curthr->kt_errno;

                case SYS_execve:
                        return sys_execve((execve_args_t *)args, regs);

                case SYS_stat:
                        return sys_stat((stat_args_t *)args);

                case SYS_pipe:
                        return sys_pipe((int *)args);

                case SYS_uname:
                        return sys_uname((struct utsname *)args);

                case SYS_debug:
                        return sys_debug((argstr_t *)args);
                case SYS_kshell:
                        return sys_kshell((int)args);
                default:
                        dbg(DBG_ERROR, "ERROR: unknown system call: %d (args: %#08x)\n", sysnum, args);
                        curthr->kt_errno = ENOSYS;
                        return -1;
        }
}
예제 #7
0
static void
trap_dispatch(struct trapframe *tf) {
    char c;

    int ret=0;

    switch (tf->tf_trapno) {
    case T_PGFLT:  //page fault
        if ((ret = pgfault_handler(tf)) != 0) {
            print_trapframe(tf);
            if (current == NULL) {
                panic("handle pgfault failed. ret=%d\n", ret);
            }
            else {
                if (trap_in_kernel(tf)) {
                    panic("handle pgfault failed in kernel mode. ret=%d\n", ret);
                }
                cprintf("killed by kernel.\n");
                cprintf("current %s.\n",current->name);
                panic("handle user mode pgfault failed. ret=%d\n", ret);
                do_exit(-E_KILLED);
            }
        }
        break;
    case T_SYSCALL:
        syscall();
        break;
    case IRQ_OFFSET + IRQ_TIMER:
#if 0
    LAB3 : If some page replacement algorithm(such as CLOCK PRA) need tick to change the priority of pages,
    then you can add code here.
#endif
        /* LAB1 YOUR CODE : STEP 3 */
        /* handle the timer interrupt */
        /* (1) After a timer interrupt, you should record this event using a global variable (increase it), such as ticks in kern/driver/clock.c
         * (2) Every TICK_NUM cycle, you can print some info using a funciton, such as print_ticks().
         * (3) Too Simple? Yes, I think so!
         */
        /* LAB5 YOUR CODE */
        /* you should upate you lab1 code (just add ONE or TWO lines of code):
         *    Every TICK_NUM cycle, you should set current process's current->need_resched = 1
         */

        break;
    case IRQ_OFFSET + IRQ_COM1:
        c = cons_getc();
        cprintf("serial [%03d] %c\n", c, c);
        break;
    case IRQ_OFFSET + IRQ_KBD:
        c = cons_getc();
        cprintf("kbd [%03d] %c\n", c, c);
        break;
    //LAB1 CHALLENGE 1 : YOUR CODE you should modify below codes.
    case T_SWITCH_TOU:
    case T_SWITCH_TOK:
        panic("T_SWITCH_** ??\n");
        break;
    case IRQ_OFFSET + IRQ_IDE1:
    case IRQ_OFFSET + IRQ_IDE2:
        /* do nothing */
        break;
    default:
        print_trapframe(tf);
        if (current != NULL) {
            cprintf("unhandled trap.\n");
            do_exit(-E_KILLED);
        }
        // in kernel, it must be a mistake
        panic("unexpected trap in kernel.\n");

    }
}
예제 #8
0
파일: syscall.c 프로젝트: spinlock/ucore
static uint32_t
sys_exit(uint32_t arg[]) {
    int error_code = (int)arg[0];
    return do_exit(error_code);
}
예제 #9
0
파일: trap.c 프로젝트: gjc13/ucore_os_lab
static void
trap_dispatch(struct trapframe *tf) {
    char c;

    int ret=0;

    switch (tf->tf_trapno) {
    case T_PGFLT:  //page fault
        if ((ret = pgfault_handler(tf)) != 0) {
            print_trapframe(tf);
            if (current == NULL) {
                panic("handle pgfault failed. ret=%d\n", ret);
            }
            else {
                if (trap_in_kernel(tf)) {
                    panic("handle pgfault failed in kernel mode. ret=%d\n", ret);
                }
                cprintf("killed by kernel.\n");
                panic("handle user mode pgfault failed. ret=%d\n", ret); 
                do_exit(-E_KILLED);
            }
        }
        break;
    case T_SYSCALL:
        syscall();
        break;
    case IRQ_OFFSET + IRQ_TIMER:
        //LAB3_X 2013011509
        //Call swap manager timer handler here
        if (check_mm_struct != NULL) {
            assert(swap_tick_event(check_mm_struct) == 0);
        }
        ticks++;
        run_timer_list();
#if 0
    LAB3 : If some page replacement algorithm(such as CLOCK PRA) need tick to change the priority of pages,
    then you can add code here. 
#endif
        /* LAB1 YOUR CODE : STEP 3 */
        /* handle the timer interrupt */
        /* (1) After a timer interrupt, you should record this event using a global variable (increase it), such as ticks in kern/driver/clock.c
         * (2) Every TICK_NUM cycle, you can print some info using a funciton, such as print_ticks().
         * (3) Too Simple? Yes, I think so!
         */
        /* you should upate you lab1 code (just add ONE or TWO lines of code):
         *    Every TICK_NUM cycle, you should set current process's current->need_resched = 1
         */
        /* LAB6 YOUR CODE */
        /* you should upate you lab5 code
         * IMPORTANT FUNCTIONS:
	     * sched_class_proc_tick
         */         
        /* LAB7 YOUR CODE */
        /* you should upate you lab6 code
         * IMPORTANT FUNCTIONS:
	     * run_timer_list
         */
        break;
    case IRQ_OFFSET + IRQ_COM1:
    case IRQ_OFFSET + IRQ_KBD:
        // There are user level shell in LAB8, so we need change COM/KBD interrupt processing.
        c = cons_getc();
        {
          extern void dev_stdin_write(char c);
          dev_stdin_write(c);
        }
        break;
    //LAB1 CHALLENGE 1 : YOUR CODE you should modify below codes.
    case T_SWITCH_TOU:
    case T_SWITCH_TOK:
        panic("T_SWITCH_** ??\n");
        break;
    case IRQ_OFFSET + IRQ_IDE1:
    case IRQ_OFFSET + IRQ_IDE2:
        /* do nothing */
        break;
    default:
        print_trapframe(tf);
        if (current != NULL) {
            cprintf("unhandled trap.\n");
            do_exit(-E_KILLED);
        }
        // in kernel, it must be a mistake
        panic("unexpected trap in kernel.\n");

    }
}
예제 #10
0
파일: main.c 프로젝트: BackupGGCode/lyos
/**
 * <Ring 1> The main loop of TASK MM.
 * 
 *****************************************************************************/
PUBLIC void task_mm()
{
	init_mm();

	while (1) {
		send_recv(RECEIVE, ANY, &mm_msg);
		int src = mm_msg.source;
		int reply = 1;

		int msgtype = mm_msg.type;

		switch (msgtype) {
		case FORK:
			mm_msg.RETVAL = do_fork();
			break;
		case EXIT:
			do_exit(mm_msg.STATUS);
			reply = 0;
			break;
		case EXEC:
			mm_msg.RETVAL = do_exec();
			break;
		case WAIT:
			do_wait();
			reply = 0;
			break;
		case KILL:
			mm_msg.RETVAL = do_kill();
			break; 
		case RAISE:
			mm_msg.RETVAL = do_raise();
			break;
		case BRK:
			mm_msg.RETVAL = do_brk();
			break;
		case ACCT:
			mm_msg.RETVAL = do_acct();
			break;
		case GETUID:
			mm_msg.RETVAL = do_getuid();
			break;
		case SETUID:
            mm_msg.RETVAL = do_setuid();
			break;
		case GETGID:
			mm_msg.RETVAL = do_getgid();
			break;
		case SETGID:
			mm_msg.RETVAL = do_setgid();
			break;
		case GETEUID:
			mm_msg.RETVAL = do_geteuid();
			break;
		case GETEGID:
			mm_msg.RETVAL = do_getegid();
			break;
		case SIGACTION:
			mm_msg.RETVAL = do_sigaction();
			break;
		case ALARM:
			mm_msg.RETVAL = do_alarm();
			break;
		default:
			dump_msg("MM::unknown msg", &mm_msg);
			assert(0);
			break;
		}

		if (reply) {
			mm_msg.type = SYSCALL_RET;
			send_recv(SEND, src, &mm_msg);
		}
	}
}
예제 #11
0
/*
 * This is the mechanism for creating a new kernel thread.
 *
 * NOTE! Only a kernel-only process(ie the swapper or direct descendants
 * who haven't done an "execve()") should use this: it will work within
 * a system call from a "real" process, but the process memory space will
 * not be free'd until both the parent and the child have exited.
 */
static void kernel_thread_helper(void *nouse, int (*fn)(void *), void *arg)
{
	fn(arg);
	do_exit(-1);
}
예제 #12
0
/*
 * If we ever come here the user sp is bad.  Zap the process right away.
 * Due to the bad stack signaling wouldn't work.
 */
asmlinkage void bad_stack(void)
{
	do_exit(SIGSEGV);
}
예제 #13
0
static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
				   struct kvm_s390_interrupt_info *inti)
{
	const unsigned short table[] = { 2, 4, 4, 6 };
	int rc, exception = 0;

	switch (inti->type) {
	case KVM_S390_INT_EMERGENCY:
		VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp emerg");
		vcpu->stat.deliver_emergency_signal++;
		rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x1201);
		if (rc == -EFAULT)
			exception = 1;

		rc = put_guest_u16(vcpu, __LC_CPU_ADDRESS, inti->emerg.code);
		if (rc == -EFAULT)
			exception = 1;

		rc = copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
			 &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
		if (rc == -EFAULT)
			exception = 1;

		rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
			__LC_EXT_NEW_PSW, sizeof(psw_t));
		if (rc == -EFAULT)
			exception = 1;
		break;

	case KVM_S390_INT_SERVICE:
		VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x",
			   inti->ext.ext_params);
		vcpu->stat.deliver_service_signal++;
		rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x2401);
		if (rc == -EFAULT)
			exception = 1;

		rc = copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
			 &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
		if (rc == -EFAULT)
			exception = 1;

		rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
			__LC_EXT_NEW_PSW, sizeof(psw_t));
		if (rc == -EFAULT)
			exception = 1;

		rc = put_guest_u32(vcpu, __LC_EXT_PARAMS, inti->ext.ext_params);
		if (rc == -EFAULT)
			exception = 1;
		break;

	case KVM_S390_INT_VIRTIO:
		VCPU_EVENT(vcpu, 4, "interrupt: virtio parm:%x,parm64:%llx",
			   inti->ext.ext_params, inti->ext.ext_params2);
		vcpu->stat.deliver_virtio_interrupt++;
		rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x2603);
		if (rc == -EFAULT)
			exception = 1;

		rc = put_guest_u16(vcpu, __LC_CPU_ADDRESS, 0x0d00);
		if (rc == -EFAULT)
			exception = 1;

		rc = copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
			 &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
		if (rc == -EFAULT)
			exception = 1;

		rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
			__LC_EXT_NEW_PSW, sizeof(psw_t));
		if (rc == -EFAULT)
			exception = 1;

		rc = put_guest_u32(vcpu, __LC_EXT_PARAMS, inti->ext.ext_params);
		if (rc == -EFAULT)
			exception = 1;

		rc = put_guest_u64(vcpu, __LC_EXT_PARAMS2,
				   inti->ext.ext_params2);
		if (rc == -EFAULT)
			exception = 1;
		break;

	case KVM_S390_SIGP_STOP:
		VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu stop");
		vcpu->stat.deliver_stop_signal++;
		__set_intercept_indicator(vcpu, inti);
		break;

	case KVM_S390_SIGP_SET_PREFIX:
		VCPU_EVENT(vcpu, 4, "interrupt: set prefix to %x",
			   inti->prefix.address);
		vcpu->stat.deliver_prefix_signal++;
		vcpu->arch.sie_block->prefix = inti->prefix.address;
		vcpu->arch.sie_block->ihcpu = 0xffff;
		break;

	case KVM_S390_RESTART:
		VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu restart");
		vcpu->stat.deliver_restart_signal++;
		rc = copy_to_guest(vcpu, offsetof(struct _lowcore,
		  restart_old_psw), &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
		if (rc == -EFAULT)
			exception = 1;

		rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
			offsetof(struct _lowcore, restart_psw), sizeof(psw_t));
		if (rc == -EFAULT)
			exception = 1;
		break;

	case KVM_S390_PROGRAM_INT:
		VCPU_EVENT(vcpu, 4, "interrupt: pgm check code:%x, ilc:%x",
			   inti->pgm.code,
			   table[vcpu->arch.sie_block->ipa >> 14]);
		vcpu->stat.deliver_program_int++;
		rc = put_guest_u16(vcpu, __LC_PGM_INT_CODE, inti->pgm.code);
		if (rc == -EFAULT)
			exception = 1;

		rc = put_guest_u16(vcpu, __LC_PGM_ILC,
			table[vcpu->arch.sie_block->ipa >> 14]);
		if (rc == -EFAULT)
			exception = 1;

		rc = copy_to_guest(vcpu, __LC_PGM_OLD_PSW,
			 &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
		if (rc == -EFAULT)
			exception = 1;

		rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
			__LC_PGM_NEW_PSW, sizeof(psw_t));
		if (rc == -EFAULT)
			exception = 1;
		break;

	default:
		BUG();
	}
	if (exception) {
		printk("kvm: The guest lowcore is not mapped during interrupt "
			"delivery, killing userspace\n");
		do_exit(SIGKILL);
	}
}
예제 #14
0
파일: waitpid06.c 프로젝트: CSU-GH/okl4_3.0
/*
 * do_child_2_uclinux()
 *	sets up sigint handler again, then calls the normal child 2 function
 */
void
do_child_2_uclinux(void)
{
	setup_sigint();
	do_exit();
}
예제 #15
0
/*
 * This routine handles page faults.  It determines the address,
 * and the problem, and then passes it off to one of the appropriate
 * routines.
 *
 * error_code:
 *   04       Protection           ->  Write-Protection  (suprression)
 *   10       Segment translation  ->  Not present       (nullification)
 *   11       Page translation     ->  Not present       (nullification)
 *   3b       Region third trans.  ->  Not present       (nullification)
 */
extern inline void
do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection)
{
        struct task_struct *tsk;
        struct mm_struct *mm;
        struct vm_area_struct * vma;
        unsigned long address;
	int user_address;
	const struct exception_table_entry *fixup;
	int si_code = SEGV_MAPERR;

        tsk = current;
        mm = tsk->mm;
	
	/* 
         * Check for low-address protection.  This needs to be treated
	 * as a special case because the translation exception code 
	 * field is not guaranteed to contain valid data in this case.
	 */
	if (is_protection && !(S390_lowcore.trans_exc_code & 4)) {

		/* Low-address protection hit in kernel mode means 
		   NULL pointer write access in kernel mode.  */
 		if (!(regs->psw.mask & PSW_MASK_PSTATE)) {
			address = 0;
			user_address = 0;
			goto no_context;
		}

		/* Low-address protection hit in user mode 'cannot happen'.  */
		die ("Low-address protection", regs, error_code);
        	do_exit(SIGKILL);
	}

        /* 
         * get the failing address 
         * more specific the segment and page table portion of 
         * the address 
         */
        address = S390_lowcore.trans_exc_code & __FAIL_ADDR_MASK;
	user_address = check_user_space(regs, error_code);

	/*
	 * Verify that the fault happened in user space, that
	 * we are not in an interrupt and that there is a 
	 * user context.
	 */
        if (user_address == 0 || in_interrupt() || !mm)
                goto no_context;

	/*
	 * When we get here, the fault happened in the current
	 * task's user address space, so we can switch on the
	 * interrupts again and then search the VMAs
	 */
	local_irq_enable();

        down_read(&mm->mmap_sem);

        vma = find_vma(mm, address);
        if (!vma)
                goto bad_area;
        if (vma->vm_start <= address) 
                goto good_area;
        if (!(vma->vm_flags & VM_GROWSDOWN))
                goto bad_area;
        if (expand_stack(vma, address))
                goto bad_area;
/*
 * Ok, we have a good vm_area for this memory access, so
 * we can handle it..
 */
good_area:
	si_code = SEGV_ACCERR;
	if (!is_protection) {
		/* page not present, check vm flags */
		if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
			goto bad_area;
	} else {
		if (!(vma->vm_flags & VM_WRITE))
			goto bad_area;
	}

survive:
	/*
	 * If for any reason at all we couldn't handle the fault,
	 * make sure we exit gracefully rather than endlessly redo
	 * the fault.
	 */
	switch (handle_mm_fault(mm, vma, address, is_protection)) {
	case VM_FAULT_MINOR:
		tsk->min_flt++;
		break;
	case VM_FAULT_MAJOR:
		tsk->maj_flt++;
		break;
	case VM_FAULT_SIGBUS:
		goto do_sigbus;
	case VM_FAULT_OOM:
		goto out_of_memory;
	default:
		BUG();
	}

        up_read(&mm->mmap_sem);
	/*
	 * The instruction that caused the program check will
	 * be repeated. Don't signal single step via SIGTRAP.
	 */
	clear_tsk_thread_flag(current, TIF_SINGLE_STEP);
        return;

/*
 * Something tried to access memory that isn't in our memory map..
 * Fix it, but check if it's kernel or user first..
 */
bad_area:
        up_read(&mm->mmap_sem);

        /* User mode accesses just cause a SIGSEGV */
        if (regs->psw.mask & PSW_MASK_PSTATE) {
                tsk->thread.prot_addr = address;
                tsk->thread.trap_no = error_code;
		do_sigsegv(regs, error_code, si_code, address);
                return;
	}

no_context:
        /* Are we prepared to handle this kernel fault?  */
	fixup = search_exception_tables(regs->psw.addr & __FIXUP_MASK);
	if (fixup) {
		regs->psw.addr = fixup->fixup | PSW_ADDR_AMODE;
                return;
        }

/*
 * Oops. The kernel tried to access some bad page. We'll have to
 * terminate things with extreme prejudice.
 */
        if (user_address == 0)
                printk(KERN_ALERT "Unable to handle kernel pointer dereference"
        	       " at virtual kernel address %p\n", (void *)address);
        else
                printk(KERN_ALERT "Unable to handle kernel paging request"
		       " at virtual user address %p\n", (void *)address);

        die("Oops", regs, error_code);
        do_exit(SIGKILL);


/*
 * We ran out of memory, or some other thing happened to us that made
 * us unable to handle the page fault gracefully.
*/
out_of_memory:
	up_read(&mm->mmap_sem);
	if (tsk->pid == 1) {
		yield();
		goto survive;
	}
	printk("VM: killing process %s\n", tsk->comm);
	if (regs->psw.mask & PSW_MASK_PSTATE)
		do_exit(SIGKILL);
	goto no_context;

do_sigbus:
	up_read(&mm->mmap_sem);

	/*
	 * Send a sigbus, regardless of whether we were in kernel
	 * or user mode.
	 */
        tsk->thread.prot_addr = address;
        tsk->thread.trap_no = error_code;
	force_sig(SIGBUS, tsk);

	/* Kernel mode? Handle exceptions or die */
	if (!(regs->psw.mask & PSW_MASK_PSTATE))
		goto no_context;
}
예제 #16
0
파일: exit.c 프로젝트: 0x1abin/linux0.11
//// 系统调用exit()。终止进程。
int sys_exit (int error_code)
{
  return do_exit ((error_code & 0xff) << 8);
}
예제 #17
0
SYSCALL_DEFINE1(exit, int, error_code) {
	do_exit((error_code&0xff) << 8);
	return SYSCALL_RETURN(0);
}
예제 #18
0
파일: process.c 프로젝트: CSCLOG/beaglebone
static void __noreturn
kernel_thread_helper(void *unused0, int (*fn)(void *),
		 void *arg, void *unused1)
{
	do_exit(fn(arg));
}
예제 #19
0
파일: proc.c 프로젝트: xuchiheng/ucore_plus
int do_execve(const char *filename, const char **argv, const char **envp)
{
	static_assert(EXEC_MAX_ARG_LEN >= FS_MAX_FPATH_LEN);

	struct mm_struct *mm = current->mm;

	char local_name[PROC_NAME_LEN + 1];
	memset(local_name, 0, sizeof(local_name));

	char *kargv[EXEC_MAX_ARG_NUM], *kenvp[EXEC_MAX_ENV_NUM];
	const char *path;

	int ret = -E_INVAL;
	lock_mm(mm);
#if 0
	if (name == NULL) {
		snprintf(local_name, sizeof(local_name), "<null> %d",
			 current->pid);
	} else {
		if (!copy_string(mm, local_name, name, sizeof(local_name))) {
			unlock_mm(mm);
			return ret;
		}
	}
#endif
	snprintf(local_name, sizeof(local_name), "<null> %d", current->pid);

	int argc = 0, envc = 0;
	if ((ret = copy_kargv(mm, kargv, argv, EXEC_MAX_ARG_NUM, &argc)) != 0) {
		unlock_mm(mm);
		return ret;
	}
	if ((ret = copy_kargv(mm, kenvp, envp, EXEC_MAX_ENV_NUM, &envc)) != 0) {
		unlock_mm(mm);
		put_kargv(argc, kargv);
		return ret;
	}
#if 0
	int i;
	kprintf("## fn %s\n", filename);
	kprintf("## argc %d\n", argc);
	for (i = 0; i < argc; i++)
		kprintf("## %08x %s\n", kargv[i], kargv[i]);
	kprintf("## envc %d\n", envc);
	for (i = 0; i < envc; i++)
		kprintf("## %08x %s\n", kenvp[i], kenvp[i]);
#endif
	//path = argv[0];
	//copy_from_user (mm, &path, argv, sizeof (char*), 0);
	path = filename;
	unlock_mm(mm);

	/* linux never do this */
	//fs_closeall(current->fs_struct);

	/* sysfile_open will check the first argument path, thus we have to use a user-space pointer, and argv[0] may be incorrect */

	int fd;
	if ((ret = fd = sysfile_open(path, O_RDONLY)) < 0) {
		goto execve_exit;
	}

	if (mm != NULL) {
		mm->cpuid = -1;
		mp_set_mm_pagetable(NULL);
		if (mm_count_dec(mm) == 0) {
			exit_mmap(mm);
			put_pgdir(mm);
			bool intr_flag;
			local_intr_save(intr_flag);
			{
				list_del(&(mm->proc_mm_link));
			}
			local_intr_restore(intr_flag);
			mm_destroy(mm);
		}
		current->mm = NULL;
	}
	put_sem_queue(current);

	ret = -E_NO_MEM;
	/* init signal */
	put_sighand(current);
	if ((current->signal_info.sighand = sighand_create()) == NULL) {
		goto execve_exit;
	}
	sighand_count_inc(current->signal_info.sighand);

	put_signal(current);
	if ((current->signal_info.signal = signal_create()) == NULL) {
		goto execve_exit;
	}
	signal_count_inc(current->signal_info.signal);

	if ((current->sem_queue = sem_queue_create()) == NULL) {
		goto execve_exit;
	}
	sem_queue_count_inc(current->sem_queue);

	if ((ret = load_icode(fd, argc, kargv, envc, kenvp)) != 0) {
		goto execve_exit;
	}

	set_proc_name(current, local_name);

	if (do_execve_arch_hook(argc, kargv) < 0)
		goto execve_exit;

	put_kargv(argc, kargv);
	put_kargv(envc, kenvp);
	return 0;

execve_exit:
	put_kargv(argc, kargv);
	put_kargv(envc, kenvp);
/* exec should return -1 if failed */
	//return ret;
	do_exit(ret);
	panic("already exit: %e.\n", ret);
}
예제 #20
0
static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
		       int signo, sigset_t *oldset)
{
	struct signal_frame __user *sf;
	int sigframe_size, err;

	/* 1. Make sure everything is clean */
	synchronize_user_stack();

	sigframe_size = SF_ALIGNEDSZ;
	if (!used_math())
		sigframe_size -= sizeof(__siginfo_fpu_t);

	sf = (struct signal_frame __user *)
		get_sigframe(&ka->sa, regs, sigframe_size);

	if (invalid_frame_pointer(sf, sigframe_size))
		goto sigill_and_return;

	if (current_thread_info()->w_saved != 0)
		goto sigill_and_return;

	/* 2. Save the current process state */
	err = __copy_to_user(&sf->info.si_regs, regs, sizeof(struct pt_regs));
	
	err |= __put_user(0, &sf->extra_size);

	if (used_math()) {
		err |= save_fpu_state(regs, &sf->fpu_state);
		err |= __put_user(&sf->fpu_state, &sf->fpu_save);
	} else {
		err |= __put_user(0, &sf->fpu_save);
	}

	err |= __put_user(oldset->sig[0], &sf->info.si_mask);
	err |= __copy_to_user(sf->extramask, &oldset->sig[1],
			      (_NSIG_WORDS - 1) * sizeof(unsigned int));
	err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP],
			      sizeof(struct reg_window32));
	if (err)
		goto sigsegv;
	
	/* 3. signal handler back-trampoline and parameters */
	regs->u_regs[UREG_FP] = (unsigned long) sf;
	regs->u_regs[UREG_I0] = signo;
	regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
	regs->u_regs[UREG_I2] = (unsigned long) &sf->info;

	/* 4. signal handler */
	regs->pc = (unsigned long) ka->sa.sa_handler;
	regs->npc = (regs->pc + 4);

	/* 5. return to kernel instructions */
	if (ka->ka_restorer)
		regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
	else {
		regs->u_regs[UREG_I7] = (unsigned long)(&(sf->insns[0]) - 2);

		/* mov __NR_sigreturn, %g1 */
		err |= __put_user(0x821020d8, &sf->insns[0]);

		/* t 0x10 */
		err |= __put_user(0x91d02010, &sf->insns[1]);
		if (err)
			goto sigsegv;

		/* Flush instruction space. */
		flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
	}
	return 0;

sigill_and_return:
	do_exit(SIGILL);
	return -EINVAL;

sigsegv:
	force_sigsegv(signo, current);
	return -EFAULT;
}
예제 #21
0
파일: threads.c 프로젝트: stfairy/lkl
struct task_struct *__switch_to(struct task_struct *prev,
				struct task_struct *next)
{
	struct thread_info *_prev = task_thread_info(prev);
	struct thread_info *_next = task_thread_info(next);
	/*
	 * schedule() expects the return of this function to be the task that we
	 * switched away from. Returning prev is not going to work because we
	 * are actually going to return the previous taks that was scheduled
	 * before the task we are going to wake up, and not the current task,
	 * e.g.:
	 *
	 * swapper -> init: saved prev on swapper stack is swapper
	 * init -> ksoftirqd0: saved prev on init stack is init
	 * ksoftirqd0 -> swapper: returned prev is swapper
	 */
	static struct task_struct *abs_prev = &init_task;
	/*
	 * We need to free the thread_info structure in free_thread_info to
	 * avoid races between the dying thread and other threads. We also need
	 * to cleanup sched_sem and signal to the prev thread that it needs to
	 * exit, and we use this stack varible to pass this info.
	 */
	struct thread_exit_info ei = {
		.dead = false,
		.sched_sem = _prev->sched_sem,
	};

	_current_thread_info = task_thread_info(next);
	_next->prev_sched = prev;
	abs_prev = prev;
	_prev->exit_info = &ei;

	lkl_ops->sem_up(_next->sched_sem);
	/* _next may be already gone so use ei instead */
	lkl_ops->sem_down(ei.sched_sem);

	if (ei.dead) {
		lkl_ops->sem_free(ei.sched_sem);
		threads_counter_dec();
		lkl_ops->thread_exit();
	}

	_prev->exit_info = NULL;

	return abs_prev;
}

struct thread_bootstrap_arg {
	struct thread_info *ti;
	int (*f)(void *);
	void *arg;
};

static void thread_bootstrap(void *_tba)
{
	struct thread_bootstrap_arg *tba = (struct thread_bootstrap_arg *)_tba;
	struct thread_info *ti = tba->ti;
	int (*f)(void *) = tba->f;
	void *arg = tba->arg;

	lkl_ops->sem_down(ti->sched_sem);
	kfree(tba);
	if (ti->prev_sched)
		schedule_tail(ti->prev_sched);

	f(arg);
	do_exit(0);
}

int copy_thread(unsigned long clone_flags, unsigned long esp,
		unsigned long unused, struct task_struct *p)
{
	struct thread_info *ti = task_thread_info(p);
	struct thread_bootstrap_arg *tba;
	int ret;

	tba = kmalloc(sizeof(*tba), GFP_KERNEL);
	if (!tba)
		return -ENOMEM;

	tba->f = (int (*)(void *))esp;
	tba->arg = (void *)unused;
	tba->ti = ti;

	ret = lkl_ops->thread_create(thread_bootstrap, tba);
	if (ret) {
		kfree(tba);
		return -ENOMEM;
	}

	threads_counter_inc();

	return 0;
}

void show_stack(struct task_struct *task, unsigned long *esp)
{
}

static inline void pr_early(const char *str)
{
	if (lkl_ops->print)
		lkl_ops->print(str, strlen(str));
}

/**
 * This is called before the kernel initializes, so no kernel calls (including
 * printk) can't be made yet.
 */
int threads_init(void)
{
	struct thread_info *ti = &init_thread_union.thread_info;
	int ret = 0;

	ti->exit_info = NULL;
	ti->prev_sched = NULL;

	ti->sched_sem = lkl_ops->sem_alloc(0);
	if (!ti->sched_sem) {
		pr_early("lkl: failed to allocate init schedule semaphore\n");
		ret = -ENOMEM;
		goto out;
	}

	threads_counter_lock = lkl_ops->sem_alloc(1);
	if (!threads_counter_lock) {
		pr_early("lkl: failed to alllocate threads counter lock\n");
		ret = -ENOMEM;
		goto out_free_init_sched_sem;
	}

	return 0;

out_free_init_sched_sem:
	lkl_ops->sem_free(ti->sched_sem);

out:
	return ret;
}

void threads_cleanup(void)
{
	struct task_struct *p;

	for_each_process(p) {
		struct thread_info *ti = task_thread_info(p);

		if (p->pid != 1)
			WARN(!(p->flags & PF_KTHREAD),
			     "non kernel thread task %p\n", p->comm);
		WARN(p->state == TASK_RUNNING,
		     "thread %s still running while halting\n", p->comm);

		kill_thread(ti->exit_info);
	}

	while (threads_counter_get())
		;

	lkl_ops->sem_free(init_thread_union.thread_info.sched_sem);
	lkl_ops->sem_free(threads_counter_lock);
}
예제 #22
0
static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
			  int signo, sigset_t *oldset, siginfo_t *info)
{
	struct rt_signal_frame __user *sf;
	int sigframe_size;
	unsigned int psr;
	int err;

	synchronize_user_stack();
	sigframe_size = RT_ALIGNEDSZ;
	if (!used_math())
		sigframe_size -= sizeof(__siginfo_fpu_t);
	sf = (struct rt_signal_frame __user *)
		get_sigframe(&ka->sa, regs, sigframe_size);
	if (invalid_frame_pointer(sf, sigframe_size))
		goto sigill;
	if (current_thread_info()->w_saved != 0)
		goto sigill;

	err  = __put_user(regs->pc, &sf->regs.pc);
	err |= __put_user(regs->npc, &sf->regs.npc);
	err |= __put_user(regs->y, &sf->regs.y);
	psr = regs->psr;
	if (used_math())
		psr |= PSR_EF;
	err |= __put_user(psr, &sf->regs.psr);
	err |= __copy_to_user(&sf->regs.u_regs, regs->u_regs, sizeof(regs->u_regs));
	err |= __put_user(0, &sf->extra_size);

	if (psr & PSR_EF) {
		err |= save_fpu_state(regs, &sf->fpu_state);
		err |= __put_user(&sf->fpu_state, &sf->fpu_save);
	} else {
		err |= __put_user(0, &sf->fpu_save);
	}
	err |= __copy_to_user(&sf->mask, &oldset->sig[0], sizeof(sigset_t));
	
	/* Setup sigaltstack */
	err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp);
	err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags);
	err |= __put_user(current->sas_ss_size, &sf->stack.ss_size);
	
	err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP],
			      sizeof(struct reg_window32));

	err |= copy_siginfo_to_user(&sf->info, info);

	if (err)
		goto sigsegv;

	regs->u_regs[UREG_FP] = (unsigned long) sf;
	regs->u_regs[UREG_I0] = signo;
	regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
	regs->u_regs[UREG_I2] = (unsigned long) &sf->regs;

	regs->pc = (unsigned long) ka->sa.sa_handler;
	regs->npc = (regs->pc + 4);

	if (ka->ka_restorer)
		regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
	else {
		regs->u_regs[UREG_I7] = (unsigned long)(&(sf->insns[0]) - 2);

		/* mov __NR_sigreturn, %g1 */
		err |= __put_user(0x821020d8, &sf->insns[0]);

		/* t 0x10 */
		err |= __put_user(0x91d02010, &sf->insns[1]);
		if (err)
			goto sigsegv;

		/* Flush instruction space. */
		flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
	}
	return 0;

sigill:
	do_exit(SIGILL);
	return -EINVAL;

sigsegv:
	force_sigsegv(signo, current);
	return -EFAULT;
}
예제 #23
0
파일: process.c 프로젝트: CSCLOG/beaglebone
/*
 * Create a kernel thread
 */
static void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *))
{
	do_exit(fn(arg));
}
예제 #24
0
bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
{
	struct task_struct *tsk;
	unsigned long caller;
	int vsyscall_nr, syscall_nr, tmp;
	int prev_sig_on_uaccess_error;
	long ret;

	/*
	 * No point in checking CS -- the only way to get here is a user mode
	 * trap to a high address, which means that we're in 64-bit user code.
	 */

	WARN_ON_ONCE(address != regs->ip);

	if (vsyscall_mode == NONE) {
		warn_bad_vsyscall(KERN_INFO, regs,
				  "vsyscall attempted with vsyscall=none");
		return false;
	}

	vsyscall_nr = addr_to_vsyscall_nr(address);

	trace_emulate_vsyscall(vsyscall_nr);

	if (vsyscall_nr < 0) {
		warn_bad_vsyscall(KERN_WARNING, regs,
				  "misaligned vsyscall (exploit attempt or buggy program) -- look up the vsyscall kernel parameter if you need a workaround");
		goto sigsegv;
	}

	if (get_user(caller, (unsigned long __user *)regs->sp) != 0) {
		warn_bad_vsyscall(KERN_WARNING, regs,
				  "vsyscall with bad stack (exploit attempt?)");
		goto sigsegv;
	}

	tsk = current;

	/*
	 * Check for access_ok violations and find the syscall nr.
	 *
	 * NULL is a valid user pointer (in the access_ok sense) on 32-bit and
	 * 64-bit, so we don't need to special-case it here.  For all the
	 * vsyscalls, NULL means "don't write anything" not "write it at
	 * address 0".
	 */
	switch (vsyscall_nr) {
	case 0:
		if (!write_ok_or_segv(regs->di, sizeof(struct timeval)) ||
		    !write_ok_or_segv(regs->si, sizeof(struct timezone))) {
			ret = -EFAULT;
			goto check_fault;
		}

		syscall_nr = __NR_gettimeofday;
		break;

	case 1:
		if (!write_ok_or_segv(regs->di, sizeof(time_t))) {
			ret = -EFAULT;
			goto check_fault;
		}

		syscall_nr = __NR_time;
		break;

	case 2:
		if (!write_ok_or_segv(regs->di, sizeof(unsigned)) ||
		    !write_ok_or_segv(regs->si, sizeof(unsigned))) {
			ret = -EFAULT;
			goto check_fault;
		}

		syscall_nr = __NR_getcpu;
		break;
	}

	/*
	 * Handle seccomp.  regs->ip must be the original value.
	 * See seccomp_send_sigsys and Documentation/prctl/seccomp_filter.txt.
	 *
	 * We could optimize the seccomp disabled case, but performance
	 * here doesn't matter.
	 */
	regs->orig_ax = syscall_nr;
	regs->ax = -ENOSYS;
	tmp = secure_computing(syscall_nr);
	if ((!tmp && regs->orig_ax != syscall_nr) || regs->ip != address) {
		warn_bad_vsyscall(KERN_DEBUG, regs,
				  "seccomp tried to change syscall nr or ip");
		do_exit(SIGSYS);
	}
	if (tmp)
		goto do_ret;  /* skip requested */

	/*
	 * With a real vsyscall, page faults cause SIGSEGV.  We want to
	 * preserve that behavior to make writing exploits harder.
	 */
	prev_sig_on_uaccess_error = current_thread_info()->sig_on_uaccess_error;
	current_thread_info()->sig_on_uaccess_error = 1;

	ret = -EFAULT;
	switch (vsyscall_nr) {
	case 0:
		ret = sys_gettimeofday(
			(struct timeval __user *)regs->di,
			(struct timezone __user *)regs->si);
		break;

	case 1:
		ret = sys_time((time_t __user *)regs->di);
		break;

	case 2:
		ret = sys_getcpu((unsigned __user *)regs->di,
				 (unsigned __user *)regs->si,
				 NULL);
		break;
	}

	current_thread_info()->sig_on_uaccess_error = prev_sig_on_uaccess_error;

check_fault:
	if (ret == -EFAULT) {
		/* Bad news -- userspace fed a bad pointer to a vsyscall. */
		warn_bad_vsyscall(KERN_INFO, regs,
				  "vsyscall fault (exploit attempt?)");

		/*
		 * If we failed to generate a signal for any reason,
		 * generate one here.  (This should be impossible.)
		 */
		if (WARN_ON_ONCE(!sigismember(&tsk->pending.signal, SIGBUS) &&
				 !sigismember(&tsk->pending.signal, SIGSEGV)))
			goto sigsegv;

		return true;  /* Don't emulate the ret. */
	}

	regs->ax = ret;

do_ret:
	/* Emulate a ret instruction. */
	regs->ip = caller;
	regs->sp += 8;
	return true;

sigsegv:
	force_sig(SIGSEGV, current);
	return true;
}
예제 #25
0
// There was a memory error. Exit.
void mem_error() {
    perror("Out of memory.\n");
    do_exit();
}
static inline int
setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
	       int signo, sigset_t *oldset, siginfo_t *info)
{
	struct rt_signal_frame __user *sf;
	int wsaved, err, sf_size;
	void __user *tail;

	
	synchronize_user_stack();
	save_and_clear_fpu();
	
	wsaved = get_thread_wsaved();

	sf_size = sizeof(struct rt_signal_frame);
	if (current_thread_info()->fpsaved[0] & FPRS_FEF)
		sf_size += sizeof(__siginfo_fpu_t);
	if (wsaved)
		sf_size += sizeof(__siginfo_rwin_t);
	sf = (struct rt_signal_frame __user *)
		get_sigframe(ka, regs, sf_size);

	if (invalid_frame_pointer (sf))
		goto sigill;

	tail = (sf + 1);

	
	err = copy_to_user(&sf->regs, regs, sizeof (*regs));

	if (current_thread_info()->fpsaved[0] & FPRS_FEF) {
		__siginfo_fpu_t __user *fpu_save = tail;
		tail += sizeof(__siginfo_fpu_t);
		err |= save_fpu_state(regs, fpu_save);
		err |= __put_user((u64)fpu_save, &sf->fpu_save);
	} else {
		err |= __put_user(0, &sf->fpu_save);
	}
	if (wsaved) {
		__siginfo_rwin_t __user *rwin_save = tail;
		tail += sizeof(__siginfo_rwin_t);
		err |= save_rwin_state(wsaved, rwin_save);
		err |= __put_user((u64)rwin_save, &sf->rwin_save);
		set_thread_wsaved(0);
	} else {
		err |= __put_user(0, &sf->rwin_save);
	}
	
	
	err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp);
	err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags);
	err |= __put_user(current->sas_ss_size, &sf->stack.ss_size);

	err |= copy_to_user(&sf->mask, oldset, sizeof(sigset_t));

	if (!wsaved) {
		err |= copy_in_user((u64 __user *)sf,
				    (u64 __user *)(regs->u_regs[UREG_FP] +
						   STACK_BIAS),
				    sizeof(struct reg_window));
	} else {
		struct reg_window *rp;

		rp = &current_thread_info()->reg_window[wsaved - 1];
		err |= copy_to_user(sf, rp, sizeof(struct reg_window));
	}
	if (info)
		err |= copy_siginfo_to_user(&sf->info, info);
	else {
		err |= __put_user(signo, &sf->info.si_signo);
		err |= __put_user(SI_NOINFO, &sf->info.si_code);
	}
	if (err)
		goto sigsegv;
	
	
	regs->u_regs[UREG_FP] = ((unsigned long) sf) - STACK_BIAS;
	regs->u_regs[UREG_I0] = signo;
	regs->u_regs[UREG_I1] = (unsigned long) &sf->info;

	regs->u_regs[UREG_I2] = (unsigned long) &sf->info;

	
	regs->tpc = (unsigned long) ka->sa.sa_handler;
	regs->tnpc = (regs->tpc + 4);
	if (test_thread_flag(TIF_32BIT)) {
		regs->tpc &= 0xffffffff;
		regs->tnpc &= 0xffffffff;
	}
	
	regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
	return 0;

sigill:
	do_exit(SIGILL);
	return -EINVAL;

sigsegv:
	force_sigsegv(signo, current);
	return -EFAULT;
}
예제 #27
0
asmlinkage long sys_exit(int error_code)
{
    do_exit((error_code&0xff)<<8);
}
예제 #28
0
static inline int
setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs)
{
	struct rt_signal_frame __user *sf;
	int wsaved, err, sf_size;
	void __user *tail;

	/* 1. Make sure everything is clean */
	synchronize_user_stack();
	save_and_clear_fpu();
	
	wsaved = get_thread_wsaved();

	sf_size = sizeof(struct rt_signal_frame);
	if (current_thread_info()->fpsaved[0] & FPRS_FEF)
		sf_size += sizeof(__siginfo_fpu_t);
	if (wsaved)
		sf_size += sizeof(__siginfo_rwin_t);
	sf = (struct rt_signal_frame __user *)
		get_sigframe(ksig, regs, sf_size);

	if (invalid_frame_pointer (sf)) {
		do_exit(SIGILL);	/* won't return, actually */
		return -EINVAL;
	}

	tail = (sf + 1);

	/* 2. Save the current process state */
	err = copy_to_user(&sf->regs, regs, sizeof (*regs));

	if (current_thread_info()->fpsaved[0] & FPRS_FEF) {
		__siginfo_fpu_t __user *fpu_save = tail;
		tail += sizeof(__siginfo_fpu_t);
		err |= save_fpu_state(regs, fpu_save);
		err |= __put_user((u64)fpu_save, &sf->fpu_save);
	} else {
		err |= __put_user(0, &sf->fpu_save);
	}
	if (wsaved) {
		__siginfo_rwin_t __user *rwin_save = tail;
		tail += sizeof(__siginfo_rwin_t);
		err |= save_rwin_state(wsaved, rwin_save);
		err |= __put_user((u64)rwin_save, &sf->rwin_save);
		set_thread_wsaved(0);
	} else {
		err |= __put_user(0, &sf->rwin_save);
	}
	
	/* Setup sigaltstack */
	err |= __save_altstack(&sf->stack, regs->u_regs[UREG_FP]);

	err |= copy_to_user(&sf->mask, sigmask_to_save(), sizeof(sigset_t));

	if (!wsaved) {
		err |= copy_in_user((u64 __user *)sf,
				    (u64 __user *)(regs->u_regs[UREG_FP] +
						   STACK_BIAS),
				    sizeof(struct reg_window));
	} else {
		struct reg_window *rp;

		rp = &current_thread_info()->reg_window[wsaved - 1];
		err |= copy_to_user(sf, rp, sizeof(struct reg_window));
	}
	if (ksig->ka.sa.sa_flags & SA_SIGINFO)
		err |= copy_siginfo_to_user(&sf->info, &ksig->info);
	else {
		err |= __put_user(ksig->sig, &sf->info.si_signo);
		err |= __put_user(SI_NOINFO, &sf->info.si_code);
	}
	if (err)
		return err;
	
	/* 3. signal handler back-trampoline and parameters */
	regs->u_regs[UREG_FP] = ((unsigned long) sf) - STACK_BIAS;
	regs->u_regs[UREG_I0] = ksig->sig;
	regs->u_regs[UREG_I1] = (unsigned long) &sf->info;

	/* The sigcontext is passed in this way because of how it
	 * is defined in GLIBC's /usr/include/bits/sigcontext.h
	 * for sparc64.  It includes the 128 bytes of siginfo_t.
	 */
	regs->u_regs[UREG_I2] = (unsigned long) &sf->info;

	/* 5. signal handler */
	regs->tpc = (unsigned long) ksig->ka.sa.sa_handler;
	regs->tnpc = (regs->tpc + 4);
	if (test_thread_flag(TIF_32BIT)) {
		regs->tpc &= 0xffffffff;
		regs->tnpc &= 0xffffffff;
	}
	/* 4. return to kernel instructions */
	regs->u_regs[UREG_I7] = (unsigned long)ksig->ka.ka_restorer;
	return 0;
}
예제 #29
0
asmlinkage unsigned long asm_do_sig(unsigned long esr, struct pt_regs *regs)
{
	struct siginfo info;
	struct task_struct *tsk;
	struct mm_struct *mm;
	int sig;
 	int trapidx = 0;
	unsigned long addr;
	//register unsigned long sp asm("sp");

	switch(esr & ESR_CODE)
	{
		case TCT_PRIVILEGED:
			addr = regs->elkr;
			printk("Privileged Instruction Exception @ %lx\n", addr);
			sig = SIGSEGV;
			trapidx = 1;
			break;
		case TCT_UNDEFINED:
			addr = regs->elkr;
			printk("Undefined Instruction Exception @ %lx\n", addr);
			sig = SIGSEGV;
			trapidx = 2;
			break;
		case TCT_ITLB:
			addr = regs->elkr;
			printk("Instruction TLB Exception @ %lx\n", addr);
			sig = SIGSEGV;
			trapidx = 3;
			break;
		case TCT_DTLB:
			addr = regs->elkr;
			printk("Data TLB Exception @ %lx\n", addr);
			sig = SIGSEGV;
			trapidx = 4;
			break;
		case TCT_FETCH_ABORT:
			addr = regs->elkr;
			printk("Fetch Abort Exception @ address %lx\n", addr);
			sig = SIGABRT;
			trapidx= 5;
			break;
		case TCT_DATA_ABORT:/*interrupt exception */
			addr = regs->elkr;
			printk("Data Abort Exception @ %lx\n", addr);
			sig = SIGABRT;
			trapidx = 6;
			break; 
		case TCT_ZERO_DIV:/*interrupt exception */
			addr = regs->elkr;
			printk("Zero Division Exception @ %lx\n", addr);
			sig = SIGSEGV;
			trapidx = 7;
			break;	
		default:
			addr = regs->elkr;
			printk("Unknown exception, defaulting to SIGSEGV @ %lx\n", addr);
			sig = SIGSEGV;
			trapidx = 8;
			break;		 	
	}

	memset(&info, 0, sizeof(info));
	info.si_signo = sig;
	info.si_addr = (void*)addr;

	tsk = current;
	mm = tsk->mm;

	/*
	 * If we're on the kernel stack or during disabled interrupts
	 * or in an atomic section or if we have no user context, the kernel gets the fault.
	 */
	if( !mm || in_atomic())
	{
		/* the kernel gets the fault */
		bust_spinlocks(1);
		printk(KERN_ALERT "%s: unhandled kernel space fault (%d) @ %lx\n", tsk->comm, sig, addr);
		bust_spinlocks(0);
		local_irq_enable();
		do_exit(SIGKILL);
		return 0;
	} else {
		/* the user space gets the fault */
		if( sig != SIGTRAP )
			printk(KERN_ERR "%s: unhandled user space fault (%d) @ %lx\n", tsk->comm, sig, addr);
		force_sig_info(sig, &info, tsk);
		return regs->r1;
	}
}
예제 #30
0
파일: irixioctl.c 프로젝트: 274914765/C
asmlinkage int irix_ioctl(int fd, unsigned long cmd, unsigned long arg)
{
    struct tty_struct *tp, *rtp;
    mm_segment_t old_fs;
    int i, error = 0;

#ifdef DEBUG_IOCTLS
    printk("[%s:%d] irix_ioctl(%d, ", current->comm, current->pid, fd);
#endif
    switch(cmd) {
    case 0x00005401:
#ifdef DEBUG_IOCTLS
        printk("TCGETA, %08lx) ", arg);
#endif
        error = sys_ioctl(fd, TCGETA, arg);
        break;

    case 0x0000540d: {
        struct termios kt;
        struct irix_termios __user *it =
            (struct irix_termios __user *) arg;

#ifdef DEBUG_IOCTLS
        printk("TCGETS, %08lx) ", arg);
#endif
        if (!access_ok(VERIFY_WRITE, it, sizeof(*it))) {
            error = -EFAULT;
            break;
        }
        old_fs = get_fs(); set_fs(get_ds());
        error = sys_ioctl(fd, TCGETS, (unsigned long) &kt);
        set_fs(old_fs);
        if (error)
            break;

        error = __put_user(kt.c_iflag, &it->c_iflag);
        error |= __put_user(kt.c_oflag, &it->c_oflag);
        error |= __put_user(kt.c_cflag, &it->c_cflag);
        error |= __put_user(kt.c_lflag, &it->c_lflag);

        for (i = 0; i < NCCS; i++)
            error |= __put_user(kt.c_cc[i], &it->c_cc[i]);
        break;
    }

    case 0x0000540e: {
        struct termios kt;
        struct irix_termios *it = (struct irix_termios *) arg;

#ifdef DEBUG_IOCTLS
        printk("TCSETS, %08lx) ", arg);
#endif
        if (!access_ok(VERIFY_READ, it, sizeof(*it))) {
            error = -EFAULT;
            break;
        }
        old_fs = get_fs(); set_fs(get_ds());
        error = sys_ioctl(fd, TCGETS, (unsigned long) &kt);
        set_fs(old_fs);
        if (error)
            break;

        error = __get_user(kt.c_iflag, &it->c_iflag);
        error |= __get_user(kt.c_oflag, &it->c_oflag);
        error |= __get_user(kt.c_cflag, &it->c_cflag);
        error |= __get_user(kt.c_lflag, &it->c_lflag);

        for (i = 0; i < NCCS; i++)
            error |= __get_user(kt.c_cc[i], &it->c_cc[i]);

        if (error)
            break;
        old_fs = get_fs(); set_fs(get_ds());
        error = sys_ioctl(fd, TCSETS, (unsigned long) &kt);
        set_fs(old_fs);
        break;
    }

    case 0x0000540f:
#ifdef DEBUG_IOCTLS
        printk("TCSETSW, %08lx) ", arg);
#endif
        error = sys_ioctl(fd, TCSETSW, arg);
        break;

    case 0x00005471:
#ifdef DEBUG_IOCTLS
        printk("TIOCNOTTY, %08lx) ", arg);
#endif
        error = sys_ioctl(fd, TIOCNOTTY, arg);
        break;

    case 0x00007416: {
        pid_t pid;
#ifdef DEBUG_IOCTLS
        printk("TIOCGSID, %08lx) ", arg);
#endif
        old_fs = get_fs(); set_fs(get_ds());
        error = sys_ioctl(fd, TIOCGSID, (unsigned long)&pid);
        set_fs(old_fs);
        if (!error)
            error = put_user(pid, (unsigned long __user *) arg);
        break;
    }
    case 0x746e:
        /* TIOCSTART, same effect as hitting ^Q */
#ifdef DEBUG_IOCTLS
        printk("TIOCSTART, %08lx) ", arg);
#endif
        error = sys_ioctl(fd, TCXONC, TCOON);
        break;

    case 0x20006968:
#ifdef DEBUG_IOCTLS
        printk("SIOCGETLABEL, %08lx) ", arg);
#endif
        error = -ENOPKG;
        break;

    case 0x40047477:
#ifdef DEBUG_IOCTLS
        printk("TIOCGPGRP, %08lx) ", arg);
#endif
        error = sys_ioctl(fd, TIOCGPGRP, arg);
#ifdef DEBUG_IOCTLS
        printk("arg=%d ", *(int *)arg);
#endif
        break;

    case 0x40087468:
#ifdef DEBUG_IOCTLS
        printk("TIOCGWINSZ, %08lx) ", arg);
#endif
        error = sys_ioctl(fd, TIOCGWINSZ, arg);
        break;

    case 0x8004667e:
        error = sys_ioctl(fd, FIONBIO, arg);
        break;

    case 0x80047476:
        error = sys_ioctl(fd, TIOCSPGRP, arg);
        break;

    case 0x8020690c:
        error = sys_ioctl(fd, SIOCSIFADDR, arg);
        break;

    case 0x80206910:
        error = sys_ioctl(fd, SIOCSIFFLAGS, arg);
        break;

    case 0xc0206911:
        error = sys_ioctl(fd, SIOCGIFFLAGS, arg);
        break;

    case 0xc020691b:
        error = sys_ioctl(fd, SIOCGIFMETRIC, arg);
        break;

    default: {
#ifdef DEBUG_MISSING_IOCTL
        char *msg = "Unimplemented IOCTL cmd tell [email protected]\n";

#ifdef DEBUG_IOCTLS
        printk("UNIMP_IOCTL, %08lx)\n", arg);
#endif
        old_fs = get_fs(); set_fs(get_ds());
        sys_write(2, msg, strlen(msg));
        set_fs(old_fs);
        printk("[%s:%d] Does unimplemented IRIX ioctl cmd %08lx\n",
               current->comm, current->pid, cmd);
        do_exit(255);
#else
        error = sys_ioctl(fd, cmd, arg);
#endif
    }

    };
#ifdef DEBUG_IOCTLS
    printk("error=%d\n", error);
#endif
    return error;
}