diff --git a/kmod/src/count.h b/kmod/src/count.h index b763cc2b..4198dbf5 100644 --- a/kmod/src/count.h +++ b/kmod/src/count.h @@ -54,7 +54,7 @@ static inline void scoutfs_count_dirents(struct scoutfs_item_count *cnt, static inline void scoutfs_count_sym_target(struct scoutfs_item_count *cnt, unsigned size) { - unsigned nr = DIV_ROUND_UP(size, SCOUTFS_SYMLINK_MAX_VAL_SIZE); + unsigned nr = DIV_ROUND_UP(size, SCOUTFS_MAX_VAL_SIZE); cnt->items += nr; cnt->keys += nr * sizeof(struct scoutfs_symlink_key); diff --git a/kmod/src/dir.c b/kmod/src/dir.c index 04461e75..52448cd5 100644 --- a/kmod/src/dir.c +++ b/kmod/src/dir.c @@ -661,7 +661,7 @@ enum { SYM_DELETE, }; static int symlink_item_ops(struct super_block *sb, int op, u64 ino, - const char *target, int size) + const char *target, size_t size) { struct scoutfs_symlink_key skey; struct scoutfs_key_buf key; @@ -671,15 +671,15 @@ static int symlink_item_ops(struct super_block *sb, int op, u64 ino, int ret; int i; - if (WARN_ON_ONCE(size <= 0 || size > SCOUTFS_SYMLINK_MAX_SIZE || + if (WARN_ON_ONCE(size == 0 || size > SCOUTFS_SYMLINK_MAX_SIZE || op > SYM_DELETE)) return -EINVAL; - nr = DIV_ROUND_UP(size, SCOUTFS_SYMLINK_MAX_VAL_SIZE); + nr = DIV_ROUND_UP(size, SCOUTFS_MAX_VAL_SIZE); for (i = 0; i < nr; i++) { init_symlink_key(&key, &skey, ino, i); - bytes = min(size, SCOUTFS_SYMLINK_MAX_VAL_SIZE); + bytes = min(size, SCOUTFS_MAX_VAL_SIZE); scoutfs_kvec_init(val, (void *)target, bytes); if (op == SYM_CREATE) @@ -691,7 +691,7 @@ static int symlink_item_ops(struct super_block *sb, int op, u64 ino, if (ret) break; - target += SCOUTFS_SYMLINK_MAX_VAL_SIZE; + target += SCOUTFS_MAX_VAL_SIZE; size -= bytes; } diff --git a/kmod/src/format.h b/kmod/src/format.h index fc36d50e..c511d51a 100644 --- a/kmod/src/format.h +++ b/kmod/src/format.h @@ -260,8 +260,6 @@ struct scoutfs_symlink_key { __u8 nr; } __packed; -#define SCOUTFS_SYMLINK_MAX_VAL_SIZE 200 - struct scoutfs_betimespec { __be64 sec; __be32 nsec; @@ -377,13 +375,6 @@ struct scoutfs_dirent { /* S32_MAX avoids the (int) sign bit and might avoid sloppy bugs */ #define SCOUTFS_LINK_MAX S32_MAX -#define SCOUTFS_XATTR_MAX_NAME_LEN 255 -#define SCOUTFS_XATTR_MAX_SIZE 65536 -#define SCOUTFS_XATTR_PART_SIZE \ - (SCOUTFS_BLOCK_SIZE - sizeof(struct scoutfs_xattr_val_header)) -#define SCOUTFS_XATTR_MAX_PARTS \ - DIV_ROUND_UP(SCOUTFS_XATTR_MAX_SIZE, SCOUTFS_XATTR_PART_SIZE) - /* entries begin after . and .. */ #define SCOUTFS_DIRENT_FIRST_POS 2 /* getdents returns next pos with an entry, no entry at (f_pos)~0 */ @@ -404,6 +395,18 @@ enum { #define SCOUTFS_MAX_KEY_SIZE \ offsetof(struct scoutfs_link_backref_key, name[SCOUTFS_NAME_LEN + 1]) +/* largest single val are dirents, larger broken up into units of this */ +#define SCOUTFS_MAX_VAL_SIZE \ + offsetof(struct scoutfs_dirent, name[SCOUTFS_NAME_LEN]) + +#define SCOUTFS_XATTR_MAX_NAME_LEN 255 +#define SCOUTFS_XATTR_MAX_SIZE 65536 +#define SCOUTFS_XATTR_PART_SIZE \ + (SCOUTFS_MAX_VAL_SIZE - sizeof(struct scoutfs_xattr_val_header)) +#define SCOUTFS_XATTR_MAX_PARTS \ + DIV_ROUND_UP(SCOUTFS_XATTR_MAX_SIZE, SCOUTFS_XATTR_PART_SIZE) + + /* * messages over the wire. */ diff --git a/kmod/src/item.c b/kmod/src/item.c index 79b18f60..6135b0eb 100644 --- a/kmod/src/item.c +++ b/kmod/src/item.c @@ -41,6 +41,12 @@ * clobber them in creation and skip them in lookups. */ +static bool invalid_key_val(struct scoutfs_key_buf *key, struct kvec *val) +{ + return WARN_ON_ONCE(key->key_len > SCOUTFS_MAX_KEY_SIZE || + (val && (scoutfs_kvec_length(val) > SCOUTFS_MAX_VAL_SIZE))); +} + static bool invalid_flags(int sif) { return (sif & SIF_EXCLUSIVE) && (sif & SIF_REPLACE); @@ -992,6 +998,9 @@ int scoutfs_item_create(struct super_block *sb, struct scoutfs_key_buf *key, unsigned long flags; int ret; + if (invalid_key_val(key, val)) + return -EINVAL; + item = alloc_item(sb, key, val); if (!item) return -ENOMEM; @@ -1021,6 +1030,9 @@ int scoutfs_item_add_batch(struct super_block *sb, struct list_head *list, struct cached_item *item; int ret; + if (invalid_key_val(key, val)) + return -EINVAL; + item = alloc_item(sb, key, val); if (item) { list_add_tail(&item->entry, list); @@ -1128,6 +1140,11 @@ int scoutfs_item_set_batch(struct super_block *sb, struct list_head *list, if (WARN_ON_ONCE(invalid_flags(sif))) return -EINVAL; + list_for_each_entry(item, list, entry) { + if (invalid_key_val(item->key, item->val)) + return -EINVAL; + } + trace_scoutfs_item_set_batch(sb, start, end); if (WARN_ON_ONCE(scoutfs_key_compare(start, end) > 0)) @@ -1283,6 +1300,9 @@ int scoutfs_item_update(struct super_block *sb, struct scoutfs_key_buf *key, unsigned long flags; int ret; + if (invalid_key_val(key, val)) + return -EINVAL; + end = scoutfs_key_alloc(sb, SCOUTFS_MAX_KEY_SIZE); if (!end) { ret = -ENOMEM;