diff options
author | Theodore Ts'o <tytso@mit.edu> | 2021-07-28 13:51:13 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2021-07-28 14:40:49 -0400 |
commit | 225e5d093b519f9dbe9fcaacd995426f0e5194f6 (patch) | |
tree | 1917c5fc2b892c89ff2ce4ec7c4c0b95fb53dc7f /e2fsck | |
parent | 496669a2900e6be58dcf200b8ea1802a866ef3b8 (diff) | |
download | e2fsprogs-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>
Diffstat (limited to 'e2fsck')
-rw-r--r-- | e2fsck/pass2.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c index f00cb40e..bd974c55 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++; |