X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fum%2Fsys-i386%2Fsyscalls.c;h=710d5fb807e1d6b9ae7e24e7542814aa36b69348;hb=refs%2Fheads%2Fvserver;hp=6ad31749bfe72133957a89002771549b6a8afb66;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/arch/um/sys-i386/syscalls.c b/arch/um/sys-i386/syscalls.c index 6ad31749b..710d5fb80 100644 --- a/arch/um/sys-i386/syscalls.c +++ b/arch/um/sys-i386/syscalls.c @@ -1,9 +1,11 @@ /* - * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ #include "linux/sched.h" +#include "linux/shm.h" +#include "asm/ipc.h" #include "asm/mman.h" #include "asm/uaccess.h" #include "asm/unistd.h" @@ -28,7 +30,7 @@ extern int old_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long offset); -int old_mmap_i386(struct mmap_arg_struct *arg) +long old_mmap_i386(struct mmap_arg_struct __user *arg) { struct mmap_arg_struct a; int err = -EFAULT; @@ -43,11 +45,13 @@ int old_mmap_i386(struct mmap_arg_struct *arg) struct sel_arg_struct { unsigned long n; - fd_set *inp, *outp, *exp; - struct timeval *tvp; + fd_set __user *inp; + fd_set __user *outp; + fd_set __user *exp; + struct timeval __user *tvp; }; -int old_select(struct sel_arg_struct *arg) +long old_select(struct sel_arg_struct __user *arg) { struct sel_arg_struct a; @@ -57,34 +61,142 @@ int old_select(struct sel_arg_struct *arg) return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); } -/* The i386 version skips reading from %esi, the fourth argument. So we must do - * this, too. +/* + * The prototype on i386 is: + * + * int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr) + * + * and the "newtls" arg. on i386 is read by copy_thread directly from the + * register saved on the stack. */ -int sys_clone(unsigned long clone_flags, unsigned long newsp, int *parent_tid, - int unused, int *child_tid) +long sys_clone(unsigned long clone_flags, unsigned long newsp, + int __user *parent_tid, void *newtls, int __user *child_tid) { long ret; - /* XXX: normal arch do here this pass, and also pass the regs to - * do_fork, instead of NULL. Currently the arch-independent code - * ignores these values, while the UML code (actually it's - * copy_thread) does the right thing. But this should change, - probably. */ - /*if (!newsp) - newsp = UPT_SP(current->thread.regs);*/ + if (!newsp) + newsp = UPT_SP(¤t->thread.regs.regs); + current->thread.forking = 1; - ret = do_fork(clone_flags, newsp, NULL, 0, parent_tid, child_tid); + ret = do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid, + child_tid); current->thread.forking = 0; - return(ret); + return ret; } /* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: + * sys_ipc() is the de-multiplexer for the SysV IPC calls.. + * + * This is really horribly ugly. */ +long sys_ipc (uint call, int first, int second, + int third, void __user *ptr, long fifth) +{ + int version, ret; + + version = call >> 16; /* hack for backward compatibility */ + call &= 0xffff; + + switch (call) { + case SEMOP: + return sys_semtimedop(first, (struct sembuf __user *) ptr, + second, NULL); + case SEMTIMEDOP: + return sys_semtimedop(first, (struct sembuf __user *) ptr, + second, + (const struct timespec __user *) fifth); + case SEMGET: + return sys_semget (first, second, third); + case SEMCTL: { + union semun fourth; + if (!ptr) + return -EINVAL; + if (get_user(fourth.__pad, (void __user * __user *) ptr)) + return -EFAULT; + return sys_semctl (first, second, third, fourth); + } + + case MSGSND: + return sys_msgsnd (first, (struct msgbuf *) ptr, + second, third); + case MSGRCV: + switch (version) { + case 0: { + struct ipc_kludge tmp; + if (!ptr) + return -EINVAL; + + if (copy_from_user(&tmp, + (struct ipc_kludge *) ptr, + sizeof (tmp))) + return -EFAULT; + return sys_msgrcv (first, tmp.msgp, second, + tmp.msgtyp, third); + } + default: + panic("msgrcv with version != 0"); + return sys_msgrcv (first, + (struct msgbuf *) ptr, + second, fifth, third); + } + case MSGGET: + return sys_msgget ((key_t) first, second); + case MSGCTL: + return sys_msgctl (first, second, (struct msqid_ds *) ptr); + + case SHMAT: + switch (version) { + default: { + ulong raddr; + ret = do_shmat (first, (char *) ptr, second, &raddr); + if (ret) + return ret; + return put_user (raddr, (ulong *) third); + } + case 1: /* iBCS2 emulator entry point */ + if (!segment_eq(get_fs(), get_ds())) + return -EINVAL; + return do_shmat (first, (char *) ptr, second, (ulong *) third); + } + case SHMDT: + return sys_shmdt ((char *)ptr); + case SHMGET: + return sys_shmget (first, second, third); + case SHMCTL: + return sys_shmctl (first, second, + (struct shmid_ds *) ptr); + default: + return -ENOSYS; + } +} + +long sys_sigaction(int sig, const struct old_sigaction __user *act, + struct old_sigaction __user *oact) +{ + struct k_sigaction new_ka, old_ka; + int ret; + + if (act) { + old_sigset_t mask; + if (!access_ok(VERIFY_READ, act, sizeof(*act)) || + __get_user(new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) + return -EFAULT; + __get_user(new_ka.sa.sa_flags, &act->sa_flags); + __get_user(mask, &act->sa_mask); + siginitset(&new_ka.sa.sa_mask, mask); + } + + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { + if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) + return -EFAULT; + __put_user(old_ka.sa.sa_flags, &oact->sa_flags); + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); + } + + return ret; +}