Skip to content

Commit d5bd378

Browse files
author
Kent Overstreet
committed
bcachefs: Add missing validation for jset_entry_data_usage
Validation was completely missing for replicas entries in the journal (not the superblock replicas section) - we can't have replicas entries pointing to invalid devices. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
1 parent bbc3a46 commit d5bd378

4 files changed

Lines changed: 53 additions & 31 deletions

File tree

fs/bcachefs/errcode.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@
210210
x(BCH_ERR_invalid_sb, invalid_sb_members) \
211211
x(BCH_ERR_invalid_sb, invalid_sb_disk_groups) \
212212
x(BCH_ERR_invalid_sb, invalid_sb_replicas) \
213+
x(BCH_ERR_invalid_sb, invalid_replicas_entry) \
213214
x(BCH_ERR_invalid_sb, invalid_sb_journal) \
214215
x(BCH_ERR_invalid_sb, invalid_sb_journal_seq_blacklist) \
215216
x(BCH_ERR_invalid_sb, invalid_sb_crypt) \

fs/bcachefs/journal_io.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,7 @@ static int journal_entry_data_usage_validate(struct bch_fs *c,
547547
struct jset_entry_data_usage *u =
548548
container_of(entry, struct jset_entry_data_usage, entry);
549549
unsigned bytes = jset_u64s(le16_to_cpu(entry->u64s)) * sizeof(u64);
550+
struct printbuf err = PRINTBUF;
550551
int ret = 0;
551552

552553
if (journal_entry_err_on(bytes < sizeof(*u) ||
@@ -555,10 +556,19 @@ static int journal_entry_data_usage_validate(struct bch_fs *c,
555556
journal_entry_data_usage_bad_size,
556557
"invalid journal entry usage: bad size")) {
557558
journal_entry_null_range(entry, vstruct_next(entry));
558-
return ret;
559+
goto out;
559560
}
560561

562+
if (journal_entry_err_on(bch2_replicas_entry_validate(&u->r, c->disk_sb.sb, &err),
563+
c, version, jset, entry,
564+
journal_entry_data_usage_bad_size,
565+
"invalid journal entry usage: %s", err.buf)) {
566+
journal_entry_null_range(entry, vstruct_next(entry));
567+
goto out;
568+
}
569+
out:
561570
fsck_err:
571+
printbuf_exit(&err);
562572
return ret;
563573
}
564574

fs/bcachefs/replicas.c

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,33 @@ void bch2_replicas_entry_to_text(struct printbuf *out,
6868
prt_printf(out, "]");
6969
}
7070

71+
int bch2_replicas_entry_validate(struct bch_replicas_entry *r,
72+
struct bch_sb *sb,
73+
struct printbuf *err)
74+
{
75+
if (!r->nr_devs) {
76+
prt_printf(err, "no devices in entry ");
77+
goto bad;
78+
}
79+
80+
if (r->nr_required > 1 &&
81+
r->nr_required >= r->nr_devs) {
82+
prt_printf(err, "bad nr_required in entry ");
83+
goto bad;
84+
}
85+
86+
for (unsigned i = 0; i < r->nr_devs; i++)
87+
if (!bch2_dev_exists(sb, r->devs[i])) {
88+
prt_printf(err, "invalid device %u in entry ", r->devs[i]);
89+
goto bad;
90+
}
91+
92+
return 0;
93+
bad:
94+
bch2_replicas_entry_to_text(err, r);
95+
return -BCH_ERR_invalid_replicas_entry;
96+
}
97+
7198
void bch2_cpu_replicas_to_text(struct printbuf *out,
7299
struct bch_replicas_cpu *r)
73100
{
@@ -163,7 +190,8 @@ void bch2_devlist_to_replicas(struct bch_replicas_entry *e,
163190
}
164191

165192
static struct bch_replicas_cpu
166-
cpu_replicas_add_entry(struct bch_replicas_cpu *old,
193+
cpu_replicas_add_entry(struct bch_fs *c,
194+
struct bch_replicas_cpu *old,
167195
struct bch_replicas_entry *new_entry)
168196
{
169197
unsigned i;
@@ -173,6 +201,9 @@ cpu_replicas_add_entry(struct bch_replicas_cpu *old,
173201
replicas_entry_bytes(new_entry)),
174202
};
175203

204+
for (i = 0; i < new_entry->nr_devs; i++)
205+
BUG_ON(!bch2_dev_exists2(c, new_entry->devs[i]));
206+
176207
BUG_ON(!new_entry->data_type);
177208
verify_replicas_entry(new_entry);
178209

@@ -382,15 +413,15 @@ static int bch2_mark_replicas_slowpath(struct bch_fs *c,
382413

383414
if (c->replicas_gc.entries &&
384415
!__replicas_has_entry(&c->replicas_gc, new_entry)) {
385-
new_gc = cpu_replicas_add_entry(&c->replicas_gc, new_entry);
416+
new_gc = cpu_replicas_add_entry(c, &c->replicas_gc, new_entry);
386417
if (!new_gc.entries) {
387418
ret = -BCH_ERR_ENOMEM_cpu_replicas;
388419
goto err;
389420
}
390421
}
391422

392423
if (!__replicas_has_entry(&c->replicas, new_entry)) {
393-
new_r = cpu_replicas_add_entry(&c->replicas, new_entry);
424+
new_r = cpu_replicas_add_entry(c, &c->replicas, new_entry);
394425
if (!new_r.entries) {
395426
ret = -BCH_ERR_ENOMEM_cpu_replicas;
396427
goto err;
@@ -598,7 +629,7 @@ int bch2_replicas_set_usage(struct bch_fs *c,
598629
if (idx < 0) {
599630
struct bch_replicas_cpu n;
600631

601-
n = cpu_replicas_add_entry(&c->replicas, r);
632+
n = cpu_replicas_add_entry(c, &c->replicas, r);
602633
if (!n.entries)
603634
return -BCH_ERR_ENOMEM_cpu_replicas;
604635

@@ -797,7 +828,7 @@ static int bch2_cpu_replicas_validate(struct bch_replicas_cpu *cpu_r,
797828
struct bch_sb *sb,
798829
struct printbuf *err)
799830
{
800-
unsigned i, j;
831+
unsigned i;
801832

802833
sort_cmp_size(cpu_r->entries,
803834
cpu_r->nr,
@@ -808,31 +839,9 @@ static int bch2_cpu_replicas_validate(struct bch_replicas_cpu *cpu_r,
808839
struct bch_replicas_entry *e =
809840
cpu_replicas_entry(cpu_r, i);
810841

811-
if (e->data_type >= BCH_DATA_NR) {
812-
prt_printf(err, "invalid data type in entry ");
813-
bch2_replicas_entry_to_text(err, e);
814-
return -BCH_ERR_invalid_sb_replicas;
815-
}
816-
817-
if (!e->nr_devs) {
818-
prt_printf(err, "no devices in entry ");
819-
bch2_replicas_entry_to_text(err, e);
820-
return -BCH_ERR_invalid_sb_replicas;
821-
}
822-
823-
if (e->nr_required > 1 &&
824-
e->nr_required >= e->nr_devs) {
825-
prt_printf(err, "bad nr_required in entry ");
826-
bch2_replicas_entry_to_text(err, e);
827-
return -BCH_ERR_invalid_sb_replicas;
828-
}
829-
830-
for (j = 0; j < e->nr_devs; j++)
831-
if (!bch2_dev_exists(sb, e->devs[j])) {
832-
prt_printf(err, "invalid device %u in entry ", e->devs[j]);
833-
bch2_replicas_entry_to_text(err, e);
834-
return -BCH_ERR_invalid_sb_replicas;
835-
}
842+
int ret = bch2_replicas_entry_validate(e, sb, err);
843+
if (ret)
844+
return ret;
836845

837846
if (i + 1 < cpu_r->nr) {
838847
struct bch_replicas_entry *n =

fs/bcachefs/replicas.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
void bch2_replicas_entry_sort(struct bch_replicas_entry *);
1010
void bch2_replicas_entry_to_text(struct printbuf *,
1111
struct bch_replicas_entry *);
12+
int bch2_replicas_entry_validate(struct bch_replicas_entry *,
13+
struct bch_sb *, struct printbuf *);
1214
void bch2_cpu_replicas_to_text(struct printbuf *, struct bch_replicas_cpu *);
1315

1416
static inline struct bch_replicas_entry *

0 commit comments

Comments
 (0)