include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / arch / s390 / kernel / compat_linux.c
index 91b2884..73b624e 100644 (file)
 #include <linux/signal.h>
 #include <linux/resource.h>
 #include <linux/times.h>
-#include <linux/utsname.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
-#include <linux/slab.h>
 #include <linux/uio.h>
-#include <linux/nfs_fs.h>
 #include <linux/quota.h>
 #include <linux/module.h>
-#include <linux/sunrpc/svc.h>
-#include <linux/nfsd/nfsd.h>
-#include <linux/nfsd/cache.h>
-#include <linux/nfsd/xdr.h>
-#include <linux/nfsd/syscall.h>
 #include <linux/poll.h>
 #include <linux/personality.h>
 #include <linux/stat.h>
 #include <linux/vfs.h>
 #include <linux/ptrace.h>
 #include <linux/fadvise.h>
+#include <linux/ipc.h>
+#include <linux/slab.h>
 
 #include <asm/types.h>
-#include <asm/ipc.h>
 #include <asm/uaccess.h>
-#include <asm/semaphore.h>
 
 #include <net/scm.h>
 #include <net/sock.h>
 
 #include "compat_linux.h"
 
+long psw_user32_bits   = (PSW_BASE32_BITS | PSW_MASK_DAT | PSW_ASC_HOME |
+                          PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
+                          PSW_MASK_PSTATE | PSW_DEFAULT_KEY);
+long psw32_user_bits   = (PSW32_BASE_BITS | PSW32_MASK_DAT | PSW32_ASC_HOME |
+                          PSW32_MASK_IO | PSW32_MASK_EXT | PSW32_MASK_MCHECK |
+                          PSW32_MASK_PSTATE);
  
 /* For this source file, we want overflow handling. */
 
@@ -143,9 +141,9 @@ asmlinkage long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user
 {
        int retval;
 
-       if (!(retval = put_user(high2lowuid(current->uid), ruid)) &&
-           !(retval = put_user(high2lowuid(current->euid), euid)))
-               retval = put_user(high2lowuid(current->suid), suid);
+       if (!(retval = put_user(high2lowuid(current->cred->uid), ruid)) &&
+           !(retval = put_user(high2lowuid(current->cred->euid), euid)))
+               retval = put_user(high2lowuid(current->cred->suid), suid);
 
        return retval;
 }
@@ -160,9 +158,9 @@ asmlinkage long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user
 {
        int retval;
 
-       if (!(retval = put_user(high2lowgid(current->gid), rgid)) &&
-           !(retval = put_user(high2lowgid(current->egid), egid)))
-               retval = put_user(high2lowgid(current->sgid), sgid);
+       if (!(retval = put_user(high2lowgid(current->cred->gid), rgid)) &&
+           !(retval = put_user(high2lowgid(current->cred->egid), egid)))
+               retval = put_user(high2lowgid(current->cred->sgid), sgid);
 
        return retval;
 }
@@ -212,20 +210,20 @@ asmlinkage long sys32_getgroups16(int gidsetsize, u16 __user *grouplist)
        if (gidsetsize < 0)
                return -EINVAL;
 
-       get_group_info(current->group_info);
-       i = current->group_info->ngroups;
+       get_group_info(current->cred->group_info);
+       i = current->cred->group_info->ngroups;
        if (gidsetsize) {
                if (i > gidsetsize) {
                        i = -EINVAL;
                        goto out;
                }
-               if (groups16_to_user(grouplist, current->group_info)) {
+               if (groups16_to_user(grouplist, current->cred->group_info)) {
                        i = -EFAULT;
                        goto out;
                }
        }
 out:
-       put_group_info(current->group_info);
+       put_group_info(current->cred->group_info);
        return i;
 }
 
