From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Coly Li <colyli@suse.de>, Hannes Reinecke <hare@suse.de>,
Jens Axboe <axboe@kernel.dk>, Sasha Levin <sashal@kernel.org>,
linux-bcache@vger.kernel.org
Subject: [PATCH AUTOSEL 4.14 21/22] bcache: fix super block seq numbers comparision in register_cache_set()
Date: Mon, 10 Aug 2020 15:13:43 -0400 [thread overview]
Message-ID: <20200810191345.3795166-21-sashal@kernel.org> (raw)
In-Reply-To: <20200810191345.3795166-1-sashal@kernel.org>
From: Coly Li <colyli@suse.de>
[ Upstream commit 117f636ea695270fe492d0c0c9dfadc7a662af47 ]
In register_cache_set(), c is pointer to struct cache_set, and ca is
pointer to struct cache, if ca->sb.seq > c->sb.seq, it means this
registering cache has up to date version and other members, the in-
memory version and other members should be updated to the newer value.
But current implementation makes a cache set only has a single cache
device, so the above assumption works well except for a special case.
The execption is when a cache device new created and both ca->sb.seq and
c->sb.seq are 0, because the super block is never flushed out yet. In
the location for the following if() check,
2156 if (ca->sb.seq > c->sb.seq) {
2157 c->sb.version = ca->sb.version;
2158 memcpy(c->sb.set_uuid, ca->sb.set_uuid, 16);
2159 c->sb.flags = ca->sb.flags;
2160 c->sb.seq = ca->sb.seq;
2161 pr_debug("set version = %llu\n", c->sb.version);
2162 }
c->sb.version is not initialized yet and valued 0. When ca->sb.seq is 0,
the if() check will fail (because both values are 0), and the cache set
version, set_uuid, flags and seq won't be updated.
The above problem is hiden for current code, because the bucket size is
compatible among different super block version. And the next time when
running cache set again, ca->sb.seq will be larger than 0 and cache set
super block version will be updated properly.
But if the large bucket feature is enabled, sb->bucket_size is the low
16bits of the bucket size. For a power of 2 value, when the actual
bucket size exceeds 16bit width, sb->bucket_size will always be 0. Then
read_super_common() will fail because the if() check to
is_power_of_2(sb->bucket_size) is false. This is how the long time
hidden bug is triggered.
This patch modifies the if() check to the following way,
2156 if (ca->sb.seq > c->sb.seq || c->sb.seq == 0) {
Then cache set's version, set_uuid, flags and seq will always be updated
corectly including for a new created cache device.
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/md/bcache/super.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 690aeb09bbf55..32498b912ce7c 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -1780,7 +1780,14 @@ static const char *register_cache_set(struct cache *ca)
sysfs_create_link(&c->kobj, &ca->kobj, buf))
goto err;
- if (ca->sb.seq > c->sb.seq) {
+ /*
+ * A special case is both ca->sb.seq and c->sb.seq are 0,
+ * such condition happens on a new created cache device whose
+ * super block is never flushed yet. In this case c->sb.version
+ * and other members should be updated too, otherwise we will
+ * have a mistaken super block version in cache set.
+ */
+ if (ca->sb.seq > c->sb.seq || c->sb.seq == 0) {
c->sb.version = ca->sb.version;
memcpy(c->sb.set_uuid, ca->sb.set_uuid, 16);
c->sb.flags = ca->sb.flags;
--
2.25.1
next prev parent reply other threads:[~2020-08-10 19:17 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-08-10 19:13 [PATCH AUTOSEL 4.14 01/22] drm/tilcdc: fix leak & null ref in panel_connector_get_modes Sasha Levin
2020-08-10 19:13 ` [PATCH AUTOSEL 4.14 02/22] Bluetooth: add a mutex lock to avoid UAF in do_enale_set Sasha Levin
2020-08-10 19:13 ` [PATCH AUTOSEL 4.14 03/22] fs/btrfs: Add cond_resched() for try_release_extent_mapping() stalls Sasha Levin
2020-08-10 19:13 ` [PATCH AUTOSEL 4.14 04/22] drm/radeon: Fix reference count leaks caused by pm_runtime_get_sync Sasha Levin
2020-08-10 19:13 ` [PATCH AUTOSEL 4.14 05/22] video: fbdev: neofb: fix memory leak in neo_scan_monitor() Sasha Levin
2020-08-10 19:13 ` [PATCH AUTOSEL 4.14 06/22] md-cluster: fix wild pointer of unlock_all_bitmaps() Sasha Levin
2020-08-10 19:13 ` [PATCH AUTOSEL 4.14 07/22] arm64: dts: hisilicon: hikey: fixes to comply with adi, adv7533 DT binding Sasha Levin
2020-08-10 19:13 ` [PATCH AUTOSEL 4.14 08/22] drm/nouveau: fix multiple instances of reference count leaks Sasha Levin
2020-08-10 19:13 ` [PATCH AUTOSEL 4.14 09/22] drm/debugfs: fix plain echo to connector "force" attribute Sasha Levin
2020-08-10 19:13 ` [PATCH AUTOSEL 4.14 10/22] irqchip/irq-mtk-sysirq: Replace spinlock with raw_spinlock Sasha Levin
2020-08-10 19:13 ` [PATCH AUTOSEL 4.14 11/22] mm/mmap.c: Add cond_resched() for exit_mmap() CPU stalls Sasha Levin
2020-08-10 19:13 ` [PATCH AUTOSEL 4.14 12/22] brcmfmac: To fix Bss Info flag definition Bug Sasha Levin
2020-08-10 19:13 ` [PATCH AUTOSEL 4.14 13/22] brcmfmac: set state of hanger slot to FREE when flushing PSQ Sasha Levin
2020-08-10 19:13 ` [PATCH AUTOSEL 4.14 14/22] iwlegacy: Check the return value of pcie_capability_read_*() Sasha Levin
2020-08-10 19:13 ` [PATCH AUTOSEL 4.14 15/22] gpu: host1x: debug: Fix multiple channels emitting messages simultaneously Sasha Levin
2020-08-10 19:13 ` [PATCH AUTOSEL 4.14 16/22] usb: gadget: net2280: fix memory leak on probe error handling paths Sasha Levin
2020-08-10 19:13 ` [PATCH AUTOSEL 4.14 17/22] bdc: Fix bug causing crash after multiple disconnects Sasha Levin
2020-08-10 19:13 ` [PATCH AUTOSEL 4.14 18/22] usb: bdc: Halt controller on suspend Sasha Levin
2020-08-10 19:13 ` [PATCH AUTOSEL 4.14 19/22] dyndbg: fix a BUG_ON in ddebug_describe_flags Sasha Levin
2020-08-10 19:13 ` [PATCH AUTOSEL 4.14 20/22] dyndbg: prefer declarative init in caller, to memset in callee Sasha Levin
2020-08-10 19:13 ` Sasha Levin [this message]
2020-08-10 19:13 ` [PATCH AUTOSEL 4.14 22/22] ACPICA: Do not increment operation_region reference counts for field units Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200810191345.3795166-21-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=axboe@kernel.dk \
--cc=colyli@suse.de \
--cc=hare@suse.de \
--cc=linux-bcache@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox