From: Ethan Benson 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. 25-akpm/fs/open.c | 16 ++++++++++++++++ 1 files changed, 16 insertions(+) diff -puN fs/open.c~utime-on-immutable-file-fix fs/open.c --- 25/fs/open.c~utime-on-immutable-file-fix Thu Sep 4 11:14:12 2003 +++ 25-akpm/fs/open.c Thu Sep 4 11:14:12 2003 @@ -354,6 +354,10 @@ asmlinkage long sys_utime(char __user * /* 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, ×->actime); newattrs.ia_atime.tv_nsec = 0; if (!error) @@ -364,6 +368,10 @@ asmlinkage long sys_utime(char __user * 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, s /* 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; _