@@ -256,38 +254,22 @@ asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist)
 
 asmlinkage long sys32_getuid16(void)
 {
-       return high2lowuid(current->uid);
+       return high2lowuid(current->cred->uid);
 }
 
 asmlinkage long sys32_geteuid16(void)
 {
-       return high2lowuid(current->euid);
+       return high2lowuid(current->cred->euid);
 }
 
 asmlinkage long sys32_getgid16(void)
 {
-       return high2lowgid(current->gid);
+       return high2lowgid(current->cred->gid);
 }
 
 asmlinkage long sys32_getegid16(void)
 {
-       return high2lowgid(current->egid);
-}
-
-/* 32-bit timeval and related flotsam.  */
-
-static inline long get_tv32(struct timeval *o, struct compat_timeval __user *i)
-{
-       return (!access_ok(VERIFY_READ, o, sizeof(*o)) ||
-               (__get_user(o->tv_sec, &i->tv_sec) ||
-                __get_user(o->tv_usec, &i->tv_usec)));
-}
-
-static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
-{
-       return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
-               (__put_user(i->tv_sec, &o->tv_sec) ||
-                __put_user(i->tv_usec, &o->tv_usec)));
+       return high2lowgid(current->cred->egid);
 }
 
 /*
@@ -295,6 +277,7 @@ static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
  *
  * This is really horribly ugly.
  */
+#ifdef CONFIG_SYSVIPC
 asmlinkage long sys32_ipc(u32 call, int first, int second, int third, u32 ptr)
 {
        if (call >> 16)         /* hack for backward compatibility */
@@ -338,6 +321,7 @@ asmlinkage long sys32_ipc(u32 call, int first, int second, int third, u32 ptr)
 
        return -ENOSYS;
 }
+#endif
 
 asmlinkage long sys32_truncate64(const char __user * path, unsigned long high, unsigned long low)
 {
@@ -355,81 +339,6 @@ asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned
                return sys_ftruncate(fd, (high << 32) | low);
 }
 
-int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
-{
-       int err;
-
-       if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))
-               return -EOVERFLOW;
-
-       err = put_user(old_encode_dev(stat->dev), &statbuf->st_dev);
-       err |= put_user(stat->ino, &statbuf->st_ino);
-       err |= put_user(stat->mode, &statbuf->st_mode);
-       err |= put_user(stat->nlink, &statbuf->st_nlink);
-       err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid);
-       err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid);
-       err |= put_user(old_encode_dev(stat->rdev), &statbuf->st_rdev);
-       err |= put_user(stat->size, &statbuf->st_size);
-       err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);
-       err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
-       err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
-       err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
-       err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
-       err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
-       err |= put_user(stat->blksize, &statbuf->st_blksize);
-       err |= put_user(stat->blocks, &statbuf->st_blocks);
-/* fixme
-       err |= put_user(0, &statbuf->__unused4[0]);
-       err |= put_user(0, &statbuf->__unused4[1]);
-*/
-       return err;
-}
-
-struct sysinfo32 {
-        s32 uptime;
-        u32 loads[3];
-        u32 totalram;
-        u32 freeram;
-        u32 sharedram;
-        u32 bufferram;
-        u32 totalswap;
-        u32 freeswap;
-        unsigned short procs;
-       unsigned short pads;
-       u32 totalhigh;
-       u32 freehigh;
-       unsigned int mem_unit;
-        char _f[8];
-};
-
-asmlinkage long sys32_sysinfo(struct sysinfo32 __user *info)
-{
-       struct sysinfo s;
-       int ret, err;
-       mm_segment_t old_fs = get_fs ();
-       
-       set_fs (KERNEL_DS);
-       ret = sys_sysinfo((struct sysinfo __user *) &s);
-       set_fs (old_fs);
-       err = put_user (s.uptime, &info->uptime);
-       err |= __put_user (s.loads[0], &info->loads[0]);
-       err |= __put_user (s.loads[1], &info->loads[1]);
-       err |= __put_user (s.loads[2], &info->loads[2]);
-       err |= __put_user (s.totalram, &info->totalram);
-       err |= __put_user (s.freeram, &info->freeram);
-       err |= __put_user (s.sharedram, &info->sharedram);
-       err |= __put_user (s.bufferram, &info->bufferram);
-       err |= __put_user (s.totalswap, &info->totalswap);
-       err |= __put_user (s.freeswap, &info->freeswap);
-       err |= __put_user (s.procs, &info->procs);
-       err |= __put_user (s.totalhigh, &info->totalhigh);
-       err |= __put_user (s.freehigh, &info->freehigh);
-       err |= __put_user (s.mem_unit, &info->mem_unit);
-       if (err)
-               return -EFAULT;
-       return ret;
-}
-
 asmlinkage long sys32_sched_rr_get_interval(compat_pid_t pid,
                                struct compat_timespec __user *interval)
 {
@@ -438,7 +347,8 @@ asmlinkage long sys32_sched_rr_get_interval(compat_pid_t pid,
        mm_segment_t old_fs = get_fs ();
        
        set_fs (KERNEL_DS);
-       ret = sys_sched_rr_get_interval(pid, (struct timespec __user *) &t);
+       ret = sys_sched_rr_get_interval(pid,
+                                       (struct timespec __force __user *) &t);
        set_fs (old_fs);
        if (put_compat_timespec(&t, interval))
                return -EFAULT;
@@ -465,8 +375,8 @@ asmlinkage long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
        }
        set_fs (KERNEL_DS);
        ret = sys_rt_sigprocmask(how,
-                                set ? (sigset_t __user *) &s : NULL,
-                                oset ? (sigset_t __user *) &s : NULL,
+                                set ? (sigset_t __force __user *) &s : NULL,
+                                oset ? (sigset_t __force __user *) &s : NULL,
                                 sigsetsize);
        set_fs (old_fs);
        if (ret) return ret;
@@ -492,7 +402,7 @@ asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set,
        mm_segment_t old_fs = get_fs();
                
        set_fs (KERNEL_DS);
-       ret = sys_rt_sigpending((sigset_t __user *) &s, sigsetsize);
+       ret = sys_rt_sigpending((sigset_t __force __user *) &s, sigsetsize);
        set_fs (old_fs);
        if (!ret) {
                switch (_NSIG_WORDS) {
@@ -517,7 +427,7 @@ sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
        if (copy_siginfo_from_user32(&info, uinfo))
                return -EFAULT;
        set_fs (KERNEL_DS);
-       ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info);
+       ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __force __user *) &info);
        set_fs (old_fs);
        return ret;
 }
