aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2021-07-28 13:51:13 -0400
committerTheodore Ts'o <tytso@mit.edu>2021-07-28 14:40:49 -0400
commit225e5d093b519f9dbe9fcaacd995426f0e5194f6 (patch)
tree1917c5fc2b892c89ff2ce4ec7c4c0b95fb53dc7f
parent496669a2900e6be58dcf200b8ea1802a866ef3b8 (diff)
downloade2fsprogs-225e5d093b519f9dbe9fcaacd995426f0e5194f6.tar.gz
e2fsck: fix f_baddotdir failure on big-endian systems
Commit 63f44aafb1f2 ("e2fsck: fix ".." more gracefully if possible") changed the check_dot() function to try to avoid resetting the '..' entry when the '.' entry is too large.. But if we do that, then on big-endian systems, we need to try byte swapping the rest of the directory entries, or else the f_baddotdir test will fail on big-endian systems. Also add a check to avoid UBSAN warning when there is not enough space at the end of the directory block for a directory entry, and so we can potentially overflow some pointer arithmetic when trying to byte swap the remainder of the (negative) space in the directory block. Fixes: 63f44aafb1f2 ("e2fsck: fix ".." more gracefully if possible") Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r--e2fsck/pass2.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c
index f00cb40e0..bd974c551 100644
--- a/e2fsck/pass2.c
+++ b/e2fsck/pass2.c
@@ -458,6 +458,12 @@ static int check_dot(e2fsck_t ctx,
ext2fs_dirent_set_name_len(nextdir, 0);
ext2fs_dirent_set_file_type(nextdir,
ftype);
+#ifdef WORDS_BIGENDIAN
+ } else {
+ (void) ext2fs_dirent_swab_in2(ctx->fs,
+ (char *) nextdir,
+ ctx->fs->blocksize - 12, 0);
+#endif
}
status = 1;
}
@@ -1370,12 +1376,14 @@ skip_checksum:
hash_in_dirent);
#ifdef WORDS_BIGENDIAN
if (need_reswab) {
+ unsigned int len;
+
(void) ext2fs_get_rec_len(fs,
- dirent, &rec_len);
- ext2fs_dirent_swab_in2(fs,
- ((char *)dirent) + offset + rec_len,
- max_block_size - offset - rec_len,
- 0);
+ dirent, &len);
+ len += offset;
+ if (max_block_size > len)
+ ext2fs_dirent_swab_in2(fs,
+ ((char *)dirent) + len, max_block_size - len, 0);
}
#endif
dir_modified++;