mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 06:02:05 +00:00
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: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
ef435abd6a
commit
6ddedca218
@ -708,3 +708,13 @@ void bch2_opt_compression_to_text(struct printbuf *out,
|
||||
if (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 @@
|
||||
|
||||
#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 {
|
||||
u8 type: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) {
|
||||
.type = v & 15,
|
||||
@ -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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return __bch2_compression_opt_to_type[bch2_compression_decode(v).type];
|
||||
@ -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 *);
|
||||
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) { \
|
||||
.parse = bch2_opt_compression_parse, \
|
||||
.to_text = bch2_opt_compression_to_text, \
|
||||
.validate = bch2_opt_compression_validate, \
|
||||
}
|
||||
|
||||
#endif /* _BCACHEFS_COMPRESS_H */
|
||||
|
@ -213,6 +213,7 @@
|
||||
x(BCH_ERR_invalid_sb, invalid_sb_crypt) \
|
||||
x(BCH_ERR_invalid_sb, invalid_sb_clean) \
|
||||
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_operation_blocked, nocow_lock_blocked) \
|
||||
x(EIO, btree_node_read_err) \
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "bkey_methods.h"
|
||||
#include "btree_update.h"
|
||||
#include "buckets.h"
|
||||
#include "compress.h"
|
||||
#include "error.h"
|
||||
#include "extents.h"
|
||||
#include "extent_update.h"
|
||||
@ -422,9 +423,10 @@ static int __bch2_inode_invalid(struct bkey_s_c k, struct printbuf *err)
|
||||
return -BCH_ERR_invalid_bkey;
|
||||
}
|
||||
|
||||
if (unpacked.bi_compression >= BCH_COMPRESSION_OPT_NR + 1) {
|
||||
prt_printf(err, "invalid data checksum type (%u >= %u)",
|
||||
unpacked.bi_compression, BCH_COMPRESSION_OPT_NR + 1);
|
||||
if (unpacked.bi_compression &&
|
||||
!bch2_compression_opt_valid(unpacked.bi_compression - 1)) {
|
||||
prt_printf(err, "invalid compression opt %u",
|
||||
unpacked.bi_compression - 1);
|
||||
return -BCH_ERR_invalid_bkey;
|
||||
}
|
||||
|
||||
|
@ -294,6 +294,9 @@ int bch2_opt_validate(const struct bch_option *opt, u64 v, struct printbuf *err)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (opt->fn.validate)
|
||||
return opt->fn.validate(v, err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -74,6 +74,7 @@ enum opt_type {
|
||||
struct bch_opt_fn {
|
||||
int (*parse)(struct bch_fs *, const char *, u64 *, struct printbuf *);
|
||||
void (*to_text)(struct printbuf *, struct bch_fs *, struct bch_sb *, u64);
|
||||
int (*validate)(u64, struct printbuf *);
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user