patch-2.1.101 linux/arch/mips/kernel/syscall.c

Next file: linux/arch/mips/kernel/syscalls.h
Previous file: linux/arch/mips/kernel/signal.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/syscall.c linux/arch/mips/kernel/syscall.c
@@ -11,7 +11,7 @@
  *        Don't waste that much memory for empty entries in the syscall
  *        table.
  *
- * $Id: syscall.c,v 1.4 1997/09/18 07:57:30 root Exp $
+ * $Id: syscall.c,v 1.11 1998/05/01 01:34:30 ralf Exp $
  */
 #undef CONF_PRINT_SYSCALLS
 #undef CONF_DEBUG_IRIX
@@ -23,11 +23,14 @@
 #include <linux/smp_lock.h>
 #include <linux/mman.h>
 #include <linux/sched.h>
+#include <linux/file.h>
 #include <linux/utsname.h>
 #include <linux/unistd.h>
 #include <asm/branch.h>
+#include <asm/offset.h>
 #include <asm/ptrace.h>
 #include <asm/signal.h>
+#include <asm/stackframe.h>
 #include <asm/uaccess.h>
 
 extern asmlinkage void syscall_trace(void);
@@ -37,7 +40,7 @@
 extern syscall_t sys_call_table[];
 extern unsigned char sys_narg_table[];
 
-asmlinkage int sys_pipe(struct pt_regs *regs)
+asmlinkage int sys_pipe(struct pt_regs regs)
 {
 	int fd[2];
 	int error, res;
@@ -48,7 +51,7 @@
 		res = error;
 		goto out;
 	}
-	regs->regs[3] = fd[1];
+	regs.regs[3] = fd[1];
 	res = fd[0];
 out:
 	unlock_kernel();
@@ -59,19 +62,22 @@
                                   int flags, int fd, off_t offset)
 {
 	struct file * file = NULL;
-	unsigned long res;
+	unsigned long error = -EFAULT;
 
 	lock_kernel();
 	if (!(flags & MAP_ANONYMOUS)) {
-		if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
-			return -EBADF;
-	}
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-
-	res = do_mmap(file, addr, len, prot, flags, offset);
-
+		error = -EBADF;
+		file = fget(fd);
+		if (!file)
+			goto out;
+	}
+        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+        error = do_mmap(file, addr, len, prot, flags, offset);
+        if (file)
+                fput(file);
+out:
 	unlock_kernel();
-	return res;
+	return error;
 }
 
 asmlinkage int sys_idle(void)
@@ -105,28 +111,30 @@
 	return ret;
 }
 
-asmlinkage int sys_fork(struct pt_regs *regs)
+asmlinkage int sys_fork(struct pt_regs regs)
 {
 	int res;
 
+	save_static(&regs);
 	lock_kernel();
-	res = do_fork(SIGCHLD, regs->regs[29], regs);
+	res = do_fork(SIGCHLD, regs.regs[29], &regs);
 	unlock_kernel();
 	return res;
 }
 
-asmlinkage int sys_clone(struct pt_regs *regs)
+asmlinkage int sys_clone(struct pt_regs regs)
 {
 	unsigned long clone_flags;
 	unsigned long newsp;
 	int res;
 
+	save_static(&regs);
 	lock_kernel();
-	clone_flags = regs->regs[4];
-	newsp = regs->regs[5];
+	clone_flags = regs.regs[4];
+	newsp = regs.regs[5];
 	if (!newsp)
-		newsp = regs->regs[29];
-	res = do_fork(clone_flags, newsp, regs);
+		newsp = regs.regs[29];
+	res = do_fork(clone_flags, newsp, &regs);
 	unlock_kernel();
 	return res;
 }
@@ -134,18 +142,18 @@
 /*
  * sys_execve() executes a new program.
  */
-asmlinkage int sys_execve(struct pt_regs *regs)
+asmlinkage int sys_execve(struct pt_regs regs)
 {
 	int error;
 	char * filename;
 
 	lock_kernel();
-	filename = getname((char *) (long)regs->regs[4]);
+	filename = getname((char *) (long)regs.regs[4]);
 	error = PTR_ERR(filename);
 	if (IS_ERR(filename))
 		goto out;
-	error = do_execve(filename, (char **) (long)regs->regs[5],
-	                  (char **) (long)regs->regs[6], regs);
+	error = do_execve(filename, (char **) (long)regs.regs[5],
+	                  (char **) (long)regs.regs[6], &regs);
 	putname(filename);
 
 out:
@@ -193,11 +201,13 @@
 /*
  * Do the indirect syscall syscall.
  * Don't care about kernel locking; the actual syscall will do it.
+ *
+ * XXX This is borken.
  */
-asmlinkage int sys_syscall(struct pt_regs *regs)
+asmlinkage int sys_syscall(struct pt_regs regs)
 {
 	syscall_t syscall;
-	unsigned long syscallnr = regs->regs[4];
+	unsigned long syscallnr = regs.regs[4];
 	unsigned long a0, a1, a2, a3, a4, a5, a6;
 	int nargs, errno;
 
@@ -219,7 +229,7 @@
 	}
 
 	if(nargs > 3) {
-		unsigned long usp = regs->regs[29];
+		unsigned long usp = regs.regs[29];
 		unsigned long *sp = (unsigned long *) usp;
 		if(usp & 3) {
 			printk("unaligned usp -EFAULT\n");
@@ -252,9 +262,9 @@
 	} else {
 		a3 = a4 = a5 = a6 = 0;
 	}
-	a0 = regs->regs[5]; a1 = regs->regs[6]; a2 = regs->regs[7];
+	a0 = regs.regs[5]; a1 = regs.regs[6]; a2 = regs.regs[7];
 	if(nargs == 0)
-		a0 = (unsigned long) regs;
+		a0 = (unsigned long) &regs;
 	return syscall((void *)a0, a1, a2, a3, a4, a5, a6);
 }
 
@@ -268,6 +278,9 @@
 	do_exit(SIGSEGV);
 }
 
