CVE-2026-46129
Description
In the Linux kernel, the following vulnerability has been resolved:
btrfs: fix double free in create_space_info() error path
When kobject_init_and_add() fails, the call chain is:
create_space_info() -> btrfs_sysfs_add_space_info_type() -> kobject_init_and_add() -> failure -> kobject_put(&space_info->kobj) -> space_info_release() -> kfree(space_info)
Then control returns to create_space_info():
btrfs_sysfs_add_space_info_type() returns error -> goto out_free -> kfree(space_info)
This causes a double free.
Keep the direct kfree(space_info) for the earlier failure path, but after btrfs_sysfs_add_space_info_type() has called kobject_put(), let the kobject release callback handle the cleanup.
Affected products
1Patches
103f487be81292btrfs: fix double free in create_space_info() error path
2 files changed · +2 −4
fs/btrfs/space-info.c+1 −2 modifieddiff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 8278e7998bc9a0..f0436eea15445b 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -320,7 +320,7 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags) ret = btrfs_sysfs_add_space_info_type(space_info); if (ret) - goto out_free; + return ret; list_add(&space_info->list, &info->space_info); if (flags & BTRFS_BLOCK_GROUP_DATA) -- cgit 1.3-korg
fs/btrfs/space-info.c+1 −2 modifieddiff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 8278e7998bc9a0..f0436eea15445b 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -320,7 +320,7 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags) ret = btrfs_sysfs_add_space_info_type(space_info); if (ret) - goto out_free; + return ret; list_add(&space_info->list, &info->space_info); if (flags & BTRFS_BLOCK_GROUP_DATA) -- cgit 1.3-korg
c2670ec4aa49btrfs: fix double free in create_space_info() error path
2 files changed · +2 −4
fs/btrfs/space-info.c+1 −2 modifieddiff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 12f8f55bb99384..0a960b6c866e5b 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -293,7 +293,7 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags) ret = btrfs_sysfs_add_space_info_type(info, space_info); if (ret) - goto out_free; + return ret; list_add(&space_info->list, &info->space_info); if (flags & BTRFS_BLOCK_GROUP_DATA) -- cgit 1.3-korg
fs/btrfs/space-info.c+1 −2 modifieddiff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 12f8f55bb99384..0a960b6c866e5b 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -293,7 +293,7 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags) ret = btrfs_sysfs_add_space_info_type(info, space_info); if (ret) - goto out_free; + return ret; list_add(&space_info->list, &info->space_info); if (flags & BTRFS_BLOCK_GROUP_DATA) -- cgit 1.3-korg
f414b3abbba5btrfs: fix double free in create_space_info() error path
2 files changed · +2 −4
fs/btrfs/space-info.c+1 −2 modifieddiff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index ada19b3288611a..7da0e739762afe 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -296,7 +296,7 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags) ret = btrfs_sysfs_add_space_info_type(info, space_info); if (ret) - goto out_free; + return ret; list_add(&space_info->list, &info->space_info); if (flags & BTRFS_BLOCK_GROUP_DATA) -- cgit 1.3-korg
fs/btrfs/space-info.c+1 −2 modifieddiff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index ada19b3288611a..7da0e739762afe 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -296,7 +296,7 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags) ret = btrfs_sysfs_add_space_info_type(info, space_info); if (ret) - goto out_free; + return ret; list_add(&space_info->list, &info->space_info); if (flags & BTRFS_BLOCK_GROUP_DATA) -- cgit 1.3-korg
9a060970fd7bbtrfs: fix double free in create_space_info() error path
2 files changed · +2 −4
fs/btrfs/space-info.c+1 −2 modifieddiff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 194f590201658e..a815308e2db912 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -311,7 +311,7 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags) ret = btrfs_sysfs_add_space_info_type(info, space_info); if (ret) - goto out_free; + return ret; list_add(&space_info->list, &info->space_info); if (flags & BTRFS_BLOCK_GROUP_DATA) -- cgit 1.3-korg
fs/btrfs/space-info.c+1 −2 modifieddiff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 194f590201658e..a815308e2db912 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -311,7 +311,7 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags) ret = btrfs_sysfs_add_space_info_type(info, space_info); if (ret) - goto out_free; + return ret; list_add(&space_info->list, &info->space_info); if (flags & BTRFS_BLOCK_GROUP_DATA) -- cgit 1.3-korg
dd6ade0fdd59btrfs: fix double free in create_space_info() error path
2 files changed · +2 −4
fs/btrfs/space-info.c+1 −2 modifieddiff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 87cbc051cb12ff..45ec126fca4f2f 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -311,7 +311,7 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags) ret = btrfs_sysfs_add_space_info_type(space_info); if (ret) - goto out_free; + return ret; list_add(&space_info->list, &info->space_info); if (flags & BTRFS_BLOCK_GROUP_DATA) -- cgit 1.3-korg
fs/btrfs/space-info.c+1 −2 modifieddiff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 87cbc051cb12ff..45ec126fca4f2f 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -311,7 +311,7 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags) ret = btrfs_sysfs_add_space_info_type(space_info); if (ret) - goto out_free; + return ret; list_add(&space_info->list, &info->space_info); if (flags & BTRFS_BLOCK_GROUP_DATA) -- cgit 1.3-korg
dd6ade0fdd59btrfs: fix double free in create_space_info() error path
2 files changed · +2 −4
fs/btrfs/space-info.c+1 −2 modifieddiff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 87cbc051cb12ff..45ec126fca4f2f 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -311,7 +311,7 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags) ret = btrfs_sysfs_add_space_info_type(space_info); if (ret) - goto out_free; + return ret; list_add(&space_info->list, &info->space_info); if (flags & BTRFS_BLOCK_GROUP_DATA) -- cgit 1.3-korg
fs/btrfs/space-info.c+1 −2 modifieddiff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 87cbc051cb12ff..45ec126fca4f2f 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -311,7 +311,7 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags) ret = btrfs_sysfs_add_space_info_type(space_info); if (ret) - goto out_free; + return ret; list_add(&space_info->list, &info->space_info); if (flags & BTRFS_BLOCK_GROUP_DATA) -- cgit 1.3-korg
9a060970fd7bbtrfs: fix double free in create_space_info() error path
2 files changed · +2 −4
fs/btrfs/space-info.c+1 −2 modifieddiff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 194f590201658e..a815308e2db912 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -311,7 +311,7 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags) ret = btrfs_sysfs_add_space_info_type(info, space_info); if (ret) - goto out_free; + return ret; list_add(&space_info->list, &info->space_info); if (flags & BTRFS_BLOCK_GROUP_DATA) -- cgit 1.3-korg
fs/btrfs/space-info.c+1 −2 modifieddiff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 194f590201658e..a815308e2db912 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -311,7 +311,7 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags) ret = btrfs_sysfs_add_space_info_type(info, space_info); if (ret) - goto out_free; + return ret; list_add(&space_info->list, &info->space_info); if (flags & BTRFS_BLOCK_GROUP_DATA) -- cgit 1.3-korg
c2670ec4aa49btrfs: fix double free in create_space_info() error path
2 files changed · +2 −4
fs/btrfs/space-info.c+1 −2 modifieddiff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 12f8f55bb99384..0a960b6c866e5b 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -293,7 +293,7 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags) ret = btrfs_sysfs_add_space_info_type(info, space_info); if (ret) - goto out_free; + return ret; list_add(&space_info->list, &info->space_info); if (flags & BTRFS_BLOCK_GROUP_DATA) -- cgit 1.3-korg
fs/btrfs/space-info.c+1 −2 modifieddiff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 12f8f55bb99384..0a960b6c866e5b 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -293,7 +293,7 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags) ret = btrfs_sysfs_add_space_info_type(info, space_info); if (ret) - goto out_free; + return ret; list_add(&space_info->list, &info->space_info); if (flags & BTRFS_BLOCK_GROUP_DATA) -- cgit 1.3-korg
f414b3abbba5btrfs: fix double free in create_space_info() error path
2 files changed · +2 −4
fs/btrfs/space-info.c+1 −2 modifieddiff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index ada19b3288611a..7da0e739762afe 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -296,7 +296,7 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags) ret = btrfs_sysfs_add_space_info_type(info, space_info); if (ret) - goto out_free; + return ret; list_add(&space_info->list, &info->space_info); if (flags & BTRFS_BLOCK_GROUP_DATA) -- cgit 1.3-korg
fs/btrfs/space-info.c+1 −2 modifieddiff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index ada19b3288611a..7da0e739762afe 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -296,7 +296,7 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags) ret = btrfs_sysfs_add_space_info_type(info, space_info); if (ret) - goto out_free; + return ret; list_add(&space_info->list, &info->space_info); if (flags & BTRFS_BLOCK_GROUP_DATA) -- cgit 1.3-korg
3f487be81292btrfs: fix double free in create_space_info() error path
2 files changed · +2 −4
fs/btrfs/space-info.c+1 −2 modifieddiff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 8278e7998bc9a0..f0436eea15445b 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -320,7 +320,7 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags) ret = btrfs_sysfs_add_space_info_type(space_info); if (ret) - goto out_free; + return ret; list_add(&space_info->list, &info->space_info); if (flags & BTRFS_BLOCK_GROUP_DATA) -- cgit 1.3-korg
fs/btrfs/space-info.c+1 −2 modifieddiff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 8278e7998bc9a0..f0436eea15445b 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -320,7 +320,7 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags) ret = btrfs_sysfs_add_space_info_type(space_info); if (ret) - goto out_free; + return ret; list_add(&space_info->list, &info->space_info); if (flags & BTRFS_BLOCK_GROUP_DATA) -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Double free in create_space_info() error path: when btrfs_sysfs_add_space_info_type() fails, kobject_put() inside that function already frees space_info via the release callback, but the caller then jumps to out_free and calls kfree(space_info) again."
Attack vector
An attacker cannot directly trigger this bug from userspace; it is a kernel-internal error-handling flaw. The double free occurs when the kernel function create_space_info() in fs/btrfs/space-info.c calls btrfs_sysfs_add_space_info_type(), which in turn calls kobject_init_and_add(). If that kobject initialization fails (e.g. due to memory pressure or a sysfs name collision), kobject_put() is invoked inside the callee, which triggers space_info_release() and frees the space_info struct. Control then returns to create_space_info() with a non-zero error code, and the existing code jumps to the out_free label, which calls kfree(space_info) a second time on the already-freed pointer [patch_id=2898444].
Affected code
The vulnerable function is create_space_info() in fs/btrfs/space-info.c. The error path after the call to btrfs_sysfs_add_space_info_type() previously jumped to the out_free label, which unconditionally called kfree(space_info).
What the fix does
The patch changes the error-handling branch after btrfs_sysfs_add_space_info_type() from "goto out_free" to "return ret" [patch_id=2898444]. This prevents the second kfree(space_info) at the out_free label. The earlier failure paths in create_space_info() that allocate space_info but have not yet handed ownership to the kobject still use the direct kfree(space_info) as before. The commit message explicitly states: "Keep the direct kfree(space_info) for the earlier failure path, but after btrfs_sysfs_add_space_info_type() has called kobject_put(), let the kobject release callback handle the cleanup."
Preconditions
- configThe kernel must be running a btrfs filesystem that triggers the create_space_info() code path (e.g. during mount or block group allocation).
- inputThe kobject_init_and_add() call inside btrfs_sysfs_add_space_info_type() must fail (e.g. due to memory pressure or sysfs name collision).
Generated on May 28, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- git.kernel.org/stable/c/3f487be81292702a59ea9dbc4088b3360a50e837nvd
- git.kernel.org/stable/c/9a060970fd7b5e1c561e4ce73cb9949e4269a738nvd
- git.kernel.org/stable/c/c2670ec4aa49ca226bce9776601e0da37502be07nvd
- git.kernel.org/stable/c/dd6ade0fdd59218d71a981ae7c937a304e49209cnvd
- git.kernel.org/stable/c/f414b3abbba59ef379a2b3c31f2bdd9358ed5e53nvd
News mentions
0No linked articles in our index yet.