Blame SOURCES/0054-exfat-fix-use-of-uninitialized-spinlock-on-error-pat.patch

Kmods SIG 9e3ffb
From 8ff006e57ad3a25f909c456d053aa498b6673a39 Mon Sep 17 00:00:00 2001
Kmods SIG 9e3ffb
From: Namjae Jeon <namjae.jeon@samsung.com>
Kmods SIG 9e3ffb
Date: Tue, 29 Sep 2020 09:09:49 +0900
Kmods SIG 9e3ffb
Subject: [Backport 8ff006e57ad3] exfat: fix use of uninitialized spinlock on
Kmods SIG 9e3ffb
 error path
Kmods SIG 9e3ffb
Kmods SIG 9e3ffb
syzbot reported warning message:
Kmods SIG 9e3ffb
Kmods SIG 9e3ffb
Call Trace:
Kmods SIG 9e3ffb
 __dump_stack lib/dump_stack.c:77 [inline]
Kmods SIG 9e3ffb
 dump_stack+0x1d6/0x29e lib/dump_stack.c:118
Kmods SIG 9e3ffb
 register_lock_class+0xf06/0x1520 kernel/locking/lockdep.c:893
Kmods SIG 9e3ffb
 __lock_acquire+0xfd/0x2ae0 kernel/locking/lockdep.c:4320
Kmods SIG 9e3ffb
 lock_acquire+0x148/0x720 kernel/locking/lockdep.c:5029
Kmods SIG 9e3ffb
 __raw_spin_lock include/linux/spinlock_api_smp.h:142 [inline]
Kmods SIG 9e3ffb
 _raw_spin_lock+0x2a/0x40 kernel/locking/spinlock.c:151
Kmods SIG 9e3ffb
 spin_lock include/linux/spinlock.h:354 [inline]
Kmods SIG 9e3ffb
 exfat_cache_inval_inode+0x30/0x280 src/cache.c:226
Kmods SIG 9e3ffb
 exfat_evict_inode+0x124/0x270 src/inode.c:660
Kmods SIG 9e3ffb
 evict+0x2bb/0x6d0 fs/inode.c:576
Kmods SIG 9e3ffb
 exfat_fill_super+0x1e07/0x27d0 src/super.c:681
Kmods SIG 9e3ffb
 get_tree_bdev+0x3e9/0x5f0 fs/super.c:1342
Kmods SIG 9e3ffb
 vfs_get_tree+0x88/0x270 fs/super.c:1547
Kmods SIG 9e3ffb
 do_new_mount fs/namespace.c:2875 [inline]
Kmods SIG 9e3ffb
 path_mount+0x179d/0x29e0 fs/namespace.c:3192
Kmods SIG 9e3ffb
 do_mount fs/namespace.c:3205 [inline]
Kmods SIG 9e3ffb
 __do_sys_mount fs/namespace.c:3413 [inline]
Kmods SIG 9e3ffb
 __se_sys_mount+0x126/0x180 fs/namespace.c:3390
Kmods SIG 9e3ffb
 do_syscall_64+0x31/0x70 arch/x86/entry/common.c:46
Kmods SIG 9e3ffb
 entry_SYSCALL_64_after_hwframe+0x44/0xa9
Kmods SIG 9e3ffb
Kmods SIG 9e3ffb
If exfat_read_root() returns an error, spinlock is used in
Kmods SIG 9e3ffb
exfat_evict_inode() without initialization. This patch combines
Kmods SIG 9e3ffb
exfat_cache_init_inode() with exfat_inode_init_once() to initialize
Kmods SIG 9e3ffb
spinlock by slab constructor.
Kmods SIG 9e3ffb
Kmods SIG 9e3ffb
Fixes: c35b6810c495 ("exfat: add exfat cache")
Kmods SIG 9e3ffb
Cc: stable@vger.kernel.org # v5.7+
Kmods SIG 9e3ffb
Reported-by: syzbot <syzbot+b91107320911a26c9a95@syzkaller.appspotmail.com>
Kmods SIG 9e3ffb
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
Kmods SIG 9e3ffb
---
Kmods SIG 9e3ffb
 src/cache.c    | 11 -----------
