Details
-
Bug
-
Resolution: Unresolved
-
Minor
-
None
-
None
-
None
-
3
-
9223372036854775807
Description
In check_dot() it assumes that the "." and ".." entries are fixed at 12-bytes, but with the dirdata feature storing a FID in these directory entries, they will be larger. If there is some unrelated problem in the directory returned by e2fsck_check_dirent_data() then this check will incorrectly cause the "." and ".." entries to be recreated and clobber the FIDs.
static int check_dot(...) { : dir_data_error = e2fsck_check_dirent_data(ctx, dirent, offset, pctx); : if (rec_len > 12) { new_len = rec_len - 12; if (new_len > 12 && dir_data_error) { if (created || fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) { nextdir = (struct ext2_dir_entry *) ((char *) dirent + 12); dirent->rec_len = 12; (void) ext2fs_set_rec_len(ctx->fs, new_len, nextdir); nextdir->inode = 0; ext2fs_dirent_set_name_len(nextdir, 0); ext2fs_dirent_set_file_type(nextdir, EXT2_FT_UNKNOWN);
As a follow-on, the HTree index will no longer immediately follow the ".." entry (fake_root) and be invalidated:
Directory entry for '.' in ... (1032783) is big. Split? no Second entry '3.3.0' (inode=538027 fid=[0x380020941:0x4c38:0x0]) in directory inode 1032783 should be '..' Fix? no
The code in check_dot() needs to be updated to properly check for the length of dirdata entries.
It doesn't look like same bug appears in check_dotdot(). It is checking for (rec_len < 12), which should be OK, since dirdata entries will always be larger. Properly accounting for rec_len in check_dot() should avoid any problems in check_dotdot(). However, there is LU-7399 which suggests an improvement for rebuilding ".." in other situations.
With dirdata enabled, the ".." entry may not be at offset 12, so it would be more graceful to do a quick scan to see if ".." is at offset "12+20=32" (1 byte NUL + 1 byte size + 16 byte lu_fid + alignment). That wouldn't "preserve" the dirdata for "." but it might keep it for "..", which is more important anyway (for fid2path).