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
- Lines: 329
- Date:
Fri May 8 00:13:24 1998
- Orig file:
v2.1.100/linux/arch/mips/kernel/syscall.c
- Orig date:
Wed Dec 10 10:31:10 1997
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(®s);
lock_kernel();
- res = do_fork(SIGCHLD, regs->regs[29], regs);
+ res = do_fork(SIGCHLD, regs.regs[29], ®s);
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(®s);
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, ®s);
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], ®s);
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) ®s;
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