]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ext4: enforce the immutable flag on open files
authorTheodore Ts'o <tytso@mit.edu>
Mon, 10 Jun 2019 02:04:33 +0000 (22:04 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Mon, 10 Jun 2019 02:04:33 +0000 (22:04 -0400)
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
fs/ext4/file.c
fs/ext4/inode.c

index 2c5baa5e8291165e07d5609b650c38c13eda587f..f4a24a46245eacebf90e771bf34defc8019bc792 100644 (file)
@@ -165,6 +165,10 @@ static ssize_t ext4_write_checks(struct kiocb *iocb, struct iov_iter *from)
        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.
index c16071547c9c4530881e4e21b1bb1e910a2c1640..ed1d8f9ce5f986a7c7c44980c6dbfd3eb80db18a 100644 (file)
@@ -5520,6 +5520,14 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
        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;
@@ -6194,6 +6202,9 @@ vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf)
        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);