Kmods SIG 9e3ffb
 src/exfat_fs.h |  3 ++-
Kmods SIG 9e3ffb
 src/inode.c    |  2 --
Kmods SIG 9e3ffb
 src/super.c    |  5 ++++-
Kmods SIG 9e3ffb
 4 files changed, 6 insertions(+), 15 deletions(-)
Kmods SIG 9e3ffb
Kmods SIG 9e3ffb
diff --git a/src/cache.c b/src/cache.c
Kmods SIG 9e3ffb
index 03d0824fc368a5b10241082e271dd4bfefd26ada..5a2f119b7e8c79c6e6c917dd66f12b10acef00b5 100644
Kmods SIG 9e3ffb
--- a/src/cache.c
Kmods SIG 9e3ffb
+++ b/src/cache.c
Kmods SIG 9e3ffb
@@ -17,7 +17,6 @@
Kmods SIG 9e3ffb
 #include "exfat_raw.h"
Kmods SIG 9e3ffb
 #include "exfat_fs.h"
Kmods SIG 9e3ffb
 
Kmods SIG 9e3ffb
-#define EXFAT_CACHE_VALID	0
Kmods SIG 9e3ffb
 #define EXFAT_MAX_CACHE		16
Kmods SIG 9e3ffb
 
Kmods SIG 9e3ffb
 struct exfat_cache {
Kmods SIG 9e3ffb
@@ -61,16 +60,6 @@ void exfat_cache_shutdown(void)
Kmods SIG 9e3ffb
 	kmem_cache_destroy(exfat_cachep);
Kmods SIG 9e3ffb
 }
Kmods SIG 9e3ffb
 
Kmods SIG 9e3ffb
-void exfat_cache_init_inode(struct inode *inode)
Kmods SIG 9e3ffb
-{
Kmods SIG 9e3ffb
-	struct exfat_inode_info *ei = EXFAT_I(inode);
Kmods SIG 9e3ffb
-
Kmods SIG 9e3ffb
-	spin_lock_init(&ei->cache_lru_lock);
Kmods SIG 9e3ffb
-	ei->nr_caches = 0;
Kmods SIG 9e3ffb
-	ei->cache_valid_id = EXFAT_CACHE_VALID + 1;
Kmods SIG 9e3ffb
-	INIT_LIST_HEAD(&ei->cache_lru);
Kmods SIG 9e3ffb
-}
Kmods SIG 9e3ffb
-
Kmods SIG 9e3ffb
 static inline struct exfat_cache *exfat_cache_alloc(void)
