From d202f46d81c6ca8a0dbce2053cf8114bd68a3ddc Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 22 Jul 2017 16:08:25 -0400 Subject: [PATCH] e2fsck: check for invalid quota inode numbers If the superblock has invalid inode numbers for the user, group, or project quota inodes, e2fsck should notice and offer to fix things by zeroing out the invalid superblock field. Signed-off-by: Theodore Ts'o --- e2fsck/e2fsck.h | 1 + e2fsck/problem.c | 5 +++++ e2fsck/problem.h | 3 +++ e2fsck/quota.c | 31 +++++++++++++++++++++++++++++++ e2fsck/super.c | 2 ++ tests/f_quota_invalid_inum/expect.1 | 15 +++++++++++++++ tests/f_quota_invalid_inum/expect.2 | 7 +++++++ tests/f_quota_invalid_inum/image.gz | Bin 0 -> 583 bytes tests/f_quota_invalid_inum/name | 1 + 9 files changed, 65 insertions(+) create mode 100644 tests/f_quota_invalid_inum/expect.1 create mode 100644 tests/f_quota_invalid_inum/expect.2 create mode 100644 tests/f_quota_invalid_inum/image.gz create mode 100644 tests/f_quota_invalid_inum/name diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h index 6ab4f9c..81c09d7 100644 --- a/e2fsck/e2fsck.h +++ b/e2fsck/e2fsck.h @@ -505,6 +505,7 @@ extern void set_up_logging(e2fsck_t ctx); /* quota.c */ extern void e2fsck_hide_quota(e2fsck_t ctx); +extern void e2fsck_validate_quota_inodes(e2fsck_t ctx); /* pass1.c */ extern errcode_t e2fsck_setup_icount(e2fsck_t ctx, const char *icount_name, diff --git a/e2fsck/problem.c b/e2fsck/problem.c index 5359d6b..c4c5542 100644 --- a/e2fsck/problem.c +++ b/e2fsck/problem.c @@ -488,6 +488,11 @@ static struct e2fsck_problem problem_table[] = { N_("Bad desired extra isize in @S (%N). "), PROMPT_FIX, 0 }, + /* Invalid quota inode number */ + { PR_0_INVALID_QUOTA_INO, + N_("Invalid %U @q @i %i. "), + PROMPT_FIX, 0 }, + /* Pass 1 errors */ /* Pass 1: Checking inodes, blocks, and sizes */ diff --git a/e2fsck/problem.h b/e2fsck/problem.h index d291e26..c949547 100644 --- a/e2fsck/problem.h +++ b/e2fsck/problem.h @@ -279,6 +279,9 @@ struct problem_context { /* Bad desired extra isize in superblock */ #define PR_0_BAD_WANT_EXTRA_ISIZE 0x00004E +/* Invalid quota inode number */ +#define PR_0_INVALID_QUOTA_INO 0x00004F + /* * Pass 1 errors diff --git a/e2fsck/quota.c b/e2fsck/quota.c index 173997e..b0f9af6 100644 --- a/e2fsck/quota.c +++ b/e2fsck/quota.c @@ -79,8 +79,39 @@ void e2fsck_hide_quota(e2fsck_t ctx) fix_problem(ctx, PR_0_HIDE_QUOTA, &pctx)) { move_quota_inode(fs, pctx.ino, quota_ino, qtype); *quota_sb_inump(sb, qtype) = quota_ino; + ext2fs_mark_super_dirty(fs); } } return; } + +void e2fsck_validate_quota_inodes(e2fsck_t ctx) +{ + struct ext2_super_block *sb = ctx->fs->super; + struct problem_context pctx; + ext2_filsys fs = ctx->fs; + enum quota_type qtype; + ext2_ino_t quota_ino; + + clear_problem_context(&pctx); + + for (qtype = 0; qtype < MAXQUOTAS; qtype++) { + pctx.ino = *quota_sb_inump(sb, qtype); + pctx.num = qtype; + if (pctx.ino && + ((pctx.ino == EXT2_BAD_INO) || + (pctx.ino == EXT2_ROOT_INO) || + (pctx.ino == EXT2_BOOT_LOADER_INO) || + (pctx.ino == EXT2_UNDEL_DIR_INO) || + (pctx.ino == EXT2_RESIZE_INO) || + (pctx.ino == EXT2_JOURNAL_INO) || + (pctx.ino == EXT2_EXCLUDE_INO) || + (pctx.ino == EXT4_REPLICA_INO) || + (pctx.ino > fs->super->s_inodes_count)) && + fix_problem(ctx, PR_0_INVALID_QUOTA_INO, &pctx)) { + *quota_sb_inump(sb, qtype) = 0; + ext2fs_mark_super_dirty(fs); + } + } +} diff --git a/e2fsck/super.c b/e2fsck/super.c index d2fd922..8153f2b 100644 --- a/e2fsck/super.c +++ b/e2fsck/super.c @@ -910,6 +910,8 @@ void check_super_block(e2fsck_t ctx) } } + e2fsck_validate_quota_inodes(ctx); + /* * Move the ext3 journal file, if necessary. */ diff --git a/tests/f_quota_invalid_inum/expect.1 b/tests/f_quota_invalid_inum/expect.1 new file mode 100644 index 0000000..a989f16 --- /dev/null +++ b/tests/f_quota_invalid_inum/expect.1 @@ -0,0 +1,15 @@ +Invalid user quota inode 808464432. Fix? yes + +Invalid group quota inode 808464432. Fix? yes + +Invalid group quota inode 808464432. Fix? yes + +Pass 1: Checking inodes, blocks, and sizes +Pass 2: Checking directory structure +Pass 3: Checking directory connectivity +Pass 4: Checking reference counts +Pass 5: Checking group summary information + +test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** +test_filesys: 11/16 files (0.0% non-contiguous), 21/100 blocks +Exit status is 1 diff --git a/tests/f_quota_invalid_inum/expect.2 b/tests/f_quota_invalid_inum/expect.2 new file mode 100644 index 0000000..41ceefb --- /dev/null +++ b/tests/f_quota_invalid_inum/expect.2 @@ -0,0 +1,7 @@ +Pass 1: Checking inodes, blocks, and sizes +Pass 2: Checking directory structure +Pass 3: Checking directory connectivity +Pass 4: Checking reference counts +Pass 5: Checking group summary information +test_filesys: 11/16 files (0.0% non-contiguous), 21/100 blocks +Exit status is 0 diff --git a/tests/f_quota_invalid_inum/image.gz b/tests/f_quota_invalid_inum/image.gz new file mode 100644 index 0000000000000000000000000000000000000000..28be80efe972be0f9c3fda38619ae45e9bbffdd0 GIT binary patch literal 583 zcmb2|=3uz8t~ip3`R(2P*}{o3><_-{ae75B(aO3jQYhq9(lvSQi${wdg~W7;h>CV! zvD&faudoY?yJO6fkaoT@;e}1j8c{2nN`y-VTwU)xnk}#E`kH^ums?LNAIz@S{~j0j zZpZoGX`Gyl8KHAG{z?{2lFiGR+$y{6>gvrKt!?dYNINYpdgC1Q+C1|1`q|d&ZLfK( zDO$sx$&voJeclYodHYI!KKOjwUvAs`H=6IyKZ^S9^MpTE{#{+k>vOG-x~G4yntVal zO6s^+-0}ZYbUww|?c2G~bKd-*!}q^U-7)p?&4QoVdU@u@ZUvsMS6tGY>^^VaJMET# z3*+ZnZ!Z1pTP_f`-D|1Aezv;R3~QI{x>w$!qI)cN@7!falm1%&SsfEym6!10(YndZ z&d-0Joq9p%(JcGlKhExc{MP=-|J-%+>KE+%Y`^>6fp=NIz0dt^2s{11w>Es)6Zt3d z6Y3rQG5%ynVnodS$<7evo!Wcf!Fjb2GZOP4HYtuLF{nsCRvoF4C?%N-WuRHCCpIh(Mebzqn#jmq}E(g}uO}F^B%>SA! VvLi@mCp`VZ7ra*JEyDyx1_0=<4>