]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
fs/ntfs3: Exclude call make_bad_inode for live nodes.
authorKonstantin Komarov <almaz.alexandrovich@paragon-software.com>
Tue, 24 Jun 2025 13:35:39 +0000 (16:35 +0300)
committerKonstantin Komarov <almaz.alexandrovich@paragon-software.com>
Mon, 7 Jul 2025 12:35:46 +0000 (14:35 +0200)
Use ntfs_inode field 'ni_bad' to mark inode as bad (if something went wrong)
and to avoid any operations

Suggested-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3/file.c
fs/ntfs3/frecord.c
fs/ntfs3/fsntfs.c
fs/ntfs3/inode.c
fs/ntfs3/namei.c
fs/ntfs3/ntfs_fs.h
fs/ntfs3/xattr.c

index 1e99a35691cdfc52072c17275e5571c4d7b3920d..65fb27d1e17cdacaae439f86e85f90ac11524782 100644 (file)
@@ -57,6 +57,10 @@ long ntfs_ioctl(struct file *filp, u32 cmd, unsigned long arg)
        struct inode *inode = file_inode(filp);
        struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info;
 
+       /* Avoid any operation if inode is bad. */
+       if (unlikely(is_bad_ni(ntfs_i(inode))))
+               return -EINVAL;
+
        switch (cmd) {
        case FITRIM:
                return ntfs_ioctl_fitrim(sbi, arg);
@@ -81,6 +85,10 @@ int ntfs_getattr(struct mnt_idmap *idmap, const struct path *path,
        struct inode *inode = d_inode(path->dentry);
        struct ntfs_inode *ni = ntfs_i(inode);
 
+       /* Avoid any operation if inode is bad. */
+       if (unlikely(is_bad_ni(ni)))
+               return -EINVAL;
+
        stat->result_mask |= STATX_BTIME;
        stat->btime = ni->i_crtime;
        stat->blksize = ni->mi.sbi->cluster_size; /* 512, 1K, ..., 2M */
@@ -271,6 +279,10 @@ static int ntfs_file_mmap(struct file *file, struct vm_area_struct *vma)
        bool rw = vma->vm_flags & VM_WRITE;
        int err;
 
+       /* Avoid any operation if inode is bad. */
+       if (unlikely(is_bad_ni(ni)))
+               return -EINVAL;
+
        if (unlikely(ntfs3_forced_shutdown(inode->i_sb)))
                return -EIO;
 
@@ -735,6 +747,10 @@ int ntfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
        umode_t mode = inode->i_mode;
        int err;
 
+       /* Avoid any operation if inode is bad. */
+       if (unlikely(is_bad_ni(ni)))
+               return -EINVAL;
+
        if (unlikely(ntfs3_forced_shutdown(inode->i_sb)))
                return -EIO;
 
@@ -795,6 +811,10 @@ static int check_read_restriction(struct inode *inode)
 {
        struct ntfs_inode *ni = ntfs_i(inode);
 
+       /* Avoid any operation if inode is bad. */
+       if (unlikely(is_bad_ni(ni)))
+               return -EINVAL;
+
        if (unlikely(ntfs3_forced_shutdown(inode->i_sb)))
                return -EIO;
 
@@ -1130,6 +1150,10 @@ static int check_write_restriction(struct inode *inode)
 {
        struct ntfs_inode *ni = ntfs_i(inode);
 
+       /* Avoid any operation if inode is bad. */
+       if (unlikely(is_bad_ni(ni)))
+               return -EINVAL;
+
        if (unlikely(ntfs3_forced_shutdown(inode->i_sb)))
                return -EIO;
 
@@ -1212,6 +1236,10 @@ int ntfs_file_open(struct inode *inode, struct file *file)
 {
        struct ntfs_inode *ni = ntfs_i(inode);
 
+       /* Avoid any operation if inode is bad. */
+       if (unlikely(is_bad_ni(ni)))
+               return -EINVAL;
+
        if (unlikely(ntfs3_forced_shutdown(inode->i_sb)))
                return -EIO;
 
@@ -1281,6 +1309,10 @@ int ntfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
        int err;
        struct ntfs_inode *ni = ntfs_i(inode);
 
+       /* Avoid any operation if inode is bad. */
+       if (unlikely(is_bad_ni(ni)))
+               return -EINVAL;
+
        err = fiemap_prep(inode, fieinfo, start, &len, ~FIEMAP_FLAG_XATTR);
        if (err)
                return err;
index 37826288fbb042ab23df50491ca604e072401c83..8f9fe1d7a69081ed57e11d2ffe207873d8c8c656 100644 (file)
@@ -3208,6 +3208,10 @@ int ni_write_inode(struct inode *inode, int sync, const char *hint)
        if (is_bad_inode(inode) || sb_rdonly(sb))
                return 0;
 
+       /* Avoid any operation if inode is bad. */
+       if (unlikely(is_bad_ni(ni)))
+               return -EINVAL;
+
        if (unlikely(ntfs3_forced_shutdown(sb)))
                return -EIO;
 
index df81f1f7330cf97df7ce2788e79733c2a62aedbd..c7a2f191254dad5beab8e8a46587e44936fef51b 100644 (file)
@@ -905,9 +905,13 @@ void ntfs_update_mftmirr(struct ntfs_sb_info *sbi, int wait)
 void ntfs_bad_inode(struct inode *inode, const char *hint)
 {
        struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info;
+       struct ntfs_inode *ni = ntfs_i(inode);
 
        ntfs_inode_err(inode, "%s", hint);
-       make_bad_inode(inode);
+
+       /* Do not call make_bad_inode()! */
+       ni->ni_bad = true;
+
        /* Avoid recursion if bad inode is $Volume. */
        if (inode->i_ino != MFT_REC_VOL &&
            !(sbi->flags & NTFS_FLAGS_LOG_REPLAYING)) {
index 8bfe354776544b4f7f96a0fbc07fe7ffac81da05..4f9020df8912dbb4498c25c8eb5799b06bd1b24d 100644 (file)
@@ -878,6 +878,10 @@ static int ntfs_resident_writepage(struct folio *folio,
        struct ntfs_inode *ni = ntfs_i(inode);
        int ret;
 
+       /* Avoid any operation if inode is bad. */
+       if (unlikely(is_bad_ni(ni)))
+               return -EINVAL;
+
        if (unlikely(ntfs3_forced_shutdown(inode->i_sb)))
                return -EIO;
 
@@ -896,6 +900,10 @@ static int ntfs_writepages(struct address_space *mapping,
 {
        struct inode *inode = mapping->host;
 
+       /* Avoid any operation if inode is bad. */
+       if (unlikely(is_bad_ni(ntfs_i(inode))))
+               return -EINVAL;
+
        if (unlikely(ntfs3_forced_shutdown(inode->i_sb)))
                return -EIO;
 
@@ -919,6 +927,10 @@ int ntfs_write_begin(struct file *file, struct address_space *mapping,
        struct inode *inode = mapping->host;
        struct ntfs_inode *ni = ntfs_i(inode);
 
+       /* Avoid any operation if inode is bad. */
+       if (unlikely(is_bad_ni(ni)))
+               return -EINVAL;
+
        if (unlikely(ntfs3_forced_shutdown(inode->i_sb)))
                return -EIO;
 
@@ -1265,6 +1277,12 @@ int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
                goto out1;
        }
 
+       /* Avoid any operation if inode is bad. */
+       if (unlikely(is_bad_ni(dir_ni))) {
+               err = -EINVAL;
+               goto out2;
+       }
+
        if (unlikely(ntfs3_forced_shutdown(sb))) {
                err = -EIO;
                goto out2;
index 0db7ca3b64ead55d4de6eeb1fe0263819375a358..82c8ae56beee6d79046dd6c8f02ff0f35e9a1ad3 100644 (file)
@@ -171,6 +171,10 @@ static int ntfs_unlink(struct inode *dir, struct dentry *dentry)
        struct ntfs_inode *ni = ntfs_i(dir);
        int err;
 
+       /* Avoid any operation if inode is bad. */
+       if (unlikely(is_bad_ni(ni)))
+               return -EINVAL;
+
        if (unlikely(ntfs3_forced_shutdown(dir->i_sb)))
                return -EIO;
 
@@ -191,6 +195,10 @@ static int ntfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
 {
        u32 size = strlen(symname);
 
+       /* Avoid any operation if inode is bad. */
+       if (unlikely(is_bad_ni(ntfs_i(dir))))
+               return -EINVAL;
+
        if (unlikely(ntfs3_forced_shutdown(dir->i_sb)))
                return -EIO;
 
@@ -216,6 +224,10 @@ static int ntfs_rmdir(struct inode *dir, struct dentry *dentry)
        struct ntfs_inode *ni = ntfs_i(dir);
        int err;
 
+       /* Avoid any operation if inode is bad. */
+       if (unlikely(is_bad_ni(ni)))
+               return -EINVAL;
+
        if (unlikely(ntfs3_forced_shutdown(dir->i_sb)))
                return -EIO;
 
@@ -256,6 +268,10 @@ static int ntfs_rename(struct mnt_idmap *idmap, struct inode *dir,
                      1024);
        static_assert(PATH_MAX >= 4 * 1024);
 
+       /* Avoid any operation if inode is bad. */
+       if (unlikely(is_bad_ni(ni)))
+               return -EINVAL;
+
        if (unlikely(ntfs3_forced_shutdown(sb)))
                return -EIO;
 
index 7fde06019ac6e2113c3010fbe6f8f09de025cf5e..9a25fec25f01070f6df0ed058db64e92ac0e20ed 100644 (file)
@@ -377,6 +377,13 @@ struct ntfs_inode {
         */
        u8 mi_loaded;
 
+       /* 
+        * Use this field to avoid any write(s).
+        * If inode is bad during initialization - use make_bad_inode
+        * If inode is bad during operations - use this field
+        */
+       u8 ni_bad;
+
        union {
                struct ntfs_index dir;
                struct {
@@ -1024,6 +1031,11 @@ static inline bool is_compressed(const struct ntfs_inode *ni)
               (ni->ni_flags & NI_FLAG_COMPRESSED_MASK);
 }
 
+static inline bool is_bad_ni(const struct ntfs_inode *ni)
+{
+       return ni->ni_bad;
+}
+
 static inline int ni_ext_compress_bits(const struct ntfs_inode *ni)
 {
        return 0xb + (ni->ni_flags & NI_FLAG_COMPRESSED_MASK);
index 4bf14cff2683eb650287290ae7f81b4d6f103a6c..e519e21596a708dcc1f8b234fcabc68de6ef41e6 100644 (file)
@@ -552,6 +552,10 @@ struct posix_acl *ntfs_get_acl(struct mnt_idmap *idmap, struct dentry *dentry,
        int err;
        void *buf;
 
+       /* Avoid any operation if inode is bad. */
+       if (unlikely(is_bad_ni(ni)))
+               return ERR_PTR(-EINVAL);
+
        /* Allocate PATH_MAX bytes. */
        buf = __getname();
        if (!buf)
@@ -600,6 +604,10 @@ static noinline int ntfs_set_acl_ex(struct mnt_idmap *idmap,
        int flags;
        umode_t mode;
 
+       /* Avoid any operation if inode is bad. */
+       if (unlikely(is_bad_ni(ntfs_i(inode))))
+               return -EINVAL;
+
        if (S_ISLNK(inode->i_mode))
                return -EOPNOTSUPP;
 
@@ -730,6 +738,10 @@ ssize_t ntfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
        struct ntfs_inode *ni = ntfs_i(inode);
        ssize_t ret;
 
+       /* Avoid any operation if inode is bad. */
+       if (unlikely(is_bad_ni(ni)))
+               return -EINVAL;
+
        if (!(ni->ni_flags & NI_FLAG_EA)) {
                /* no xattr in file */
                return 0;
@@ -751,6 +763,10 @@ static int ntfs_getxattr(const struct xattr_handler *handler, struct dentry *de,
        int err;
        struct ntfs_inode *ni = ntfs_i(inode);
 
+       /* Avoid any operation if inode is bad. */
+       if (unlikely(is_bad_ni(ni)))
+               return -EINVAL;
+
        if (unlikely(ntfs3_forced_shutdown(inode->i_sb)))
                return -EIO;