@@ -526,124 +436,26 @@ sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
  * sys32_execve() executes a new program after the asm stub has set
  * things up for us.  This should basically do what I want it to.
  */
-asmlinkage long
-sys32_execve(struct pt_regs regs)
-{
-        int error;
-        char * filename;
-
-        filename = getname(compat_ptr(regs.orig_gpr2));
-        error = PTR_ERR(filename);
-        if (IS_ERR(filename))
-                goto out;
-        error = compat_do_execve(filename, compat_ptr(regs.gprs[3]),
-                                compat_ptr(regs.gprs[4]), &regs);
-       if (error == 0)
-       {
-               task_lock(current);
-               current->ptrace &= ~PT_DTRACE;
-               task_unlock(current);
-               current->thread.fp_regs.fpc=0;
-               __asm__ __volatile__
-                       ("sr  0,0\n\t"
-                        "sfpc 0,0\n\t"
-                        : : :"0");
-       }
-        putname(filename);
+asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv,
+                            compat_uptr_t __user *envp)
+{
+       struct pt_regs *regs = task_pt_regs(current);
+       char *filename;
+       long rc;
+
+       filename = getname(name);
+       rc = PTR_ERR(filename);
+       if (IS_ERR(filename))
+               return rc;
+       rc = compat_do_execve(filename, argv, envp, regs);
+       if (rc)
+               goto out;
+       current->thread.fp_regs.fpc=0;
+       asm volatile("sfpc %0,0" : : "d" (0));
+       rc = regs->gprs[2];
 out:
-        return error;
-}
-
-
-#ifdef CONFIG_MODULES
-
-asmlinkage long
-sys32_init_module(void __user *umod, unsigned long len,
-               const char __user *uargs)
-{
-       return sys_init_module(umod, len, uargs);
-}
-
-asmlinkage long
-sys32_delete_module(const char __user *name_user, unsigned int flags)
-{
-       return sys_delete_module(name_user, flags);
-}
-
-#else /* CONFIG_MODULES */
-
-asmlinkage long
-sys32_init_module(void __user *umod, unsigned long len,
-               const char __user *uargs)
-{
-       return -ENOSYS;
-}
-
-asmlinkage long
-sys32_delete_module(const char __user *name_user, unsigned int flags)
-{
-       return -ENOSYS;
-}
-
-#endif  /* CONFIG_MODULES */
-
-/* Translations due to time_t size differences.  Which affects all
-   sorts of things, like timeval and itimerval.  */
-
-extern struct timezone sys_tz;
-
-asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
-{
-       if (tv) {
-               struct timeval ktv;
-               do_gettimeofday(&ktv);
-               if (put_tv32(tv, &ktv))
-                       return -EFAULT;
-       }
-       if (tz) {
-               if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
-                       return -EFAULT;
-       }
-       return 0;
-}
-
-static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
-{
-       long usec;
-
-       if (!access_ok(VERIFY_READ, i, sizeof(*i)))
-               return -EFAULT;
-       if (__get_user(o->tv_sec, &i->tv_sec))
-               return -EFAULT;
-       if (__get_user(usec, &i->tv_usec))
-               return -EFAULT;
-       o->tv_nsec = usec * 1000;
-       return 0;
-}
-
-asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
-{
-       struct timespec kts;
-       struct timezone ktz;
-
-       if (tv) {
-               if (get_ts32(&kts, tv))
-                       return -EFAULT;
-       }
-       if (tz) {
-               if (copy_from_user(&ktz, tz, sizeof(ktz)))
-                       return -EFAULT;
-       }
-
-       return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
-}
-
-/* These are here just in case some old sparc32 binary calls it. */
-asmlinkage long sys32_pause(void)
-{
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       return -ERESTARTNOHAND;
+       putname(filename);
+       return rc;
 }
 
 asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf,
