]> git.hungrycats.org Git - linux/commitdiff
[PATCH] disallow utime{s}() on immutable or append-only files
authorAndrew Morton <akpm@osdl.org>
Tue, 23 Sep 2003 16:43:18 +0000 (09:43 -0700)
committerLinus Torvalds <torvalds@home.osdl.org>
Tue, 23 Sep 2003 16:43:18 +0000 (09:43 -0700)
From: Ethan Benson <erbenson@alaska.net>

Currently Linux allows the use of the utime() and utimes() syscalls on
immutable or append-only files, this is incorrect.

utime{s}() is not supposed to work if you lack write access to a file,
in the case of an immutable file NOBODY has write access.

for an append-only file it only makes sense to be able to update its
time to present, not the past.

I have checked BSD, and they implement the behavior I propose, for
immutable files utime() and utimes() fail.  for append-only files they
fail if the time argument is not NULL.

fs/open.c

index 4cdbbcae8da17c81d5e703968a41309fbf93f875..b5550e9049af4b9007eac732d55672553699ed3e 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -354,6 +354,10 @@ asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times)
        /* Don't worry, the checks are done in inode_change_ok() */
        newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
        if (times) {
+               error = -EPERM;
+               if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+                       goto dput_and_out;
+
                error = get_user(newattrs.ia_atime.tv_sec, &times->actime);
                newattrs.ia_atime.tv_nsec = 0;
                if (!error) 
@@ -364,6 +368,10 @@ asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times)
 
                newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
        } else {
+                error = -EACCES;
+                if (IS_IMMUTABLE(inode))
+                        goto dput_and_out;
+
                if (current->fsuid != inode->i_uid &&
                    (error = permission(inode,MAY_WRITE,&nd)) != 0)
                        goto dput_and_out;
@@ -403,12 +411,20 @@ long do_utimes(char __user * filename, struct timeval * times)
        /* Don't worry, the checks are done in inode_change_ok() */
        newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
        if (times) {
+               error = -EPERM;
+                if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+                        goto dput_and_out;
+
                newattrs.ia_atime.tv_sec = times[0].tv_sec;
                newattrs.ia_atime.tv_nsec = times[0].tv_usec * 1000;
                newattrs.ia_mtime.tv_sec = times[1].tv_sec;
                newattrs.ia_mtime.tv_nsec = times[1].tv_usec * 1000;
                newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
        } else {
+               error = -EACCES;
+                if (IS_IMMUTABLE(inode))
+                        goto dput_and_out;
+
                if (current->fsuid != inode->i_uid &&
                    (error = permission(inode,MAY_WRITE,&nd)) != 0)
                        goto dput_and_out;