* [PATCH] btrfs: reject names longer than BTRFS_NAME_LEN in btrfs_get_name()
@ 2026-06-07 12:14 Weiming Shi
2026-06-07 20:23 ` Miquel Sabaté Solà
2026-06-07 22:21 ` Qu Wenruo
0 siblings, 2 replies; 4+ messages in thread
From: Weiming Shi @ 2026-06-07 12:14 UTC (permalink / raw)
To: linux-btrfs; +Cc: dsterba, josef, clm, xmei5, Weiming Shi
btrfs_get_name() reads the name length straight from the on-disk
inode_ref (or root_ref) and copies that many bytes into the caller's
buffer with no upper bound. The caller (exportfs_get_name()) supplies a
fixed NAME_MAX + 1 byte stack buffer, but name_len is a __le16 read from
the leaf and the tree-checker only bounds it to the item size, not to
BTRFS_NAME_LEN. A crafted leaf with name_len = 4096 therefore overflows
the 256-byte buffer with attacker-controlled bytes. It is reachable from
a mounted untrusted btrfs image via open_by_handle_at(), and on btrfs
filesystems exported over NFS.
BUG: KASAN: stack-out-of-bounds in read_extent_buffer (fs/btrfs/extent_io.c:3742)
Write of size 633 at addr ffffc90006c9fc40 by task exploit/5192
read_extent_buffer (fs/btrfs/extent_io.c:3742)
btrfs_get_name (fs/btrfs/export.c:289)
reconnect_path (fs/exportfs/expfs.c:222)
exportfs_decode_fh_raw (fs/exportfs/expfs.c:473)
do_handle_open (fs/fhandle.c:230)
do_syscall_64 (arch/x86/entry/syscall_64.c:94)
Kernel panic - not syncing: stack-protector: Kernel stack is corrupted
Reject any name_len greater than BTRFS_NAME_LEN before the copy. Such a
name is never valid on disk, so this only rejects corrupted leaves and
leaves valid names unchanged.
Fixes: 2ede0daf0154 ("Btrfs: handle NFS lookups properly")
Reported-by: Xiang Mei <xmei5@asu.edu>
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
---
fs/btrfs/export.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/fs/btrfs/export.c b/fs/btrfs/export.c
index c403117ac..a54c6e8b3 100644
--- a/fs/btrfs/export.c
+++ b/fs/btrfs/export.c
@@ -285,6 +285,16 @@ static int btrfs_get_name(struct dentry *parent, char *name,
name_len = btrfs_inode_ref_name_len(leaf, iref);
}
+ /* The caller's buffer is only NAME_MAX + 1 bytes. */
+ if (name_len > BTRFS_NAME_LEN) {
+ btrfs_err(fs_info,
+ "corrupt name length %d for inode %llu in root %llu, max %d",
+ name_len, btrfs_ino(BTRFS_I(inode)),
+ btrfs_root_id(BTRFS_I(inode)->root), BTRFS_NAME_LEN);
+ btrfs_free_path(path);
+ return -EUCLEAN;
+ }
+
read_extent_buffer(leaf, name, name_ptr, name_len);
btrfs_free_path(path);
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH] btrfs: reject names longer than BTRFS_NAME_LEN in btrfs_get_name()
2026-06-07 12:14 [PATCH] btrfs: reject names longer than BTRFS_NAME_LEN in btrfs_get_name() Weiming Shi
@ 2026-06-07 20:23 ` Miquel Sabaté Solà
2026-06-07 22:21 ` Qu Wenruo
1 sibling, 0 replies; 4+ messages in thread
From: Miquel Sabaté Solà @ 2026-06-07 20:23 UTC (permalink / raw)
To: Weiming Shi; +Cc: linux-btrfs, dsterba, josef, clm, xmei5
[-- Attachment #1: Type: text/plain, Size: 2429 bytes --]
Hi,
Weiming Shi @ 2026-06-07 05:14 -07:
> btrfs_get_name() reads the name length straight from the on-disk
> inode_ref (or root_ref) and copies that many bytes into the caller's
> buffer with no upper bound. The caller (exportfs_get_name()) supplies a
> fixed NAME_MAX + 1 byte stack buffer, but name_len is a __le16 read from
> the leaf and the tree-checker only bounds it to the item size, not to
> BTRFS_NAME_LEN. A crafted leaf with name_len = 4096 therefore overflows
> the 256-byte buffer with attacker-controlled bytes. It is reachable from
> a mounted untrusted btrfs image via open_by_handle_at(), and on btrfs
> filesystems exported over NFS.
>
> BUG: KASAN: stack-out-of-bounds in read_extent_buffer (fs/btrfs/extent_io.c:3742)
> Write of size 633 at addr ffffc90006c9fc40 by task exploit/5192
> read_extent_buffer (fs/btrfs/extent_io.c:3742)
> btrfs_get_name (fs/btrfs/export.c:289)
> reconnect_path (fs/exportfs/expfs.c:222)
> exportfs_decode_fh_raw (fs/exportfs/expfs.c:473)
> do_handle_open (fs/fhandle.c:230)
> do_syscall_64 (arch/x86/entry/syscall_64.c:94)
> Kernel panic - not syncing: stack-protector: Kernel stack is corrupted
>
> Reject any name_len greater than BTRFS_NAME_LEN before the copy. Such a
> name is never valid on disk, so this only rejects corrupted leaves and
> leaves valid names unchanged.
>
> Fixes: 2ede0daf0154 ("Btrfs: handle NFS lookups properly")
> Reported-by: Xiang Mei <xmei5@asu.edu>
> Assisted-by: Claude:claude-opus-4-8
> Signed-off-by: Weiming Shi <bestswngs@gmail.com>
> ---
> fs/btrfs/export.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/fs/btrfs/export.c b/fs/btrfs/export.c
> index c403117ac..a54c6e8b3 100644
> --- a/fs/btrfs/export.c
> +++ b/fs/btrfs/export.c
> @@ -285,6 +285,16 @@ static int btrfs_get_name(struct dentry *parent, char *name,
> name_len = btrfs_inode_ref_name_len(leaf, iref);
> }
>
> + /* The caller's buffer is only NAME_MAX + 1 bytes. */
> + if (name_len > BTRFS_NAME_LEN) {
> + btrfs_err(fs_info,
> + "corrupt name length %d for inode %llu in root %llu, max %d",
> + name_len, btrfs_ino(BTRFS_I(inode)),
> + btrfs_root_id(BTRFS_I(inode)->root), BTRFS_NAME_LEN);
> + btrfs_free_path(path);
Nitpicking: this is not necessary as 'path' is declared with a cleanup
attribute.
> + return -EUCLEAN;
> + }
> +
> read_extent_buffer(leaf, name, name_ptr, name_len);
> btrfs_free_path(path);
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 897 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] btrfs: reject names longer than BTRFS_NAME_LEN in btrfs_get_name()
2026-06-07 12:14 [PATCH] btrfs: reject names longer than BTRFS_NAME_LEN in btrfs_get_name() Weiming Shi
2026-06-07 20:23 ` Miquel Sabaté Solà
@ 2026-06-07 22:21 ` Qu Wenruo
2026-06-08 9:58 ` Weiming Shi
1 sibling, 1 reply; 4+ messages in thread
From: Qu Wenruo @ 2026-06-07 22:21 UTC (permalink / raw)
To: Weiming Shi, linux-btrfs; +Cc: dsterba, josef, clm, xmei5
在 2026/6/7 21:44, Weiming Shi 写道:
> btrfs_get_name() reads the name length straight from the on-disk
> inode_ref (or root_ref) and copies that many bytes into the caller's
> buffer with no upper bound. The caller (exportfs_get_name()) supplies a
> fixed NAME_MAX + 1 byte stack buffer, but name_len is a __le16 read from
> the leaf and the tree-checker only bounds it to the item size, not to
> BTRFS_NAME_LEN. A crafted leaf with name_len = 4096 therefore overflows
> the 256-byte buffer with attacker-controlled bytes. It is reachable from
> a mounted untrusted btrfs image via open_by_handle_at(), and on btrfs
> filesystems exported over NFS.
>
> BUG: KASAN: stack-out-of-bounds in read_extent_buffer (fs/btrfs/extent_io.c:3742)
> Write of size 633 at addr ffffc90006c9fc40 by task exploit/5192
> read_extent_buffer (fs/btrfs/extent_io.c:3742)
> btrfs_get_name (fs/btrfs/export.c:289)
> reconnect_path (fs/exportfs/expfs.c:222)
> exportfs_decode_fh_raw (fs/exportfs/expfs.c:473)
> do_handle_open (fs/fhandle.c:230)
> do_syscall_64 (arch/x86/entry/syscall_64.c:94)
> Kernel panic - not syncing: stack-protector: Kernel stack is corrupted
>
> Reject any name_len greater than BTRFS_NAME_LEN before the copy. Such a
> name is never valid on disk, so this only rejects corrupted leaves and
> leaves valid names unchanged.
>
> Fixes: 2ede0daf0154 ("Btrfs: handle NFS lookups properly")
> Reported-by: Xiang Mei <xmei5@asu.edu>
> Assisted-by: Claude:claude-opus-4-8
> Signed-off-by: Weiming Shi <bestswngs@gmail.com>
> ---
> fs/btrfs/export.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/fs/btrfs/export.c b/fs/btrfs/export.c
> index c403117ac..a54c6e8b3 100644
> --- a/fs/btrfs/export.c
> +++ b/fs/btrfs/export.c
> @@ -285,6 +285,16 @@ static int btrfs_get_name(struct dentry *parent, char *name,
> name_len = btrfs_inode_ref_name_len(leaf, iref);
> }
>
> + /* The caller's buffer is only NAME_MAX + 1 bytes. */
> + if (name_len > BTRFS_NAME_LEN) {
We do not play the whac-a-mole game by add random checks ad-hoc.
Do the proper ROOT_REF_KEY and INODE_REF_KEY verification inside
tree-checker.
> + btrfs_err(fs_info,
> + "corrupt name length %d for inode %llu in root %llu, max %d",
> + name_len, btrfs_ino(BTRFS_I(inode)),
> + btrfs_root_id(BTRFS_I(inode)->root), BTRFS_NAME_LEN);
> + btrfs_free_path(path);
> + return -EUCLEAN;
> + }
> +
> read_extent_buffer(leaf, name, name_ptr, name_len);
> btrfs_free_path(path);
>
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] btrfs: reject names longer than BTRFS_NAME_LEN in btrfs_get_name()
2026-06-07 22:21 ` Qu Wenruo
@ 2026-06-08 9:58 ` Weiming Shi
0 siblings, 0 replies; 4+ messages in thread
From: Weiming Shi @ 2026-06-08 9:58 UTC (permalink / raw)
To: Qu Wenruo; +Cc: linux-btrfs, dsterba, josef, clm, xmei5
On 26-06-08 07:51, Qu Wenruo wrote:
>
>
> 在 2026/6/7 21:44, Weiming Shi 写道:
> > btrfs_get_name() reads the name length straight from the on-disk
> > inode_ref (or root_ref) and copies that many bytes into the caller's
> > buffer with no upper bound. The caller (exportfs_get_name()) supplies a
> > fixed NAME_MAX + 1 byte stack buffer, but name_len is a __le16 read from
> > the leaf and the tree-checker only bounds it to the item size, not to
> > BTRFS_NAME_LEN. A crafted leaf with name_len = 4096 therefore overflows
> > the 256-byte buffer with attacker-controlled bytes. It is reachable from
> > a mounted untrusted btrfs image via open_by_handle_at(), and on btrfs
> > filesystems exported over NFS.
> >
> > BUG: KASAN: stack-out-of-bounds in read_extent_buffer (fs/btrfs/extent_io.c:3742)
> > Write of size 633 at addr ffffc90006c9fc40 by task exploit/5192
> > read_extent_buffer (fs/btrfs/extent_io.c:3742)
> > btrfs_get_name (fs/btrfs/export.c:289)
> > reconnect_path (fs/exportfs/expfs.c:222)
> > exportfs_decode_fh_raw (fs/exportfs/expfs.c:473)
> > do_handle_open (fs/fhandle.c:230)
> > do_syscall_64 (arch/x86/entry/syscall_64.c:94)
> > Kernel panic - not syncing: stack-protector: Kernel stack is corrupted
> >
> > Reject any name_len greater than BTRFS_NAME_LEN before the copy. Such a
> > name is never valid on disk, so this only rejects corrupted leaves and
> > leaves valid names unchanged.
> >
> > Fixes: 2ede0daf0154 ("Btrfs: handle NFS lookups properly")
> > Reported-by: Xiang Mei <xmei5@asu.edu>
> > Assisted-by: Claude:claude-opus-4-8
> > Signed-off-by: Weiming Shi <bestswngs@gmail.com>
> > ---
> > fs/btrfs/export.c | 10 ++++++++++
> > 1 file changed, 10 insertions(+)
> >
> > diff --git a/fs/btrfs/export.c b/fs/btrfs/export.c
> > index c403117ac..a54c6e8b3 100644
> > --- a/fs/btrfs/export.c
> > +++ b/fs/btrfs/export.c
> > @@ -285,6 +285,16 @@ static int btrfs_get_name(struct dentry *parent, char *name,
> > name_len = btrfs_inode_ref_name_len(leaf, iref);
> > }
> > + /* The caller's buffer is only NAME_MAX + 1 bytes. */
> > + if (name_len > BTRFS_NAME_LEN) {
>
> We do not play the whac-a-mole game by add random checks ad-hoc.
>
> Do the proper ROOT_REF_KEY and INODE_REF_KEY verification inside
> tree-checker.
>
> > + btrfs_err(fs_info,
> > + "corrupt name length %d for inode %llu in root %llu, max %d",
> > + name_len, btrfs_ino(BTRFS_I(inode)),
> > + btrfs_root_id(BTRFS_I(inode)->root), BTRFS_NAME_LEN);
> > + btrfs_free_path(path);
> > + return -EUCLEAN;
> > + }
> > +
> > read_extent_buffer(leaf, name, name_ptr, name_len);
> > btrfs_free_path(path);
>
Thanks for the review. v2 sent.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-06-08 9:58 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-07 12:14 [PATCH] btrfs: reject names longer than BTRFS_NAME_LEN in btrfs_get_name() Weiming Shi
2026-06-07 20:23 ` Miquel Sabaté Solà
2026-06-07 22:21 ` Qu Wenruo
2026-06-08 9:58 ` Weiming Shi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox