* Forwarded: [PATCH] ocfs2: fix use-after-free in o2hb_region_dev_store
2026-09-04 22:00 [syzbot] KASAN: slab-use-after-free Write in o2hb_region_dev_store syzbot
@ 2026-09-04 23:35 ` syzbot
2026-10-20 8:30 ` syzbot
2026-10-20 8:30 ` syzbot
2 siblings, 0 replies; 4+ messages in thread
From: syzbot @ 2026-09-04 23:35 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH] ocfs2: fix use-after-free in o2hb_region_dev_store
Author: kartikey406@gmail.com
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
Concurrent writes to a region's "dev" attribute can race, letting two
tasks both allocate/free reg->hr_slot_data for the same region and
causing a use-after-free. Add a per-region mutex to serialize
o2hb_region_dev_store() against itself and against
o2hb_region_release().
Reported-by: syzbot+3025e3e8fc0b928af8f5@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=3025e3e8fc0b928af8f5
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
fs/ocfs2/cluster/heartbeat.c | 23 +++++++++++++++++++----
1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index 1c3def99bb07..6f03de1b6d4a 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -273,6 +273,9 @@ struct o2hb_region {
/* last hb status, 0 for success, other value for error. */
int hr_last_hb_status;
+ /* Serializes dev_store() against itself and region_release() */
+ struct mutex hr_dev_write_mutex;
+
};
static inline struct block_device *reg_bdev(struct o2hb_region *reg)
@@ -1616,7 +1619,10 @@ static void o2hb_region_release(struct config_item *item)
o2hb_quiesce_timeout(reg);
o2net_unregister_and_flush_handler_list(®->hr_handler_list);
+
+ mutex_lock(®->hr_dev_write_mutex);
o2hb_unmap_slot_data(reg);
+ mutex_unlock(®->hr_dev_write_mutex);
if (reg->hr_bdev_file)
fput(reg->hr_bdev_file);
@@ -1879,9 +1885,6 @@ static ssize_t o2hb_region_dev_store(struct config_item *item,
ssize_t ret = -EINVAL;
int live_threshold;
- if (reg->hr_bdev_file)
- return -EINVAL;
-
/* We can't heartbeat without having had our node number
* configured yet. */
reg->hr_node_num = o2nm_this_node();
@@ -1906,12 +1909,20 @@ static ssize_t o2hb_region_dev_store(struct config_item *item,
if (!S_ISBLK(fd_file(f)->f_mapping->host->i_mode))
return -EINVAL;
+ if (mutex_lock_interruptible(®->hr_dev_write_mutex))
+ return -ERESTARTSYS;
+
+ if (reg->hr_bdev_file) {
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
reg->hr_bdev_file = bdev_file_open_by_dev(fd_file(f)->f_mapping->host->i_rdev,
BLK_OPEN_WRITE | BLK_OPEN_READ, NULL, NULL);
if (IS_ERR(reg->hr_bdev_file)) {
ret = PTR_ERR(reg->hr_bdev_file);
reg->hr_bdev_file = NULL;
- return ret;
+ goto out_unlock;
}
sectsize = bdev_logical_block_size(reg_bdev(reg));
@@ -2029,6 +2040,8 @@ static ssize_t o2hb_region_dev_store(struct config_item *item,
fput(reg->hr_bdev_file);
reg->hr_bdev_file = NULL;
}
+out_unlock:
+ mutex_unlock(®->hr_dev_write_mutex);
return ret;
}
@@ -2149,6 +2162,8 @@ static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *g
config_item_init_type_name(®->hr_item, name, &o2hb_region_type);
+ mutex_init(®->hr_dev_write_mutex);
+
/* this is the same way to generate msg key as dlm, for local heartbeat,
* name is also the same, so make initial crc value different to avoid
* message key conflict.
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread* Forwarded: [PATCH] ocfs2: fix use-after-free in o2hb_region_dev_store
2026-09-04 22:00 [syzbot] KASAN: slab-use-after-free Write in o2hb_region_dev_store syzbot
2026-09-04 23:35 ` Forwarded: [PATCH] ocfs2: fix use-after-free " syzbot
@ 2026-10-20 8:30 ` syzbot
2026-10-20 8:30 ` syzbot
2 siblings, 0 replies; 4+ messages in thread
From: syzbot @ 2026-10-20 8:30 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH] ocfs2: fix use-after-free in o2hb_region_dev_store
Author: kartikey406@gmail.com
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
Two tasks can concurrently write to the same region's "dev" configfs
attribute, each through its own open fd. configfs does not serialize
separate fds against each other here.
The only guard against a second writer is an unlocked check near the
top of o2hb_region_dev_store():
if (reg->hr_bdev_file)
return -EINVAL;
This check happens well before hr_bdev_file is actually assigned;
several validation steps and an fd lookup sit in between. If a second
task runs this same check before the first task has assigned
hr_bdev_file, it also reads NULL and also proceeds.
Both tasks then call o2hb_map_slot_data(), which allocates
reg->hr_slot_data, and later, on any failure, o2hb_unmap_slot_data(),
which frees it. Since hr_slot_data is also unprotected, one task can
free it through its failure path while the other task is still
populating the array, producing the use-after-free reported by syzbot.
Race flow:
T1: dev_store() T2: dev_store()
if (reg->hr_bdev_file) // NULL if (reg->hr_bdev_file) // NULL
... ...
reg->hr_bdev_file = ...
o2hb_map_slot_data()
alloc reg->hr_slot_data
populating slots...
reg->hr_bdev_file = ...
o2hb_map_slot_data()
failure -> out:
o2hb_unmap_slot_data()
frees reg->hr_slot_data
writes to freed slot data <-- UAF
Fix this by adding a per-region mutex, taken at the top of
o2hb_region_dev_store() before any region state is modified and held
until the function returns.
Reported-by: syzbot+3025e3e8fc0b928af8f5@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=3025e3e8fc0b928af8f5
Assisted-by: Claude
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
v2:
- Expanded the description with the race flow
- Updated Fixes: tag
- Use tab for indentation
- Dropped locking in o2hb_region_release(); configfs already
serializes store and rmdir
- Take the lock before the hr_node_num assignment, using
guard(mutex) so every early return releases it
---
fs/ocfs2/cluster/heartbeat.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index 1c3def99bb07..e20ef0459f54 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -273,6 +273,8 @@ struct o2hb_region {
/* last hb status, 0 for success, other value for error. */
int hr_last_hb_status;
+ /* Serializes concurrent writers of the "dev" attribute */
+ struct mutex hr_dev_write_mutex;
};
static inline struct block_device *reg_bdev(struct o2hb_region *reg)
@@ -1879,6 +1881,8 @@ static ssize_t o2hb_region_dev_store(struct config_item *item,
ssize_t ret = -EINVAL;
int live_threshold;
+ guard(mutex)(®->hr_dev_write_mutex);
+
if (reg->hr_bdev_file)
return -EINVAL;
@@ -2149,6 +2153,8 @@ static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *g
config_item_init_type_name(®->hr_item, name, &o2hb_region_type);
+ mutex_init(®->hr_dev_write_mutex);
+
/* this is the same way to generate msg key as dlm, for local heartbeat,
* name is also the same, so make initial crc value different to avoid
* message key conflict.
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread* Forwarded: [PATCH] ocfs2: fix use-after-free in o2hb_region_dev_store
2026-09-04 22:00 [syzbot] KASAN: slab-use-after-free Write in o2hb_region_dev_store syzbot
2026-09-04 23:35 ` Forwarded: [PATCH] ocfs2: fix use-after-free " syzbot
2026-10-20 8:30 ` syzbot
@ 2026-10-20 8:30 ` syzbot
2 siblings, 0 replies; 4+ messages in thread
From: syzbot @ 2026-10-20 8:30 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH] ocfs2: fix use-after-free in o2hb_region_dev_store
Author: kartikey406@gmail.com
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
Two tasks can concurrently write to the same region's "dev" configfs
attribute, each through its own open fd. configfs does not serialize
separate fds against each other here.
The only guard against a second writer is an unlocked check near the
top of o2hb_region_dev_store():
if (reg->hr_bdev_file)
return -EINVAL;
This check happens well before hr_bdev_file is actually assigned;
several validation steps and an fd lookup sit in between. If a second
task runs this same check before the first task has assigned
hr_bdev_file, it also reads NULL and also proceeds.
Both tasks then call o2hb_map_slot_data(), which allocates
reg->hr_slot_data, and later, on any failure, o2hb_unmap_slot_data(),
which frees it. Since hr_slot_data is also unprotected, one task can
free it through its failure path while the other task is still
populating the array, producing the use-after-free reported by syzbot.
Race flow:
T1: dev_store() T2: dev_store()
if (reg->hr_bdev_file) // NULL if (reg->hr_bdev_file) // NULL
... ...
reg->hr_bdev_file = ...
o2hb_map_slot_data()
alloc reg->hr_slot_data
populating slots...
reg->hr_bdev_file = ...
o2hb_map_slot_data()
failure -> out:
o2hb_unmap_slot_data()
frees reg->hr_slot_data
writes to freed slot data <-- UAF
Fix this by adding a per-region mutex, taken at the top of
o2hb_region_dev_store() before any region state is modified and held
until the function returns.
Reported-by: syzbot+3025e3e8fc0b928af8f5@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=3025e3e8fc0b928af8f5
Assisted-by: Claude
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
v2:
- Expanded the description with the race flow
- Updated Fixes: tag
- Use tab for indentation
- Dropped locking in o2hb_region_release(); configfs already
serializes store and rmdir
- Take the lock before the hr_node_num assignment, using
guard(mutex) so every early return releases it
---
fs/ocfs2/cluster/heartbeat.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index 1c3def99bb07..e20ef0459f54 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -273,6 +273,8 @@ struct o2hb_region {
/* last hb status, 0 for success, other value for error. */
int hr_last_hb_status;
+ /* Serializes concurrent writers of the "dev" attribute */
+ struct mutex hr_dev_write_mutex;
};
static inline struct block_device *reg_bdev(struct o2hb_region *reg)
@@ -1879,6 +1881,8 @@ static ssize_t o2hb_region_dev_store(struct config_item *item,
ssize_t ret = -EINVAL;
int live_threshold;
+ guard(mutex)(®->hr_dev_write_mutex);
+
if (reg->hr_bdev_file)
return -EINVAL;
@@ -2149,6 +2153,8 @@ static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *g
config_item_init_type_name(®->hr_item, name, &o2hb_region_type);
+ mutex_init(®->hr_dev_write_mutex);
+
/* this is the same way to generate msg key as dlm, for local heartbeat,
* name is also the same, so make initial crc value different to avoid
* message key conflict.
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread