syscall.c 3.3 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 77 78 79 80 81
}

/* 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;
}
/*
 * sys_pipe() is the normal C calling standard for creating
 * a pipe. It's not the way unix traditionally does this, though.
 */
long sys_pipe(unsigned long __user * fildes)
{
J
Jeff Dike 已提交
82 83
	int fd[2];
	long error;
L
Linus Torvalds 已提交
84

J
Jeff Dike 已提交
85 86
	error = do_pipe(fd);
	if (!error) {
L
Linus Torvalds 已提交
87
		if (copy_to_user(fildes, fd, sizeof(fd)))
J
Jeff Dike 已提交
88 89 90
			error = -EFAULT;
	}
	return error;
L
Linus Torvalds 已提交
91 92 93
}


A
Al Viro 已提交
94
long sys_uname(struct old_utsname __user * name)
L
Linus Torvalds 已提交
95 96 97 98 99
{
	long err;
	if (!name)
		return -EFAULT;
	down_read(&uts_sem);
100
	err = copy_to_user(name, utsname(), sizeof (*name));
L
Linus Torvalds 已提交
101 102 103 104
	up_read(&uts_sem);
	return err?-EFAULT:0;
}

A
Al Viro 已提交
105
long sys_olduname(struct oldold_utsname __user * name)
L
Linus Torvalds 已提交
106 107 108 109 110 111 112
{
	long error;

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

J
Jeff Dike 已提交
114
	down_read(&uts_sem);
J
Jeff Dike 已提交
115

116
	error = __copy_to_user(&name->sysname, &utsname()->sysname,
L
Linus Torvalds 已提交
117
			       __OLD_UTS_LEN);
118 119
	error |= __put_user(0, name->sysname + __OLD_UTS_LEN);
	error |= __copy_to_user(&name->nodename, &utsname()->nodename,
L
Linus Torvalds 已提交
120
				__OLD_UTS_LEN);
121 122
	error |= __put_user(0, name->nodename + __OLD_UTS_LEN);
	error |= __copy_to_user(&name->release, &utsname()->release,
L
Linus Torvalds 已提交
123
				__OLD_UTS_LEN);
124 125
	error |= __put_user(0, name->release + __OLD_UTS_LEN);
	error |= __copy_to_user(&name->version, &utsname()->version,
L
Linus Torvalds 已提交
126
				__OLD_UTS_LEN);
127 128
	error |= __put_user(0, name->version + __OLD_UTS_LEN);
	error |= __copy_to_user(&name->machine, &utsname()->machine,
L
Linus Torvalds 已提交
129
				__OLD_UTS_LEN);
130
	error |= __put_user(0, name->machine + __OLD_UTS_LEN);
J
Jeff Dike 已提交
131

L
Linus Torvalds 已提交
132
	up_read(&uts_sem);
J
Jeff Dike 已提交
133

L
Linus Torvalds 已提交
134 135 136 137 138
	error = error ? -EFAULT : 0;

	return error;
}

139 140 141 142 143 144 145 146 147 148 149 150
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;
}