ACPICA: Fixed a problem with CopyObject used in conjunction with the Index operator
[safe/jmp/linux-2.6] / fs / utimes.c
index 480f7c8..b18da9c 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/sched.h>
 #include <linux/stat.h>
 #include <linux/utime.h>
+#include <linux/syscalls.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 
@@ -38,6 +39,14 @@ asmlinkage long sys_utime(char __user *filename, struct utimbuf __user *times)
 
 #endif
 
+static bool nsec_valid(long nsec)
+{
+       if (nsec == UTIME_OMIT || nsec == UTIME_NOW)
+               return true;
+
+       return nsec >= 0 && nsec <= 999999999;
+}
+
 /* If times==NULL, set access and modification to current time,
  * must be owner or have write permission.
  * Else, update from *times, must be owner or super user.
@@ -52,6 +61,11 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
        struct file *f = NULL;
 
        error = -EINVAL;
+       if (times && (!nsec_valid(times[0].tv_nsec) ||
+                     !nsec_valid(times[1].tv_nsec))) {
+               goto out;
+       }
+
        if (flags & ~AT_SYMLINK_NOFOLLOW)
                goto out;
 
@@ -70,7 +84,7 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
                if (error)
                        goto out;
 
-               dentry = nd.dentry;
+               dentry = nd.path.dentry;
        }
 
        inode = dentry->d_inode;
@@ -106,9 +120,16 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
                 if (IS_IMMUTABLE(inode))
                         goto dput_and_out;
 
-               if (current->fsuid != inode->i_uid &&
-                   (error = vfs_permission(&nd, MAY_WRITE)) != 0)
-                       goto dput_and_out;
+               if (!is_owner_or_cap(inode)) {
+                       if (f) {
+                               if (!(f->f_mode & FMODE_WRITE))
+                                       goto dput_and_out;
+                       } else {
+                               error = vfs_permission(&nd, MAY_WRITE);
+                               if (error)
+                                       goto dput_and_out;
+                       }
+               }
        }
        mutex_lock(&inode->i_mutex);
        error = notify_change(dentry, &newattrs);
@@ -117,7 +138,7 @@ dput_and_out:
        if (f)
                fput(f);
        else
-               path_release(&nd);
+               path_put(&nd.path);
 out:
        return error;
 }