futex: Fix the write access fault problem for real
[safe/jmp/linux-2.6] / fs / compat.c
index 440a019..cdd51a3 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
 
@@ -477,7 +471,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 +812,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);
@@ -1235,7 +1227,7 @@ compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec,
 
 asmlinkage ssize_t
 compat_sys_preadv(unsigned long fd, const struct compat_iovec __user *vec,
-                 unsigned long vlen, u32 pos_high, u32 pos_low)
+                 unsigned long vlen, u32 pos_low, u32 pos_high)
 {
        loff_t pos = ((loff_t)pos_high << 32) | pos_low;
        struct file *file;
@@ -1292,7 +1284,7 @@ compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec,
 
 asmlinkage ssize_t
 compat_sys_pwritev(unsigned long fd, const struct compat_iovec __user *vec,
-                  unsigned long vlen, u32 pos_high, u32 pos_low)
+                  unsigned long vlen, u32 pos_low, u32 pos_high)
 {
        loff_t pos = ((loff_t)pos_high << 32) | pos_low;
        struct file *file;
@@ -1482,6 +1474,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);
@@ -1493,7 +1486,7 @@ int compat_do_execve(char * filename,
        if (!bprm)
                goto out_files;
 
-       retval = mutex_lock_interruptible(&current->cred_exec_mutex);
+       retval = mutex_lock_interruptible(&current->cred_guard_mutex);
        if (retval < 0)
                goto out_free;
        current->in_execve = 1;
@@ -1502,12 +1495,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();
 
@@ -1549,8 +1546,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)
@@ -1567,9 +1565,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);