Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
[linux-2.6] / arch / um / kernel / syscall.c
1 /*
2  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3  * Licensed under the GPL
4  */
5
6 #include "linux/file.h"
7 #include "linux/fs.h"
8 #include "linux/mm.h"
9 #include "linux/sched.h"
10 #include "linux/utsname.h"
11 #include "asm/current.h"
12 #include "asm/mman.h"
13 #include "asm/uaccess.h"
14 #include "asm/unistd.h"
15
16 long sys_fork(void)
17 {
18         long ret;
19
20         current->thread.forking = 1;
21         ret = do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
22                       &current->thread.regs, 0, NULL, NULL);
23         current->thread.forking = 0;
24         return ret;
25 }
26
27 long sys_vfork(void)
28 {
29         long ret;
30
31         current->thread.forking = 1;
32         ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
33                       UPT_SP(&current->thread.regs.regs),
34                       &current->thread.regs, 0, NULL, NULL);
35         current->thread.forking = 0;
36         return ret;
37 }
38
39 /* common code for old and new mmaps */
40 long sys_mmap2(unsigned long addr, unsigned long len,
41                unsigned long prot, unsigned long flags,
42                unsigned long fd, unsigned long pgoff)
43 {
44         long error = -EBADF;
45         struct file * file = NULL;
46
47         flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
48         if (!(flags & MAP_ANONYMOUS)) {
49                 file = fget(fd);
50                 if (!file)
51                         goto out;
52         }
53
54         down_write(&current->mm->mmap_sem);
55         error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
56         up_write(&current->mm->mmap_sem);
57
58         if (file)
59                 fput(file);
60  out:
61         return error;
62 }
63
64 long old_mmap(unsigned long addr, unsigned long len,
65               unsigned long prot, unsigned long flags,
66               unsigned long fd, unsigned long offset)
67 {
68         long err = -EINVAL;
69         if (offset & ~PAGE_MASK)
70                 goto out;
71
72         err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
73  out:
74         return err;
75 }
76
77 long sys_uname(struct old_utsname __user * name)
78 {
79         long err;
80         if (!name)
81                 return -EFAULT;
82         down_read(&uts_sem);
83         err = copy_to_user(name, utsname(), sizeof (*name));
84         up_read(&uts_sem);
85         return err?-EFAULT:0;
86 }
87
88 long sys_olduname(struct oldold_utsname __user * name)
89 {
90         long error;
91
92         if (!name)
93                 return -EFAULT;
94         if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
95                 return -EFAULT;
96
97         down_read(&uts_sem);
98
99         error = __copy_to_user(&name->sysname, &utsname()->sysname,
100                                __OLD_UTS_LEN);
101         error |= __put_user(0, name->sysname + __OLD_UTS_LEN);
102         error |= __copy_to_user(&name->nodename, &utsname()->nodename,
103                                 __OLD_UTS_LEN);
104         error |= __put_user(0, name->nodename + __OLD_UTS_LEN);
105         error |= __copy_to_user(&name->release, &utsname()->release,
106                                 __OLD_UTS_LEN);
107         error |= __put_user(0, name->release + __OLD_UTS_LEN);
108         error |= __copy_to_user(&name->version, &utsname()->version,
109                                 __OLD_UTS_LEN);
110         error |= __put_user(0, name->version + __OLD_UTS_LEN);
111         error |= __copy_to_user(&name->machine, &utsname()->machine,
112                                 __OLD_UTS_LEN);
113         error |= __put_user(0, name->machine + __OLD_UTS_LEN);
114
115         up_read(&uts_sem);
116
117         error = error ? -EFAULT : 0;
118
119         return error;
120 }
121
122 int kernel_execve(const char *filename, char *const argv[], char *const envp[])
123 {
124         mm_segment_t fs;
125         int ret;
126
127         fs = get_fs();
128         set_fs(KERNEL_DS);
129         ret = um_execve(filename, argv, envp);
130         set_fs(fs);
131
132         return ret;
133 }