@@ -678,7 +490,7 @@ asmlinkage long sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offse
                
        set_fs(KERNEL_DS);
        ret = sys_sendfile(out_fd, in_fd,
-                          offset ? (off_t __user *) &of : NULL, count);
+                          offset ? (off_t __force __user *) &of : NULL, count);
        set_fs(old_fs);
        
        if (offset && put_user(of, offset))
@@ -699,7 +511,8 @@ asmlinkage long sys32_sendfile64(int out_fd, int in_fd,
                
        set_fs(KERNEL_DS);
        ret = sys_sendfile64(out_fd, in_fd,
-                            offset ? (loff_t __user *) &lof : NULL, count);
+                            offset ? (loff_t __force __user *) &lof : NULL,
+                            count);
        set_fs(old_fs);
        
        if (offset && put_user(lof, offset))
@@ -708,57 +521,6 @@ asmlinkage long sys32_sendfile64(int out_fd, int in_fd,
        return ret;
 }
 
-#ifdef CONFIG_SYSCTL_SYSCALL
-struct __sysctl_args32 {
-       u32 name;
-       int nlen;
-       u32 oldval;
-       u32 oldlenp;
-       u32 newval;
-       u32 newlen;
-       u32 __unused[4];
-};
-
-asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
-{
-       struct __sysctl_args32 tmp;
-       int error;
-       size_t oldlen;
-       size_t __user *oldlenp = NULL;
-       unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7;
-
-       if (copy_from_user(&tmp, args, sizeof(tmp)))
-               return -EFAULT;
-
-       if (tmp.oldval && tmp.oldlenp) {
-               /* Duh, this is ugly and might not work if sysctl_args
-                  is in read-only memory, but do_sysctl does indirectly
-                  a lot of uaccess in both directions and we'd have to
-                  basically copy the whole sysctl.c here, and
-                  glibc's __sysctl uses rw memory for the structure
-                  anyway.  */
-               if (get_user(oldlen, (u32 __user *)compat_ptr(tmp.oldlenp)) ||
-                   put_user(oldlen, (size_t __user *)addr))
-                       return -EFAULT;
-               oldlenp = (size_t __user *)addr;
-       }
-
-       lock_kernel();
-       error = do_sysctl(compat_ptr(tmp.name), tmp.nlen, compat_ptr(tmp.oldval),
-                         oldlenp, compat_ptr(tmp.newval), tmp.newlen);
-       unlock_kernel();
-       if (oldlenp) {
-               if (!error) {
-                       if (get_user(oldlen, (size_t __user *)addr) ||
-                           put_user(oldlen, (u32 __user *)compat_ptr(tmp.oldlenp)))
-                               error = -EFAULT;
-               }
-               copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
-       }
-       return error;
-}
-#endif
-
 struct stat64_emu31 {
        unsigned long long  st_dev;
        unsigned int    __pad1;
@@ -839,20 +601,12 @@ asmlinkage long sys32_fstatat64(unsigned int dfd, char __user *filename,
                                struct stat64_emu31 __user* statbuf, int flag)
 {
        struct kstat stat;
-       int error = -EINVAL;
-
-       if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
-               goto out;
-
-       if (flag & AT_SYMLINK_NOFOLLOW)
-               error = vfs_lstat_fd(dfd, filename, &stat);
-       else
-               error = vfs_stat_fd(dfd, filename, &stat);
+       int error;
 
-       if (!error)
-               error = cp_stat64(statbuf, &stat);
-out:
-       return error;
+       error = vfs_fstatat(dfd, filename, &stat, flag);
+       if (error)
+               return error;
+       return cp_stat64(statbuf, &stat);
 }
 
 /*
@@ -862,75 +616,35 @@ out:
  */
 
 struct mmap_arg_struct_emu31 {
-       u32     addr;
-       u32     len;
-       u32     prot;
-       u32     flags;
-       u32     fd;
-       u32     offset;
+       compat_ulong_t addr;
+       compat_ulong_t len;
+       compat_ulong_t prot;
+       compat_ulong_t flags;
+       compat_ulong_t fd;
+       compat_ulong_t offset;
 };
 
-/* common code for old and new mmaps */
-static inline long do_mmap2(
-       unsigned long addr, unsigned long len,
-       unsigned long prot, unsigned long flags,
-       unsigned long fd, unsigned long pgoff)
-{
-       struct file * file = NULL;
-       unsigned long error = -EBADF;
-
-       flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-       if (!(flags & MAP_ANONYMOUS)) {
-               file = fget(fd);
-               if (!file)
-                       goto out;
-       }
-
-       down_write(&current->mm->mmap_sem);
-       error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-       if (!IS_ERR((void *) error) && error + len >= 0x80000000ULL) {
-               /* Result is out of bounds.  */
-               do_munmap(current->mm, addr, len);
-               error = -ENOMEM;
-       }
-       up_write(&current->mm->mmap_sem);
-
-       if (file)
-               fput(file);
-out:    
-       return error;
-}
-
-
-asmlinkage unsigned long
-old32_mmap(struct mmap_arg_struct_emu31 __user *arg)
+asmlinkage unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg)
 {
        struct mmap_arg_struct_emu31 a;
-       int error = -EFAULT;
 
        if (copy_from_user(&a, arg, sizeof(a)))
-               goto out;
-
-       error = -EINVAL;
+               return -EFAULT;
        if (a.offset & ~PAGE_MASK)
-               goto out;
-
-       error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); 
-out:
-       return error;
+               return -EINVAL;
+       a.addr = (unsigned long) compat_ptr(a.addr);
+       return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
+                             a.offset >> PAGE_SHIFT);
 }
 