Kmods SIG 9e3ffb
 {
Kmods SIG 9e3ffb
 	return kmem_cache_alloc(exfat_cachep, GFP_NOFS);
Kmods SIG 9e3ffb
diff --git a/src/exfat_fs.h b/src/exfat_fs.h
Kmods SIG 9e3ffb
index 95d717f8620cd06cd29909ca07a17208dfd12325..c013fe931d9c17aaed61c75d0d9c41e67cd67907 100644
Kmods SIG 9e3ffb
--- a/src/exfat_fs.h
Kmods SIG 9e3ffb
+++ b/src/exfat_fs.h
Kmods SIG 9e3ffb
@@ -248,6 +248,8 @@ struct exfat_sb_info {
Kmods SIG 9e3ffb
 	struct rcu_head rcu;
Kmods SIG 9e3ffb
 };
Kmods SIG 9e3ffb
 
Kmods SIG 9e3ffb
+#define EXFAT_CACHE_VALID	0
Kmods SIG 9e3ffb
+
Kmods SIG 9e3ffb
 /*
Kmods SIG 9e3ffb
  * EXFAT file system inode in-memory data
Kmods SIG 9e3ffb
  */
Kmods SIG 9e3ffb
@@ -428,7 +430,6 @@ extern const struct dentry_operations exfat_utf8_dentry_ops;
Kmods SIG 9e3ffb
 /* cache.c */
Kmods SIG 9e3ffb
 int exfat_cache_init(void);
Kmods SIG 9e3ffb
 void exfat_cache_shutdown(void);
Kmods SIG 9e3ffb
-void exfat_cache_init_inode(struct inode *inode);
Kmods SIG 9e3ffb
 void exfat_cache_inval_inode(struct inode *inode);
Kmods SIG 9e3ffb
 int exfat_get_cluster(struct inode *inode, unsigned int cluster,
Kmods SIG 9e3ffb
 		unsigned int *fclus, unsigned int *dclus,
Kmods SIG 9e3ffb
diff --git a/src/inode.c b/src/inode.c
Kmods SIG 9e3ffb
index 7f90204adef53027dd1eb4348141394af5548b1b..a6de17cac3dfd5566832da7cbabb5635bb186a1a 100644
Kmods SIG 9e3ffb
--- a/src/inode.c
Kmods SIG 9e3ffb
+++ b/src/inode.c
Kmods SIG 9e3ffb
@@ -611,8 +611,6 @@ static int exfat_fill_inode(struct inode *inode, struct exfat_dir_entry *info)
Kmods SIG 9e3ffb
 	ei->i_crtime = info->crtime;
Kmods SIG 9e3ffb
 	inode->i_atime = info->atime;
Kmods SIG 9e3ffb
 
Kmods SIG 9e3ffb
-	exfat_cache_init_inode(inode);
Kmods SIG 9e3ffb
-
Kmods SIG 9e3ffb
 	return 0;
Kmods SIG 9e3ffb
 }
Kmods SIG 9e3ffb
 
Kmods SIG 9e3ffb
diff --git a/src/super.c b/src/super.c
Kmods SIG 9e3ffb
index 3b6a1659892ffd6ee3a94f6aa0f8bfca65fba9ae..60b941ba557b41fae3ea6b16b3041c3aecdc2b93 100644
Kmods SIG 9e3ffb
--- a/src/super.c
Kmods SIG 9e3ffb
+++ b/src/super.c
Kmods SIG 9e3ffb
@@ -376,7 +376,6 @@ static int exfat_read_root(struct inode *inode)
Kmods SIG 9e3ffb
 	inode->i_mtime = inode->i_atime = inode->i_ctime = ei->i_crtime =
Kmods SIG 9e3ffb
 		current_time(inode);
Kmods SIG 9e3ffb
 	exfat_truncate_atime(&inode->i_atime);
Kmods SIG 9e3ffb
-	exfat_cache_init_inode(inode);
Kmods SIG 9e3ffb
 	return 0;
Kmods SIG 9e3ffb
 }
Kmods SIG 9e3ffb
 
Kmods SIG 9e3ffb
@@ -763,6 +762,10 @@ static void exfat_inode_init_once(void *foo)
Kmods SIG 9e3ffb
 {
Kmods SIG 9e3ffb
 	struct exfat_inode_info *ei = (struct exfat_inode_info *)foo;
Kmods SIG 9e3ffb
 
Kmods SIG 9e3ffb
+	spin_lock_init(&ei->cache_lru_lock);
Kmods SIG 9e3ffb
+	ei->nr_caches = 0;
Kmods SIG 9e3ffb
+	ei->cache_valid_id = EXFAT_CACHE_VALID + 1;
Kmods SIG 9e3ffb
+	INIT_LIST_HEAD(&ei->cache_lru);
Kmods SIG 9e3ffb
 	INIT_HLIST_NODE(&ei->i_hash_fat);
Kmods SIG 9e3ffb
 	inode_init_once(&ei->vfs_inode);
Kmods SIG 9e3ffb
 }
Kmods SIG 9e3ffb
-- 
Kmods SIG 9e3ffb
2.31.1
Kmods SIG 9e3ffb