+/*
+ * Build the string table for the builtin "poor man's strace".
+ */
 #ifdef CONF_PRINT_SYSCALLS
 #define SYS(fun, narg) #fun,
 static char *sfnames[] = {
@@ -281,146 +294,3 @@
 #include "irix5sys.h"
 };
 #endif
-
-/*
- * This isn't entirely correct with respect to kernel locking ...
- */
-void do_sys(struct pt_regs *regs)
-{
-	unsigned long syscallnr, usp;
-	syscall_t syscall;
-	int errno, narg;
-
-        /* Skip syscall instruction */
-	if (delay_slot(regs)) {
-		/*
-		 * By convention "li v0,<syscallno>" is always preceeding
-		 * the syscall instruction.  So if we're in a delay slot
-		 * userland is screwed up.
-		 */
-		force_sig(SIGILL, current);
-		return;
-	}
-	regs->cp0_epc += 4;
-
-	syscallnr = regs->regs[2];
-	if (syscallnr > (__NR_Linux + __NR_Linux_syscalls))
-		goto illegal_syscall;
-
-	syscall = sys_call_table[syscallnr];
-	if (syscall == NULL)
-		goto illegal_syscall;
-
-	narg = sys_narg_table[syscallnr];
-#ifdef CONF_PRINT_SYSCALLS
-	if(syscallnr >= 4000)
-		printk("do_sys(%s:%d): %s(%08lx,%08lx,%08lx,%08lx)<pc=%08lx>",
-		       current->comm, current->pid, sfnames[syscallnr - __NR_Linux],
-		       regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7],
-		       regs->cp0_epc);
-#endif
-#if defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX)
-	if(syscallnr < 2000 && syscallnr >= 1000) {
-		printk("irix_sys(%s:%d): %s(", current->comm,
-		       current->pid, irix_sys_names[syscallnr - 1000]);
-		if((narg < 4) && (narg != 0)) {
-			int i = 0;
-
-			while(i < (narg - 1)) {
-				printk("%08lx, ", regs->regs[i + 4]);
-				i++;
-			}
-			printk("%08lx) ", regs->regs[i + 4]);
-		} else if(narg == 0) {
-			printk("%08lx, %08lx, %08lx, %08lx) ",
-			       regs->regs[4], regs->regs[5], regs->regs[6],
-			       regs->regs[7]);
-		} else
-			printk("narg=%d) ", narg);
-	}
-#endif
-	if (narg > 4) {
-		/*
-		 * Verify that we can safely get the additional parameters
-		 * from the user stack.  Of course I could read the params
-		 * from unaligned addresses ...  Consider this a programming
-		 * course caliber .45.
-		 */
-		usp = regs->regs[29];
-		if (usp & 3) {
-			printk("unaligned usp\n");
-			force_sig(SIGSEGV, current);
-			regs->regs[2] = EFAULT;
-			regs->regs[7] = 1;
-			return;
-		}
-		if (!access_ok(VERIFY_READ, (void *) (usp + 16),
-		      (narg - 4) * sizeof(unsigned long))) {
-			regs->regs[2] = EFAULT;
-			regs->regs[7] = 1;
-			return;
-		}
-	}
-
-	if ((current->flags & PF_TRACESYS) == 0)
-	{
-		errno = do_syscalls(regs, syscall, narg);
-		if ((errno < 0 && errno > (-ENOIOCTLCMD - 1)) || current->errno) {
-			goto bad_syscall;
-		}
-		regs->regs[2] = errno;
-		regs->regs[7] = 0;
-	}
-	else
-	{
-		syscall_trace();
-
-		errno = do_syscalls(regs, syscall, narg);
-		if (errno < 0 || current->errno)
-		{
-			regs->regs[2] = -errno;
-			regs->regs[7] = 1;
-		}
-		else
-		{
-			regs->regs[2] = errno;
-			regs->regs[7] = 0;
-		}
-
-		syscall_trace();
-	}
-#if defined(CONF_PRINT_SYSCALLS) || \
-    (defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX))
-#if 0
-	printk(" returning: normal\n");
-#else
-	if(syscallnr >= 4000 && syscallnr < 5000)
-		printk(" returning: %08lx\n", (unsigned long) errno);
-#endif
-#endif
-	return;
-
-bad_syscall:
-	regs->regs[0] = regs->regs[2] = -errno;
-	regs->regs[7] = 1;
-#if defined(CONF_PRINT_SYSCALLS) || \
-    (defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX))
-#if 0
-	printk(" returning: bad_syscall\n");
-#else
-	if(syscallnr >= 4000 && syscallnr < 5000)
-		printk(" returning error: %d\n", errno);
-#endif
-#endif
-	return;
-illegal_syscall:
-
-	regs->regs[2] = ENOSYS;
-	regs->regs[7] = 1;
-#if defined(CONF_PRINT_SYSCALLS) || \
-    (defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX))
-	if(syscallnr >= 1000 && syscallnr < 2000)
-		printk(" returning: illegal_syscall\n");
-#endif
-	return;
-}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov