syscall.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:6k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * This file is subject to the terms and conditions of the GNU General Public
  3.  * License.  See the file "COPYING" in the main directory of this archive
  4.  * for more details.
  5.  *
  6.  * Copyright (C) 1995 - 2000 by Ralf Baechle
  7.  * Copyright (C) 2000 Silicon Graphics, Inc.
  8.  *
  9.  * TODO:  Implement the compatibility syscalls.
  10.  *        Don't waste that much memory for empty entries in the syscall
  11.  *        table.
  12.  */
  13. #undef CONF_PRINT_SYSCALLS
  14. #undef CONF_DEBUG_IRIX
  15. #include <linux/config.h>
  16. #include <linux/linkage.h>
  17. #include <linux/mm.h>
  18. #include <linux/smp.h>
  19. #include <linux/smp_lock.h>
  20. #include <linux/mman.h>
  21. #include <linux/sched.h>
  22. #include <linux/file.h>
  23. #include <linux/slab.h>
  24. #include <linux/utsname.h>
  25. #include <linux/unistd.h>
  26. #include <asm/branch.h>
  27. #include <asm/offset.h>
  28. #include <asm/ptrace.h>
  29. #include <asm/signal.h>
  30. #include <asm/stackframe.h>
  31. #include <asm/uaccess.h>
  32. extern asmlinkage void syscall_trace(void);
  33. typedef asmlinkage int (*syscall_t)(void *a0,...);
  34. extern asmlinkage int (*do_syscalls)(struct pt_regs *regs, syscall_t fun,
  35.      int narg);
  36. extern syscall_t sys_call_table[];
  37. extern unsigned char sys_narg_table[];
  38. asmlinkage int sys_pipe(struct pt_regs regs)
  39. {
  40. int fd[2];
  41. int error, res;
  42. error = do_pipe(fd);
  43. if (error) {
  44. res = error;
  45. goto out;
  46. }
  47. regs.regs[3] = fd[1];
  48. res = fd[0];
  49. out:
  50. return res;
  51. }
  52. /* common code for old and new mmaps */
  53. static inline long
  54. do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
  55.         unsigned long flags, unsigned long fd, unsigned long pgoff)
  56. {
  57. int error = -EBADF;
  58. struct file * file = NULL;
  59. flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
  60. if (!(flags & MAP_ANONYMOUS)) {
  61. file = fget(fd);
  62. if (!file)
  63. goto out;
  64. }
  65. down_write(&current->mm->mmap_sem);
  66. error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
  67. up_write(&current->mm->mmap_sem);
  68. if (file)
  69. fput(file);
  70. out:
  71. return error;
  72. }
  73. asmlinkage unsigned long old_mmap(unsigned long addr, size_t len, int prot,
  74.                                   int flags, int fd, off_t offset)
  75. {
  76. return do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
  77. }
  78. asmlinkage long
  79. sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
  80.           unsigned long flags, unsigned long fd, unsigned long pgoff)
  81. {
  82. return do_mmap2(addr, len, prot, flags, fd, pgoff);
  83. }
  84. save_static_function(sys_fork);
  85. static_unused int _sys_fork(struct pt_regs regs)
  86. {
  87. int res;
  88. res = do_fork(SIGCHLD, regs.regs[29], &regs, 0);
  89. return res;
  90. }
  91. save_static_function(sys_clone);
  92. static_unused int _sys_clone(struct pt_regs regs)
  93. {
  94. unsigned long clone_flags;
  95. unsigned long newsp;
  96. int res;
  97. clone_flags = regs.regs[4];
  98. newsp = regs.regs[5];
  99. if (!newsp)
  100. newsp = regs.regs[29];
  101. res = do_fork(clone_flags, newsp, &regs, 0);
  102. return res;
  103. }
  104. /*
  105.  * sys_execve() executes a new program.
  106.  */
  107. asmlinkage int sys_execve(struct pt_regs regs)
  108. {
  109. int error;
  110. char * filename;
  111. filename = getname((char *) (long)regs.regs[4]);
  112. error = PTR_ERR(filename);
  113. if (IS_ERR(filename))
  114. goto out;
  115. error = do_execve(filename, (char **) (long)regs.regs[5],
  116.                   (char **) (long)regs.regs[6], &regs);
  117. putname(filename);
  118. out:
  119. return error;
  120. }
  121. /*
  122.  * Compacrapability ...
  123.  */
  124. asmlinkage int sys_uname(struct old_utsname * name)
  125. {
  126. if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
  127. return 0;
  128. return -EFAULT;
  129. }
  130. /*
  131.  * Compacrapability ...
  132.  */
  133. asmlinkage int sys_olduname(struct oldold_utsname * name)
  134. {
  135. int error;
  136. if (!name)
  137. return -EFAULT;
  138. if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
  139. return -EFAULT;
  140.   
  141. error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
  142. error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
  143. error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
  144. error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
  145. error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
  146. error -= __put_user(0,name->release+__OLD_UTS_LEN);
  147. error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
  148. error -= __put_user(0,name->version+__OLD_UTS_LEN);
  149. error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
  150. error = __put_user(0,name->machine+__OLD_UTS_LEN);
  151. error = error ? -EFAULT : 0;
  152. return error;
  153. }
  154. /*
  155.  * Do the indirect syscall syscall.
  156.  * Don't care about kernel locking; the actual syscall will do it.
  157.  *
  158.  * XXX This is borken.
  159.  */
  160. asmlinkage int sys_syscall(struct pt_regs regs)
  161. {
  162. syscall_t syscall;
  163. unsigned long syscallnr = regs.regs[4];
  164. unsigned long a0, a1, a2, a3, a4, a5, a6;
  165. int nargs, errno;
  166. if (syscallnr > __NR_Linux + __NR_Linux_syscalls)
  167. return -ENOSYS;
  168. syscall = sys_call_table[syscallnr];
  169. nargs = sys_narg_table[syscallnr];
  170. /*
  171.  * Prevent stack overflow by recursive
  172.  * syscall(__NR_syscall, __NR_syscall,...);
  173.  */
  174. if (syscall == (syscall_t) sys_syscall) {
  175. return -EINVAL;
  176. }
  177. if (syscall == NULL) {
  178. return -ENOSYS;
  179. }
  180. if(nargs > 3) {
  181. unsigned long usp = regs.regs[29];
  182. unsigned long *sp = (unsigned long *) usp;
  183. if(usp & 3) {
  184. printk("unaligned usp -EFAULTn");
  185. force_sig(SIGSEGV, current);
  186. return -EFAULT;
  187. }
  188. errno = verify_area(VERIFY_READ, (void *) (usp + 16),
  189.                     (nargs - 3) * sizeof(unsigned long));
  190. if(errno) {
  191. return -EFAULT;
  192. }
  193. switch(nargs) {
  194. case 7:
  195. a3 = sp[4]; a4 = sp[5]; a5 = sp[6]; a6 = sp[7];
  196. break;
  197. case 6:
  198. a3 = sp[4]; a4 = sp[5]; a5 = sp[6]; a6 = 0;
  199. break;
  200. case 5:
  201. a3 = sp[4]; a4 = sp[5]; a5 = a6 = 0;
  202. break;
  203. case 4:
  204. a3 = sp[4]; a4 = a5 = a6 = 0;
  205. break;
  206. default:
  207. a3 = a4 = a5 = a6 = 0;
  208. break;
  209. }
  210. } else {
  211. a3 = a4 = a5 = a6 = 0;
  212. }
  213. a0 = regs.regs[5]; a1 = regs.regs[6]; a2 = regs.regs[7];
  214. if(nargs == 0)
  215. a0 = (unsigned long) &regs;
  216. return syscall((void *)a0, a1, a2, a3, a4, a5, a6);
  217. }
  218. /*
  219.  * If we ever come here the user sp is bad.  Zap the process right away.
  220.  * Due to the bad stack signaling wouldn't work.
  221.  * XXX kernel locking???
  222.  */
  223. asmlinkage void bad_stack(void)
  224. {
  225. do_exit(SIGSEGV);
  226. }
  227. /*
  228.  * Build the string table for the builtin "poor man's strace".
  229.  */
  230. #ifdef CONF_PRINT_SYSCALLS
  231. #define SYS(fun, narg) #fun,
  232. static char *sfnames[] = {
  233. #include "syscalls.h"
  234. };
  235. #endif
  236. #if defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX)
  237. #define SYS(fun, narg) #fun,
  238. static char *irix_sys_names[] = {
  239. #include "irix5sys.h"
  240. };
  241. #endif