From 4ea4bad1c64dc0b56ab78f5c5335eca73e086969 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Wed, 11 May 2022 14:06:02 -0700 Subject: [PATCH] Add scoutfs_item_lookup_within Add a lookup variant that returns an error if the item value is larger than the caller's value buffer size, rather than truncating and returning the truncated size. Signed-off-by: Zach Brown --- kmod/src/item.c | 25 ++++++++++++++++++++++--- kmod/src/item.h | 2 ++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/kmod/src/item.c b/kmod/src/item.c index 05b04550..76094553 100644 --- a/kmod/src/item.c +++ b/kmod/src/item.c @@ -1697,8 +1697,8 @@ static int copy_val(void *dst, int dst_len, void *src, int src_len) * The amount of bytes copied is returned which can be 0 or truncated if * the caller's buffer isn't big enough. */ -int scoutfs_item_lookup(struct super_block *sb, struct scoutfs_key *key, - void *val, int val_len, struct scoutfs_lock *lock) +static int item_lookup(struct super_block *sb, struct scoutfs_key *key, + void *val, int val_len, int len_limit, struct scoutfs_lock *lock) { DECLARE_ITEM_CACHE_INFO(sb, cinf); struct cached_item *item; @@ -1718,6 +1718,8 @@ int scoutfs_item_lookup(struct super_block *sb, struct scoutfs_key *key, item = item_rbtree_walk(&pg->item_root, key, NULL, NULL, NULL); if (!item || item->deletion) ret = -ENOENT; + else if (len_limit > 0 && item->val_len > len_limit) + ret = -EIO; else ret = copy_val(val, val_len, item->val, item->val_len); @@ -1726,13 +1728,30 @@ out: return ret; } +int scoutfs_item_lookup(struct super_block *sb, struct scoutfs_key *key, + void *val, int val_len, struct scoutfs_lock *lock) +{ + return item_lookup(sb, key, val, val_len, 0, lock); +} + +/* + * Return -EIO if the item we find has a value larger than the caller's + * val_len, rather than truncating and returning the size of the copied + * value. + */ +int scoutfs_item_lookup_within(struct super_block *sb, struct scoutfs_key *key, + void *val, int val_len, struct scoutfs_lock *lock) +{ + return item_lookup(sb, key, val, val_len, val_len, lock); +} + int scoutfs_item_lookup_exact(struct super_block *sb, struct scoutfs_key *key, void *val, int val_len, struct scoutfs_lock *lock) { int ret; - ret = scoutfs_item_lookup(sb, key, val, val_len, lock); + ret = item_lookup(sb, key, val, val_len, 0, lock); if (ret == val_len) ret = 0; else if (ret >= 0) diff --git a/kmod/src/item.h b/kmod/src/item.h index 431866d5..89b3f7ae 100644 --- a/kmod/src/item.h +++ b/kmod/src/item.h @@ -3,6 +3,8 @@ int scoutfs_item_lookup(struct super_block *sb, struct scoutfs_key *key, void *val, int val_len, struct scoutfs_lock *lock); +int scoutfs_item_lookup_within(struct super_block *sb, struct scoutfs_key *key, + void *val, int val_len, struct scoutfs_lock *lock); int scoutfs_item_lookup_exact(struct super_block *sb, struct scoutfs_key *key, void *val, int val_len, struct scoutfs_lock *lock);