aboutsummaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorSam Edwards <cfsworks@gmail.com>2023-11-11 08:19:04 -0700
committerTom Rini <trini@konsulko.com>2023-11-16 18:59:58 -0500
commit6d6ea52b629c384fb8605678b9003d2a077f9148 (patch)
treeb721c9f59b665421dc5ef8ebcee9d38edf8cf12b /fs
parentdfeb4f0d79351dc0256b45c7a9f26c752c4e0e09 (diff)
downloadu-boot-6d6ea52b629c384fb8605678b9003d2a077f9148.zip
u-boot-6d6ea52b629c384fb8605678b9003d2a077f9148.tar.gz
u-boot-6d6ea52b629c384fb8605678b9003d2a077f9148.tar.bz2
fs: btrfs: fix reading when length specified
The btrfs read function limits the read length to ensure that it and the read offset do not together exceed the size of the file. However, this size was only being queried if the read length was passed a value of zero (meaning "whole file"), and the size is defaulted to 0 otherwise. This means the clamp will just zero out the length if one is specified, preventing reading of the file. Fix this by checking the file size unconditionally, and unifying the default length and clamping logic as a single range check instead. This bug was discovered when trying to boot Linux with initrd= via 'bootefi' from a btrfs partition. The EFI stub entered an infinite loop of zero-length reads while trying to read the initrd, and the boot process stalled indefinitely. Signed-off-by: Sam Edwards <CFSworks@gmail.com> Reviewed-by: Qu Wenruo <wqu@suse.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/btrfs.c15
1 files changed, 6 insertions, 9 deletions
diff --git a/fs/btrfs/btrfs.c b/fs/btrfs/btrfs.c
index 4cdbbbe..1149a3b 100644
--- a/fs/btrfs/btrfs.c
+++ b/fs/btrfs/btrfs.c
@@ -228,7 +228,7 @@ int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len,
{
struct btrfs_fs_info *fs_info = current_fs_info;
struct btrfs_root *root;
- loff_t real_size = 0;
+ loff_t real_size;
u64 ino;
u8 type;
int ret;
@@ -246,16 +246,13 @@ int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len,
return -EINVAL;
}
- if (!len) {
- ret = btrfs_size(file, &real_size);
- if (ret < 0) {
- error("Failed to get inode size: %s", file);
- return ret;
- }
- len = real_size;
+ ret = btrfs_size(file, &real_size);
+ if (ret < 0) {
+ error("Failed to get inode size: %s", file);
+ return ret;
}
- if (len > real_size - offset)
+ if (!len || len > real_size - offset)
len = real_size - offset;
ret = btrfs_file_read(root, ino, offset, len, buf);