syscall.c 3.0 KB
Newer Older
J
Jeff Dike 已提交
1
/*
J
Jeff Dike 已提交
2
 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
L
Linus Torvalds 已提交
3 4 5 6
 * Licensed under the GPL
 */

#include "linux/file.h"
A
Alexey Dobriyan 已提交
7
#include "linux/fs.h"
J
Jeff Dike 已提交
8 9
#include "linux/mm.h"
#include "linux/sched.h"
L
Linus Torvalds 已提交
10
#include "linux/utsname.h"
J
Jeff Dike 已提交
11
#include "asm/current.h"
L
Linus Torvalds 已提交
12 13
#include "asm/mman.h"
#include "asm/uaccess.h"
J
Jeff Dike 已提交
14
#include "asm/unistd.h"
L
Linus Torvalds 已提交
15 16 17 18 19 20

long sys_fork(void)
{
	long ret;

	current->thread.forking = 1;
J
Jeff Dike 已提交
21 22
	ret = do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
		      &current->thread.regs, 0, NULL, NULL);
L
Linus Torvalds 已提交
23
	current->thread.forking = 0;
J
Jeff Dike 已提交
24
	return ret;
L
Linus Torvalds 已提交
25 26 27 28 29 30 31
}

long sys_vfork(void)
{
	long ret;

	current->thread.forking = 1;
J
Jeff Dike 已提交
32 33 34
	ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
		      UPT_SP(&current->thread.regs.regs),
		      &current->thread.regs, 0, NULL, NULL);
L
Linus Torvalds 已提交
35
	current->thread.forking = 0;
J
Jeff Dike 已提交
36
	return ret;
L
Linus Torvalds 已提交
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 67 68 69 70 71 72 73 74 75 76
}

/* common code for old and new mmaps */
long sys_mmap2(unsigned long addr, unsigned long len,
	       unsigned long prot, unsigned long flags,
	       unsigned long fd, unsigned long pgoff)
{
	long error = -EBADF;
	struct file * file = NULL;

	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
	if (!(flags & MAP_ANONYMOUS)) {
		file = fget(fd);
		if (!file)
			goto out;
	}

	down_write(&current->mm->mmap_sem);
	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
	up_write(&current->mm->mmap_sem);

	if (file)
		fput(file);
 out:
	return error;
}

long old_mmap(unsigned long addr, unsigned long len,
	      unsigned long prot, unsigned long flags,
	      unsigned long fd, unsigned long offset)
{
	long err = -EINVAL;
	if (offset & ~PAGE_MASK)
		goto out;

	err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
 out:
	return err;
}

A
Al Viro 已提交
77
long sys_uname(struct old_utsname __user * name)
L
Linus Torvalds 已提交
78 79 80 81 82
{
	long err;
	if (!name)
		return -EFAULT;
	down_read(&uts_sem);
83
	err = copy_to_user(name, utsname(), sizeof (*name));
L
Linus Torvalds 已提交
84 85 86 87
	up_read(&uts_sem);
	return err?-EFAULT:0;
}

A
Al Viro 已提交
88
long sys_olduname(struct oldold_utsname __user * name)
L
Linus Torvalds 已提交
89 90 91 92 93 94 95
{
	long error;

	if (!name)
		return -EFAULT;
	if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
		return -EFAULT;
J
Jeff Dike 已提交
96

J
Jeff Dike 已提交
97
	down_read(&uts_sem);
J
Jeff Dike 已提交
98

99
	error = __copy_to_user(&name->sysname, &utsname()->sysname,
L
Linus Torvalds 已提交
100
			       __OLD_UTS_LEN);
101 102
	error |= __put_user(0, name->sysname + __OLD_UTS_LEN);
	error |= __copy_to_user(&name->nodename, &utsname()->nodename,
L
Linus Torvalds 已提交
103
				__OLD_UTS_LEN);
104 105
	error |= __put_user(0, name->nodename + __OLD_UTS_LEN);
	error |= __copy_to_user(&name->release, &utsname()->release,
L
Linus Torvalds 已提交
106
				__OLD_UTS_LEN);
107 108
	error |= __put_user(0, name->release + __OLD_UTS_LEN);
	error |= __copy_to_user(&name->version, &utsname()->version,
L
Linus Torvalds 已提交
109
				__OLD_UTS_LEN);
110 111
	error |= __put_user(0, name->version + __OLD_UTS_LEN);
	error |= __copy_to_user(&name->machine, &utsname()->machine,
L
Linus Torvalds 已提交
112
				__OLD_UTS_LEN);
113
	error |= __put_user(0, name->machine + __OLD_UTS_LEN);
J
Jeff Dike 已提交
114

L
Linus Torvalds 已提交
115
	up_read(&uts_sem);
J
Jeff Dike 已提交
116

L
Linus Torvalds 已提交
117 118 119 120 121
	error = error ? -EFAULT : 0;

	return error;
}

122 123 124 125 126 127 128 129 130 131 132 133
int kernel_execve(const char *filename, char *const argv[], char *const envp[])
{
	mm_segment_t fs;
	int ret;

	fs = get_fs();
	set_fs(KERNEL_DS);
	ret = um_execve(filename, argv, envp);
	set_fs(fs);

	return ret;
}