| From 02b016ca7f99229ae6227e7b2fc950c4e140d74a Mon Sep 17 00:00:00 2001 |
| From: Theodore Ts'o <tytso@mit.edu> |
| Date: Sun, 9 Jun 2019 22:04:33 -0400 |
| Subject: ext4: enforce the immutable flag on open files |
| |
| From: Theodore Ts'o <tytso@mit.edu> |
| |
| commit 02b016ca7f99229ae6227e7b2fc950c4e140d74a upstream. |
| |
| According to the chattr man page, "a file with the 'i' attribute |
| cannot be modified..." Historically, this was only enforced when the |
| file was opened, per the rest of the description, "... and the file |
| can not be opened in write mode". |
| |
| There is general agreement that we should standardize all file systems |
| to prevent modifications even for files that were opened at the time |
| the immutable flag is set. Eventually, a change to enforce this at |
| the VFS layer should be landing in mainline. Until then, enforce this |
| at the ext4 level to prevent xfstests generic/553 from failing. |
| |
| Signed-off-by: Theodore Ts'o <tytso@mit.edu> |
| Cc: "Darrick J. Wong" <darrick.wong@oracle.com> |
| Cc: stable@kernel.org |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/ext4/file.c | 4 ++++ |
| fs/ext4/inode.c | 11 +++++++++++ |
| 2 files changed, 15 insertions(+) |
| |
| --- a/fs/ext4/file.c |
| +++ b/fs/ext4/file.c |
| @@ -165,6 +165,10 @@ static ssize_t ext4_write_checks(struct |
| ret = generic_write_checks(iocb, from); |
| if (ret <= 0) |
| return ret; |
| + |
| + if (unlikely(IS_IMMUTABLE(inode))) |
| + return -EPERM; |
| + |
| /* |
| * If we have encountered a bitmap-format file, the size limit |
| * is smaller than s_maxbytes, which is for extent-mapped files. |
| --- a/fs/ext4/inode.c |
| +++ b/fs/ext4/inode.c |
| @@ -5514,6 +5514,14 @@ int ext4_setattr(struct dentry *dentry, |
| if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) |
| return -EIO; |
| |
| + if (unlikely(IS_IMMUTABLE(inode))) |
| + return -EPERM; |
| + |
| + if (unlikely(IS_APPEND(inode) && |
| + (ia_valid & (ATTR_MODE | ATTR_UID | |
| + ATTR_GID | ATTR_TIMES_SET)))) |
| + return -EPERM; |
| + |
| error = setattr_prepare(dentry, attr); |
| if (error) |
| return error; |
| @@ -6184,6 +6192,9 @@ vm_fault_t ext4_page_mkwrite(struct vm_f |
| get_block_t *get_block; |
| int retries = 0; |
| |
| + if (unlikely(IS_IMMUTABLE(inode))) |
| + return VM_FAULT_SIGBUS; |
| + |
| sb_start_pagefault(inode->i_sb); |
| file_update_time(vma->vm_file); |
| |