#include <linux/sched.h>
#include <linux/stat.h>
#include <linux/utime.h>
+#include <linux/syscalls.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#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.
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;
if (error)
goto out;
- dentry = nd.dentry;
+ dentry = nd.path.dentry;
}
inode = dentry->d_inode;
if (IS_IMMUTABLE(inode))
goto dput_and_out;
- if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) {
+ if (!is_owner_or_cap(inode)) {
if (f) {
if (!(f->f_mode & FMODE_WRITE))
goto dput_and_out;
if (f)
fput(f);
else
- path_release(&nd);
+ path_put(&nd.path);
out:
return error;
}