-asmlinkage long 
-sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg)
+asmlinkage long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg)
 {
        struct mmap_arg_struct_emu31 a;
-       int error = -EFAULT;
 
        if (copy_from_user(&a, arg, sizeof(a)))
-               goto out;
-       error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
-out:
-       return error;
+               return -EFAULT;
+       a.addr = (unsigned long) compat_ptr(a.addr);
+       return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
 }
 
 asmlinkage long sys32_read(unsigned int fd, char __user * buf, size_t count)
@@ -949,22 +663,6 @@ asmlinkage long sys32_write(unsigned int fd, char __user * buf, size_t count)
        return sys_write(fd, buf, count);
 }
 
-asmlinkage long sys32_clone(struct pt_regs regs)
-{
-        unsigned long clone_flags;
-        unsigned long newsp;
-       int __user *parent_tidptr, *child_tidptr;
-
-        clone_flags = regs.gprs[3] & 0xffffffffUL;
-        newsp = regs.orig_gpr2 & 0x7fffffffUL;
-       parent_tidptr = compat_ptr(regs.gprs[4]);
-       child_tidptr = compat_ptr(regs.gprs[5]);
-        if (!newsp)
-                newsp = regs.gprs[15];
-        return do_fork(clone_flags, newsp, &regs, 0,
-                      parent_tidptr, child_tidptr);
-}
-
 /*
  * 31 bit emulation wrapper functions for sys_fadvise64/fadvise64_64.
  * These need to rewrite the advise values for POSIX_FADV_{DONTNEED,NOREUSE}