From: Greg Kroah-Hartman Date: Thu, 11 Aug 2022 14:11:24 +0000 (+0200) Subject: 4.9-stable patches X-Git-Tag: v5.15.61~222 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ac5acde2f4c84a9a51ebdca11256f4b118f661b0;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: add-barriers-to-buffer_uptodate-and-set_buffer_uptodate.patch --- diff --git a/queue-4.9/add-barriers-to-buffer_uptodate-and-set_buffer_uptodate.patch b/queue-4.9/add-barriers-to-buffer_uptodate-and-set_buffer_uptodate.patch new file mode 100644 index 00000000000..623c801eced --- /dev/null +++ b/queue-4.9/add-barriers-to-buffer_uptodate-and-set_buffer_uptodate.patch @@ -0,0 +1,77 @@ +From d4252071b97d2027d246f6a82cbee4d52f618b47 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Tue, 9 Aug 2022 14:32:13 -0400 +Subject: add barriers to buffer_uptodate and set_buffer_uptodate + +From: Mikulas Patocka + +commit d4252071b97d2027d246f6a82cbee4d52f618b47 upstream. + +Let's have a look at this piece of code in __bread_slow: + + get_bh(bh); + bh->b_end_io = end_buffer_read_sync; + submit_bh(REQ_OP_READ, 0, bh); + wait_on_buffer(bh); + if (buffer_uptodate(bh)) + return bh; + +Neither wait_on_buffer nor buffer_uptodate contain any memory barrier. +Consequently, if someone calls sb_bread and then reads the buffer data, +the read of buffer data may be executed before wait_on_buffer(bh) on +architectures with weak memory ordering and it may return invalid data. + +Fix this bug by adding a memory barrier to set_buffer_uptodate and an +acquire barrier to buffer_uptodate (in a similar way as +folio_test_uptodate and folio_mark_uptodate). + +Signed-off-by: Mikulas Patocka +Reviewed-by: Matthew Wilcox (Oracle) +Cc: stable@vger.kernel.org +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/buffer_head.h | 25 ++++++++++++++++++++++++- + 1 file changed, 24 insertions(+), 1 deletion(-) + +--- a/include/linux/buffer_head.h ++++ b/include/linux/buffer_head.h +@@ -113,7 +113,6 @@ static __always_inline int test_clear_bu + * of the form "mark_buffer_foo()". These are higher-level functions which + * do something in addition to setting a b_state bit. + */ +-BUFFER_FNS(Uptodate, uptodate) + BUFFER_FNS(Dirty, dirty) + TAS_BUFFER_FNS(Dirty, dirty) + BUFFER_FNS(Lock, locked) +@@ -131,6 +130,30 @@ BUFFER_FNS(Meta, meta) + BUFFER_FNS(Prio, prio) + BUFFER_FNS(Defer_Completion, defer_completion) + ++static __always_inline void set_buffer_uptodate(struct buffer_head *bh) ++{ ++ /* ++ * make it consistent with folio_mark_uptodate ++ * pairs with smp_load_acquire in buffer_uptodate ++ */ ++ smp_mb__before_atomic(); ++ set_bit(BH_Uptodate, &bh->b_state); ++} ++ ++static __always_inline void clear_buffer_uptodate(struct buffer_head *bh) ++{ ++ clear_bit(BH_Uptodate, &bh->b_state); ++} ++ ++static __always_inline int buffer_uptodate(const struct buffer_head *bh) ++{ ++ /* ++ * make it consistent with folio_test_uptodate ++ * pairs with smp_mb__before_atomic in set_buffer_uptodate ++ */ ++ return (smp_load_acquire(&bh->b_state) & (1UL << BH_Uptodate)) != 0; ++} ++ + #define bh_offset(bh) ((unsigned long)(bh)->b_data & ~PAGE_MASK) + + /* If we *know* page->private refers to buffer_heads */ diff --git a/queue-4.9/series b/queue-4.9/series index a2351c06e56..2e6a958c2be 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -25,3 +25,4 @@ macintosh-adb-fix-oob-read-in-do_adb_query-function.patch makefile-link-with-z-noexecstack-no-warn-rwx-segments.patch x86-link-vdso-and-boot-with-z-noexecstack-no-warn-rwx-segments.patch alsa-bcd2000-fix-a-uaf-bug-on-the-error-path-of-probing.patch +add-barriers-to-buffer_uptodate-and-set_buffer_uptodate.patch