PCI Hotplug: cpqphp: clean up accesses to pcibios_get_irq_routing_table()
[safe/jmp/linux-2.6] / fs / compat.c
index e04b466..681ed81 100644 (file)
@@ -51,6 +51,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 +181,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 +206,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
 
@@ -1222,13 +1216,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 +1273,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 +1476,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);
@@ -1462,12 +1497,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,6 +1548,7 @@ 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);
        acct_update_integrals(current);
@@ -1527,6 +1567,10 @@ 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);