diff mbox series

fs: jffs2: fix possible sleep-in-atomic-context bugs

Message ID 20191217135143.12875-1-baijiaju1990@gmail.com
State New
Delegated to: David Woodhouse
Headers show
Series fs: jffs2: fix possible sleep-in-atomic-context bugs | expand

Commit Message

Jia-Ju Bai Dec. 17, 2019, 1:51 p.m. UTC
The filesystem may sleep while holding a spinlock.
The function call path (from bottom to top) in Linux 4.19 is:

fs/jffs2/malloc.c, 188: 
	kmem_cache_alloc(GFP_KERNEL) in jffs2_alloc_refblock
fs/jffs2/malloc.c, 221: 
	jffs2_alloc_refblock in jffs2_prealloc_raw_node_refs
fs/jffs2/wbuf.c, 164: 
	jffs2_prealloc_raw_node_refs in jffs2_block_refile
fs/jffs2/wbuf.c, 291: 
	jffs2_block_refile in jffs2_wbuf_recover
fs/jffs2/wbuf.c, 287: 
	spin_lock in jffs2_wbuf_recover

fs/jffs2/malloc.c, 188: 
    kmem_cache_alloc(GFP_KERNEL) in jffs2_alloc_refblock
fs/jffs2/malloc.c, 221: 
    jffs2_alloc_refblock in jffs2_prealloc_raw_node_refs
fs/jffs2/wbuf.c, 164: 
    jffs2_prealloc_raw_node_refs in jffs2_block_refile
fs/jffs2/wbuf.c, 927: 
	jffs2_block_refile in jffs2_flash_writev
fs/jffs2/wbuf.c, 924: 
	spin_lock in jffs2_flash_writev

kmem_cache_alloc(GFP_KERNEL) can sleep at runtime.

To fix these possible bugs, GFP_KERNEL is replaced with GFP_ATOMIC for
kmem_cache_alloc().

These bugs are found by a static analysis tool STCheck written by myself.

Signed-off-by: Jia-Ju Bai <baijiaju1990@gmail.com>
---
 fs/jffs2/malloc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Al Viro Dec. 26, 2019, 10:48 p.m. UTC | #1
On Tue, Dec 17, 2019 at 09:51:43PM +0800, Jia-Ju Bai wrote:
> The filesystem may sleep while holding a spinlock.
> The function call path (from bottom to top) in Linux 4.19 is:
> 
> fs/jffs2/malloc.c, 188: 
> 	kmem_cache_alloc(GFP_KERNEL) in jffs2_alloc_refblock
> fs/jffs2/malloc.c, 221: 
> 	jffs2_alloc_refblock in jffs2_prealloc_raw_node_refs

... gets called only if jeb->last_node is NULL.  I've no idea
whether it is possible on those call chains and analysis is
certainly needed before applying that kind of patches.

It might very well be real, and certainly worth asking jffs2
folks to look into.  But this kind of "defensive" fixes
is no good without understanding of the situation in the
code being (hopefully) fixed.

It's a good catch; even if there is a reason why we never
hit the blocking allocation in there, that reason should be
spelled out in the code.  It isn't, and that can easily
grow into a bug even if it hasn't done so already.
diff mbox series

Patch

diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c
index ce1189793288..66496ef09716 100644
--- a/fs/jffs2/malloc.c
+++ b/fs/jffs2/malloc.c
@@ -185,7 +185,7 @@  static struct jffs2_raw_node_ref *jffs2_alloc_refblock(void)
 {
 	struct jffs2_raw_node_ref *ret;
 
-	ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL);
+	ret = kmem_cache_alloc(raw_node_ref_slab, GFP_ATOMIC);
 	if (ret) {
 		int i = 0;
 		for (i=0; i < REFS_PER_BLOCK; i++) {