1/* 2 * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) 3 * Licensed under the GPL 4 */ 5 6#include "linux/sched.h" 7#include "linux/file.h" 8#include "linux/smp_lock.h" 9#include "linux/mm.h" 10#include "linux/utsname.h" 11#include "linux/msg.h" 12#include "linux/shm.h" 13#include "linux/sys.h" 14#include "linux/syscalls.h" 15#include "linux/unistd.h" 16#include "linux/slab.h" 17#include "linux/utime.h" 18#include "asm/mman.h" 19#include "asm/uaccess.h" 20#include "kern_util.h" 21#include "sysdep/syscalls.h" 22#include "mode_kern.h" 23#include "choose-mode.h" 24 25/* Unlocked, I don't care if this is a bit off */ 26int nsyscalls = 0; 27 28long sys_fork(void) 29{ 30 long ret; 31 32 current->thread.forking = 1; 33 ret = do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs), 34 ¤t->thread.regs, 0, NULL, NULL); 35 current->thread.forking = 0; 36 return(ret); 37} 38 39long sys_vfork(void) 40{ 41 long ret; 42 43 current->thread.forking = 1; 44 ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 45 UPT_SP(¤t->thread.regs.regs), 46 ¤t->thread.regs, 0, NULL, NULL); 47 current->thread.forking = 0; 48 return(ret); 49} 50 51/* common code for old and new mmaps */ 52long sys_mmap2(unsigned long addr, unsigned long len, 53 unsigned long prot, unsigned long flags, 54 unsigned long fd, unsigned long pgoff) 55{ 56 long error = -EBADF; 57 struct file * file = NULL; 58 59 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); 60 if (!(flags & MAP_ANONYMOUS)) { 61 file = fget(fd); 62 if (!file) 63 goto out; 64 } 65 66 down_write(¤t->mm->mmap_sem); 67 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); 68 up_write(¤t->mm->mmap_sem); 69 70 if (file) 71 fput(file); 72 out: 73 return error; 74} 75 76long old_mmap(unsigned long addr, unsigned long len, 77 unsigned long prot, unsigned long flags, 78 unsigned long fd, unsigned long offset) 79{ 80 long err = -EINVAL; 81 if (offset & ~PAGE_MASK) 82 goto out; 83 84 err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); 85 out: 86 return err; 87} 88/* 89 * sys_pipe() is the normal C calling standard for creating 90 * a pipe. It's not the way unix traditionally does this, though. 91 */ 92long sys_pipe(unsigned long __user * fildes) 93{ 94 int fd[2]; 95 long error; 96 97 error = do_pipe(fd); 98 if (!error) { 99 if (copy_to_user(fildes, fd, sizeof(fd))) 100 error = -EFAULT; 101 } 102 return error; 103} 104 105 106long sys_uname(struct old_utsname __user * name) 107{ 108 long err; 109 if (!name) 110 return -EFAULT; 111 down_read(&uts_sem); 112 err = copy_to_user(name, utsname(), sizeof (*name)); 113 up_read(&uts_sem); 114 return err?-EFAULT:0; 115} 116 117long sys_olduname(struct oldold_utsname __user * name) 118{ 119 long error; 120 121 if (!name) 122 return -EFAULT; 123 if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) 124 return -EFAULT; 125 126 down_read(&uts_sem); 127 128 error = __copy_to_user(&name->sysname, &utsname()->sysname, 129 __OLD_UTS_LEN); 130 error |= __put_user(0, name->sysname + __OLD_UTS_LEN); 131 error |= __copy_to_user(&name->nodename, &utsname()->nodename, 132 __OLD_UTS_LEN); 133 error |= __put_user(0, name->nodename + __OLD_UTS_LEN); 134 error |= __copy_to_user(&name->release, &utsname()->release, 135 __OLD_UTS_LEN); 136 error |= __put_user(0, name->release + __OLD_UTS_LEN); 137 error |= __copy_to_user(&name->version, &utsname()->version, 138 __OLD_UTS_LEN); 139 error |= __put_user(0, name->version + __OLD_UTS_LEN); 140 error |= __copy_to_user(&name->machine, &utsname()->machine, 141 __OLD_UTS_LEN); 142 error |= __put_user(0, name->machine + __OLD_UTS_LEN); 143 144 up_read(&uts_sem); 145 146 error = error ? -EFAULT : 0; 147 148 return error; 149} 150 151int kernel_execve(const char *filename, char *const argv[], char *const envp[]) 152{ 153 mm_segment_t fs; 154 int ret; 155 156 fs = get_fs(); 157 set_fs(KERNEL_DS); 158 ret = um_execve(filename, argv, envp); 159 set_fs(fs); 160 161 return ret; 162} 163