syscalls_32.c 1.79 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5 6 7
/* 
 * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
 * Licensed under the GPL
 */

#include "linux/sched.h"
#include "linux/shm.h"
Adrian Bunk's avatar
Adrian Bunk committed
8
#include "linux/ipc.h"
Al Viro's avatar
Al Viro committed
9
#include "linux/syscalls.h"
Linus Torvalds's avatar
Linus Torvalds committed
10 11 12 13
#include "asm/mman.h"
#include "asm/uaccess.h"
#include "asm/unistd.h"

14 15 16 17 18 19 20
/*
 * The prototype on i386 is:
 *
 *     int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr)
 *
 * and the "newtls" arg. on i386 is read by copy_thread directly from the
 * register saved on the stack.
Linus Torvalds's avatar
Linus Torvalds committed
21 22
 */
long sys_clone(unsigned long clone_flags, unsigned long newsp,
23
	       int __user *parent_tid, void *newtls, int __user *child_tid)
Linus Torvalds's avatar
Linus Torvalds committed
24 25 26
{
	long ret;

Jeff Dike's avatar
Jeff Dike committed
27 28
	if (!newsp)
		newsp = UPT_SP(&current->thread.regs.regs);
29

Linus Torvalds's avatar
Linus Torvalds committed
30
	current->thread.forking = 1;
Jeff Dike's avatar
Jeff Dike committed
31 32
	ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
		      child_tid);
Linus Torvalds's avatar
Linus Torvalds committed
33
	current->thread.forking = 0;
34
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
}

long sys_sigaction(int sig, const struct old_sigaction __user *act,
			 struct old_sigaction __user *oact)
{
	struct k_sigaction new_ka, old_ka;
	int ret;

	if (act) {
		old_sigset_t mask;
		if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
			return -EFAULT;
		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
		__get_user(mask, &act->sa_mask);
		siginitset(&new_ka.sa.sa_mask, mask);
	}

	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);

	if (!ret && oact) {
		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
			return -EFAULT;
		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
	}

	return ret;
}