Skip to content

Commit 205da7c

Browse files
author
Kent Overstreet
committed
bcachefs: Don't trust sb->nr_devices in members_to_text()
We have to be able to print superblock sections even if they fail to validate (for debugging), so we have to calculate the number of entries from the field size. Reported-by: [email protected] Signed-off-by: Kent Overstreet <[email protected]>
1 parent 625c494 commit 205da7c

File tree

1 file changed

+30
-4
lines changed

1 file changed

+30
-4
lines changed

fs/bcachefs/sb-members.c

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -325,9 +325,17 @@ static void bch2_sb_members_v1_to_text(struct printbuf *out, struct bch_sb *sb,
325325
{
326326
struct bch_sb_field_members_v1 *mi = field_to_type(f, members_v1);
327327
struct bch_sb_field_disk_groups *gi = bch2_sb_field_get(sb, disk_groups);
328-
unsigned i;
329328

330-
for (i = 0; i < sb->nr_devices; i++)
329+
if (vstruct_end(&mi->field) <= (void *) &mi->_members[0]) {
330+
prt_printf(out, "field ends before start of entries");
331+
return;
332+
}
333+
334+
unsigned nr = (vstruct_end(&mi->field) - (void *) &mi->_members[0]) / sizeof(mi->_members[0]);
335+
if (nr != sb->nr_devices)
336+
prt_printf(out, "nr_devices mismatch: have %i entries, should be %u", nr, sb->nr_devices);
337+
338+
for (unsigned i = 0; i < min(sb->nr_devices, nr); i++)
331339
member_to_text(out, members_v1_get(mi, i), gi, sb, i);
332340
}
333341

@@ -341,9 +349,27 @@ static void bch2_sb_members_v2_to_text(struct printbuf *out, struct bch_sb *sb,
341349
{
342350
struct bch_sb_field_members_v2 *mi = field_to_type(f, members_v2);
343351
struct bch_sb_field_disk_groups *gi = bch2_sb_field_get(sb, disk_groups);
344-
unsigned i;
345352

346-
for (i = 0; i < sb->nr_devices; i++)
353+
if (vstruct_end(&mi->field) <= (void *) &mi->_members[0]) {
354+
prt_printf(out, "field ends before start of entries");
355+
return;
356+
}
357+
358+
if (!le16_to_cpu(mi->member_bytes)) {
359+
prt_printf(out, "member_bytes 0");
360+
return;
361+
}
362+
363+
unsigned nr = (vstruct_end(&mi->field) - (void *) &mi->_members[0]) / le16_to_cpu(mi->member_bytes);
364+
if (nr != sb->nr_devices)
365+
prt_printf(out, "nr_devices mismatch: have %i entries, should be %u", nr, sb->nr_devices);
366+
367+
/*
368+
* We call to_text() on superblock sections that haven't passed
369+
* validate, so we can't trust sb->nr_devices.
370+
*/
371+
372+
for (unsigned i = 0; i < min(sb->nr_devices, nr); i++)
347373
member_to_text(out, members_v2_get(mi, i), gi, sb, i);
348374
}
349375

0 commit comments

Comments
 (0)