]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ocfs2: fix buffer head management in ocfs2_read_blocks()
authorDmitry Antipov <dmantipov@yandex.ru>
Fri, 29 May 2026 09:41:28 +0000 (12:41 +0300)
committerAndrew Morton <akpm@linux-foundation.org>
Thu, 4 Jun 2026 21:49:28 +0000 (14:49 -0700)
In ocfs2_read_blocks(), caller should't assume that buffer head returned
by 'sb_getblk()' is exclusively owned and so 'put_bh()' always drops
b_count from 1 to 0.  If it is not so, buffer head remains on hold and
likely to be returned by the next call to 'sb_getblk()' unchanged - that
is, with BH_Uptodate bit set even if it has failed validation previously,
thus allowing to insert that buffer head into OCFS2 metadata cache and
submit it to upper layers.  To avoid such a scenario, BH_Uptodate should
be cleared immediately after 'validate()' callback has detected some data
inconsistency.

Link: https://lore.kernel.org/20260529094128.494293-1-dmantipov@yandex.ru
Fixes: cf76c78595ca ("ocfs2: don't put and assigning null to bh allocated outside")
Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
Reported-by: syzbot+caacd220635a9cc3bac9@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=caacd220635a9cc3bac9
Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
Cc: Mark Fasheh <mark@fasheh.com>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: Junxiao Bi <junxiao.bi@oracle.com>
Cc: Changwei Ge <gechangwei@live.cn>
Cc: Jun Piao <piaojun@huawei.com>
Cc: Heming Zhao <heming.zhao@suse.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
fs/ocfs2/buffer_head_io.c

index 701d27d908d4b20e6d2995c07d6ddf9f98f78e89..6114299b121e52326461143574bdf679e87362ee 100644 (file)
@@ -350,8 +350,6 @@ read_failure:
                                                wait_on_buffer(bh);
                                        put_bh(bh);
                                        bhs[i] = NULL;
-                               } else if (bh && buffer_uptodate(bh)) {
-                                       clear_buffer_uptodate(bh);
                                }
                                continue;
                        }
@@ -380,8 +378,11 @@ read_failure:
                                BUG_ON(buffer_jbd(bh));
                                clear_buffer_needs_validate(bh);
                                status = validate(sb, bh);
-                               if (status)
+                               if (status) {
+                                       if (buffer_uptodate(bh))
+                                               clear_buffer_uptodate(bh);
                                        goto read_failure;
+                               }
                        }
                }