nfsd: move some of fh_compose into helper functions
[safe/jmp/linux-2.6] / fs / compat.c
index e04b466..94502da 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/smb_mount.h>
 #include <linux/ncp_mount.h>
 #include <linux/nfs4_mount.h>
-#include <linux/smp_lock.h>
 #include <linux/syscalls.h>
 #include <linux/ctype.h>
 #include <linux/module.h>
@@ -51,6 +50,7 @@
 #include <linux/poll.h>
 #include <linux/mm.h>
 #include <linux/eventpoll.h>
+#include <linux/fs_struct.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -180,22 +180,24 @@ asmlinkage long compat_sys_newstat(char __user * filename,
                struct compat_stat __user *statbuf)
 {
        struct kstat stat;
-       int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
+       int error;
 
-       if (!error)
-               error = cp_compat_stat(&stat, statbuf);
-       return error;
+       error = vfs_stat(filename, &stat);
+       if (error)
+               return error;
+       return cp_compat_stat(&stat, statbuf);
 }
 
 asmlinkage long compat_sys_newlstat(char __user * filename,
                struct compat_stat __user *statbuf)
 {
        struct kstat stat;
-       int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
+       int error;
 
-       if (!error)
-               error = cp_compat_stat(&stat, statbuf);
-       return error;
+       error = vfs_lstat(filename, &stat);
+       if (error)
+               return error;
+       return cp_compat_stat(&stat, statbuf);
 }
 
 #ifndef __ARCH_WANT_STAT64
@@ -203,21 +205,12 @@ asmlinkage long compat_sys_newfstatat(unsigned int dfd, char __user *filename,
                struct compat_stat __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);
-
-       if (!error)
-               error = cp_compat_stat(&stat, statbuf);
+       int error;
 
-out:
-       return error;
+       error = vfs_fstatat(dfd, filename, &stat, flag);
+       if (error)
+               return error;
+       return cp_compat_stat(&stat, statbuf);
 }
 #endif
 
@@ -477,7 +470,7 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
                ret = sys_fcntl(fd, cmd, (unsigned long)&f);
                set_fs(old_fs);
                if (cmd == F_GETLK && ret == 0) {
-                       /* GETLK was successfule and we need to return the data...
+                       /* GETLK was successful and we need to return the data...
                         * but it needs to fit in the compat structure.
                         * l_start shouldn't be too big, unless the original
                         * start + end is greater than COMPAT_OFF_T_MAX, in which
@@ -818,10 +811,8 @@ asmlinkage long compat_sys_mount(char __user * dev_name, char __user * dir_name,
                }
        }
 
-       lock_kernel();
        retval = do_mount((char*)dev_page, dir_page, (char*)type_page,
                        flags, (void*)data_page);
-       unlock_kernel();
 
  out4:
        free_page(data_page);
@@ -1222,13 +1213,33 @@ compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec,
                 unsigned long vlen)
 {
        struct file *file;
+       int fput_needed;
        ssize_t ret;
 
-       file = fget(fd);
+       file = fget_light(fd, &fput_needed);
        if (!file)
                return -EBADF;
        ret = compat_readv(file, vec, vlen, &file->f_pos);
-       fput(file);
+       fput_light(file, fput_needed);
+       return ret;
+}
+
+asmlinkage ssize_t
+compat_sys_preadv(unsigned long fd, const struct compat_iovec __user *vec,
+                 unsigned long vlen, u32 pos_low, u32 pos_high)
+{
+       loff_t pos = ((loff_t)pos_high << 32) | pos_low;
+       struct file *file;
+       int fput_needed;
+       ssize_t ret;
+
+       if (pos < 0)
+               return -EINVAL;
+       file = fget_light(fd, &fput_needed);
+       if (!file)
+               return -EBADF;
+       ret = compat_readv(file, vec, vlen, &pos);
+       fput_light(file, fput_needed);
        return ret;
 }
 
@@ -1259,13 +1270,33 @@ compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec,
                  unsigned long vlen)
 {
        struct file *file;
+       int fput_needed;
        ssize_t ret;
 
-       file = fget(fd);
+       file = fget_light(fd, &fput_needed);
        if (!file)
                return -EBADF;
        ret = compat_writev(file, vec, vlen, &file->f_pos);
-       fput(file);
+       fput_light(file, fput_needed);
+       return ret;
+}
+
+asmlinkage ssize_t
+compat_sys_pwritev(unsigned long fd, const struct compat_iovec __user *vec,
+                  unsigned long vlen, u32 pos_low, u32 pos_high)
+{
+       loff_t pos = ((loff_t)pos_high << 32) | pos_low;
+       struct file *file;
+       int fput_needed;
+       ssize_t ret;
+
+       if (pos < 0)
+               return -EINVAL;
+       file = fget_light(fd, &fput_needed);
+       if (!file)
+               return -EBADF;
+       ret = compat_writev(file, vec, vlen, &pos);
+       fput_light(file, fput_needed);
        return ret;
 }
 
@@ -1442,6 +1473,7 @@ int compat_do_execve(char * filename,
        struct linux_binprm *bprm;
        struct file *file;
        struct files_struct *displaced;
+       bool clear_in_exec;
        int retval;
 
        retval = unshare_files(&displaced);
@@ -1453,8 +1485,8 @@ int compat_do_execve(char * filename,
        if (!bprm)
                goto out_files;
 
-       retval = mutex_lock_interruptible(&current->cred_exec_mutex);
-       if (retval < 0)
+       retval = -ERESTARTNOINTR;
+       if (mutex_lock_interruptible(&current->cred_guard_mutex))
                goto out_free;
        current->in_execve = 1;
 
@@ -1462,12 +1494,16 @@ int compat_do_execve(char * filename,
        bprm->cred = prepare_exec_creds();
        if (!bprm->cred)
                goto out_unlock;
-       check_unsafe_exec(bprm);
+
+       retval = check_unsafe_exec(bprm);
+       if (retval < 0)
+               goto out_unlock;
+       clear_in_exec = retval;
 
        file = open_exec(filename);
        retval = PTR_ERR(file);
        if (IS_ERR(file))
-               goto out_unlock;
+               goto out_unmark;
 
        sched_exec();
 
@@ -1509,8 +1545,9 @@ int compat_do_execve(char * filename,
                goto out;
 
        /* execve succeeded */
+       current->fs->in_exec = 0;
        current->in_execve = 0;
-       mutex_unlock(&current->cred_exec_mutex);
+       mutex_unlock(&current->cred_guard_mutex);
        acct_update_integrals(current);
        free_bprm(bprm);
        if (displaced)
@@ -1527,9 +1564,13 @@ out_file:
                fput(bprm->file);
        }
 
+out_unmark:
+       if (clear_in_exec)
+               current->fs->in_exec = 0;
+
 out_unlock:
        current->in_execve = 0;
-       mutex_unlock(&current->cred_exec_mutex);
+       mutex_unlock(&current->cred_guard_mutex);
 
 out_free:
        free_bprm(bprm);