Commit 6ddedca2 authored by Kent Overstreet's avatar Kent Overstreet

bcachefs: Guard against unknown compression options

Since compression options now include compression level, proper
validation is a bit more involved.

This adds bch2_compression_opt_valid(), and plumbs it around
appropriately.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent ef435abd
...@@ -708,3 +708,13 @@ void bch2_opt_compression_to_text(struct printbuf *out, ...@@ -708,3 +708,13 @@ void bch2_opt_compression_to_text(struct printbuf *out,
if (opt.level) if (opt.level)
prt_printf(out, ":%u", opt.level); prt_printf(out, ":%u", opt.level);
} }
int bch2_opt_compression_validate(u64 v, struct printbuf *err)
{
if (!bch2_compression_opt_valid(v)) {
prt_printf(err, "invalid compression opt %llu", v);
return -BCH_ERR_invalid_sb_opt_compression;
}
return 0;
}
...@@ -4,12 +4,18 @@ ...@@ -4,12 +4,18 @@
#include "extents_types.h" #include "extents_types.h"
static const unsigned __bch2_compression_opt_to_type[] = {
#define x(t, n) [BCH_COMPRESSION_OPT_##t] = BCH_COMPRESSION_TYPE_##t,
BCH_COMPRESSION_OPTS()
#undef x
};
struct bch_compression_opt { struct bch_compression_opt {
u8 type:4, u8 type:4,
level:4; level:4;
}; };
static inline struct bch_compression_opt bch2_compression_decode(unsigned v) static inline struct bch_compression_opt __bch2_compression_decode(unsigned v)
{ {
return (struct bch_compression_opt) { return (struct bch_compression_opt) {
.type = v & 15, .type = v & 15,
...@@ -17,17 +23,25 @@ static inline struct bch_compression_opt bch2_compression_decode(unsigned v) ...@@ -17,17 +23,25 @@ static inline struct bch_compression_opt bch2_compression_decode(unsigned v)
}; };
} }
static inline bool bch2_compression_opt_valid(unsigned v)
{
struct bch_compression_opt opt = __bch2_compression_decode(v);
return opt.type < ARRAY_SIZE(__bch2_compression_opt_to_type) && !(!opt.type && opt.level);
}
static inline struct bch_compression_opt bch2_compression_decode(unsigned v)
{
return bch2_compression_opt_valid(v)
? __bch2_compression_decode(v)
: (struct bch_compression_opt) { 0 };
}
static inline unsigned bch2_compression_encode(struct bch_compression_opt opt) static inline unsigned bch2_compression_encode(struct bch_compression_opt opt)
{ {
return opt.type|(opt.level << 4); return opt.type|(opt.level << 4);
} }
static const unsigned __bch2_compression_opt_to_type[] = {
#define x(t, n) [BCH_COMPRESSION_OPT_##t] = BCH_COMPRESSION_TYPE_##t,
BCH_COMPRESSION_OPTS()
#undef x
};
static inline enum bch_compression_type bch2_compression_opt_to_type(unsigned v) static inline enum bch_compression_type bch2_compression_opt_to_type(unsigned v)
{ {
return __bch2_compression_opt_to_type[bch2_compression_decode(v).type]; return __bch2_compression_opt_to_type[bch2_compression_decode(v).type];
...@@ -46,10 +60,12 @@ int bch2_fs_compress_init(struct bch_fs *); ...@@ -46,10 +60,12 @@ int bch2_fs_compress_init(struct bch_fs *);
int bch2_opt_compression_parse(struct bch_fs *, const char *, u64 *, struct printbuf *); int bch2_opt_compression_parse(struct bch_fs *, const char *, u64 *, struct printbuf *);
void bch2_opt_compression_to_text(struct printbuf *, struct bch_fs *, struct bch_sb *, u64); void bch2_opt_compression_to_text(struct printbuf *, struct bch_fs *, struct bch_sb *, u64);
int bch2_opt_compression_validate(u64, struct printbuf *);
#define bch2_opt_compression (struct bch_opt_fn) { \ #define bch2_opt_compression (struct bch_opt_fn) { \
.parse = bch2_opt_compression_parse, \ .parse = bch2_opt_compression_parse, \
.to_text = bch2_opt_compression_to_text, \ .to_text = bch2_opt_compression_to_text, \
.validate = bch2_opt_compression_validate, \
} }
#endif /* _BCACHEFS_COMPRESS_H */ #endif /* _BCACHEFS_COMPRESS_H */
...@@ -213,6 +213,7 @@ ...@@ -213,6 +213,7 @@
x(BCH_ERR_invalid_sb, invalid_sb_crypt) \ x(BCH_ERR_invalid_sb, invalid_sb_crypt) \
x(BCH_ERR_invalid_sb, invalid_sb_clean) \ x(BCH_ERR_invalid_sb, invalid_sb_clean) \
x(BCH_ERR_invalid_sb, invalid_sb_quota) \ x(BCH_ERR_invalid_sb, invalid_sb_quota) \
x(BCH_ERR_invalid_sb, invalid_sb_opt_compression) \
x(BCH_ERR_invalid, invalid_bkey) \ x(BCH_ERR_invalid, invalid_bkey) \
x(BCH_ERR_operation_blocked, nocow_lock_blocked) \ x(BCH_ERR_operation_blocked, nocow_lock_blocked) \
x(EIO, btree_node_read_err) \ x(EIO, btree_node_read_err) \
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "bkey_methods.h" #include "bkey_methods.h"
#include "btree_update.h" #include "btree_update.h"
#include "buckets.h" #include "buckets.h"
#include "compress.h"
#include "error.h" #include "error.h"
#include "extents.h" #include "extents.h"
#include "extent_update.h" #include "extent_update.h"
...@@ -422,9 +423,10 @@ static int __bch2_inode_invalid(struct bkey_s_c k, struct printbuf *err) ...@@ -422,9 +423,10 @@ static int __bch2_inode_invalid(struct bkey_s_c k, struct printbuf *err)
return -BCH_ERR_invalid_bkey; return -BCH_ERR_invalid_bkey;
} }
if (unpacked.bi_compression >= BCH_COMPRESSION_OPT_NR + 1) { if (unpacked.bi_compression &&
prt_printf(err, "invalid data checksum type (%u >= %u)", !bch2_compression_opt_valid(unpacked.bi_compression - 1)) {
unpacked.bi_compression, BCH_COMPRESSION_OPT_NR + 1); prt_printf(err, "invalid compression opt %u",
unpacked.bi_compression - 1);
return -BCH_ERR_invalid_bkey; return -BCH_ERR_invalid_bkey;
} }
......
...@@ -294,6 +294,9 @@ int bch2_opt_validate(const struct bch_option *opt, u64 v, struct printbuf *err) ...@@ -294,6 +294,9 @@ int bch2_opt_validate(const struct bch_option *opt, u64 v, struct printbuf *err)
return -EINVAL; return -EINVAL;
} }
if (opt->fn.validate)
return opt->fn.validate(v, err);
return 0; return 0;
} }
......
...@@ -74,6 +74,7 @@ enum opt_type { ...@@ -74,6 +74,7 @@ enum opt_type {
struct bch_opt_fn { struct bch_opt_fn {
int (*parse)(struct bch_fs *, const char *, u64 *, struct printbuf *); int (*parse)(struct bch_fs *, const char *, u64 *, struct printbuf *);
void (*to_text)(struct printbuf *, struct bch_fs *, struct bch_sb *, u64); void (*to_text)(struct printbuf *, struct bch_fs *, struct bch_sb *, u64);
int (*validate)(u64, struct printbuf *);
}; };
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment