]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
libext2fs: fix data read corruption in ext2fs_file_read_inline_data
authorDarrick J. Wong <djwong@kernel.org>
Thu, 17 Jul 2025 14:59:33 +0000 (07:59 -0700)
committerTheodore Ts'o <tytso@mit.edu>
Thu, 31 Jul 2025 14:41:55 +0000 (10:41 -0400)
Fix numerous problems in the function that reads data from an inlinedata
file:

 - Reads starting after isize should be returned as short reads.
 - Reads past the end of the inline data should return zeroes.
 - Reads from the inline data buffer must not exceed isize.

Cc: linux-ext4@vger.kernel.org # v1.43
Fixes: 54e880b870f7fe ("libext2fs: handle inline data in read/write function")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Link: https://lore.kernel.org/r/20250717145933.GI2672022@frogsfrogsfrogs
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
lib/ext2fs/fileio.c

index 818f7f054200292f2f34753d25dbaedeca241c65..900002c529568235df4f4cc121446e30cfd09f40 100644 (file)
@@ -255,18 +255,26 @@ ext2fs_file_read_inline_data(ext2_file_t file, void *buf,
                             unsigned int wanted, unsigned int *got)
 {
        ext2_filsys fs;
-       errcode_t retval;
+       errcode_t retval = 0;
        unsigned int count = 0;
+       uint64_t isize = EXT2_I_SIZE(&file->inode);
        size_t size;
 
+       if (file->pos >= isize)
+               goto out;
+
        fs = file->fs;
        retval = ext2fs_inline_data_get(fs, file->ino, &file->inode,
                                        file->buf, &size);
        if (retval)
                return retval;
 
-       if (file->pos >= size)
-               goto out;
+       /*
+        * size is the number of bytes available for inline data storage, which
+        * means it can exceed isize.
+        */
+       if (size > isize)
+               size = isize;
 
        count = size - file->pos;
        if (count > wanted)
@@ -275,6 +283,14 @@ ext2fs_file_read_inline_data(ext2_file_t file, void *buf,
        file->pos += count;
        buf = (char *) buf + count;
 
+       /* zero-fill the rest of the buffer */
+       wanted -= count;
+       if (wanted > 0) {
+               memset(buf, 0, wanted);
+               file->pos += wanted;
+               count += wanted;
+       }
+
 out:
        if (got)
                *got = count;