add patch remove-redundant-assignment-to-node
[ext4-patch-queue.git] / enforce-immutable-flag-on-open-files
blob494eac440aee139308119418677450f190d75bb9
1 ext4: enforce the immutable flag on open files
3 According to the chattr man page, "a file with the 'i' attribute
4 cannot be modified..."  Historically, this was only enforced when the
5 file was opened, per the rest of the description, "... and the file
6 can not be opened in write mode".
8 There is general agreement that we should standardize all file systems
9 to prevent modifications even for files that were opened at the time
10 the immutable flag is set.  Eventually, a change to enforce this at
11 the VFS layer should be landing in mainline.  Until then, enforce this
12 at the ext4 level to prevent xfstests generic/553 from failing.
14 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
15 Cc: "Darrick J. Wong" <darrick.wong@oracle.com>
16 Cc: stable@kernel.org
17 ---
18  fs/ext4/file.c  |  4 ++++
19  fs/ext4/inode.c | 11 +++++++++++
20  2 files changed, 15 insertions(+)
22 diff --git a/fs/ext4/file.c b/fs/ext4/file.c
23 index 2c5baa5e8291..f4a24a46245e 100644
24 --- a/fs/ext4/file.c
25 +++ b/fs/ext4/file.c
26 @@ -165,6 +165,10 @@ static ssize_t ext4_write_checks(struct kiocb *iocb, struct iov_iter *from)
27         ret = generic_write_checks(iocb, from);
28         if (ret <= 0)
29                 return ret;
31 +       if (unlikely(IS_IMMUTABLE(inode)))
32 +               return -EPERM;
34         /*
35          * If we have encountered a bitmap-format file, the size limit
36          * is smaller than s_maxbytes, which is for extent-mapped files.
37 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
38 index c16071547c9c..ed1d8f9ce5f9 100644
39 --- a/fs/ext4/inode.c
40 +++ b/fs/ext4/inode.c
41 @@ -5520,6 +5520,14 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
42         if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
43                 return -EIO;
45 +       if (unlikely(IS_IMMUTABLE(inode)))
46 +               return -EPERM;
48 +       if (unlikely(IS_APPEND(inode) &&
49 +                    (ia_valid & (ATTR_MODE | ATTR_UID |
50 +                                 ATTR_GID | ATTR_TIMES_SET))))
51 +               return -EPERM;
53         error = setattr_prepare(dentry, attr);
54         if (error)
55                 return error;
56 @@ -6194,6 +6202,9 @@ vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf)
57         get_block_t *get_block;
58         int retries = 0;
60 +       if (unlikely(IS_IMMUTABLE(inode)))
61 +               return VM_FAULT_SIGBUS;
63         sb_start_pagefault(inode->i_sb);
64         file_update_time(vma->vm_file);