[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20140805010555.2611.52850.stgit@birch.djwong.org>
Date: Mon, 04 Aug 2014 18:05:55 -0700
From: "Darrick J. Wong" <darrick.wong@...cle.com>
To: tytso@....edu, darrick.wong@...cle.com
Cc: linux-ext4@...r.kernel.org
Subject: [PATCH 09/21] e2fsck: check ea-in-inode regions for overlap
Ensure that the various blobs in the in-inode EA region do not overlap.
Signed-off-by: Darrick J. Wong <darrick.wong@...cle.com>
---
e2fsck/pass1.c | 41 ++++++++++++++++++++++++++++++++---
e2fsck/problem.c | 5 ++++
e2fsck/problem.h | 3 +++
tests/f_inode_ea_collision/expect.1 | 15 +++++++++++++
tests/f_inode_ea_collision/expect.2 | 7 ++++++
tests/f_inode_ea_collision/image.gz | Bin
tests/f_inode_ea_collision/name | 1 +
7 files changed, 69 insertions(+), 3 deletions(-)
create mode 100644 tests/f_inode_ea_collision/expect.1
create mode 100644 tests/f_inode_ea_collision/expect.2
create mode 100644 tests/f_inode_ea_collision/image.gz
create mode 100644 tests/f_inode_ea_collision/name
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index 6c79eed..172d664 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -286,15 +286,17 @@ static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
struct ext2_super_block *sb = ctx->fs->super;
struct ext2_inode_large *inode;
struct ext2_ext_attr_entry *entry;
- char *start;
+ char *start, *header;
unsigned int storage_size, remain;
problem_t problem = 0;
+ region_t region = 0;
inode = (struct ext2_inode_large *) pctx->inode;
storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
inode->i_extra_isize;
- start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
- inode->i_extra_isize + sizeof(__u32);
+ header = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
+ inode->i_extra_isize;
+ start = header + sizeof(__u32);
entry = (struct ext2_ext_attr_entry *) start;
/* scan all entry's headers first */
@@ -302,10 +304,28 @@ static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
/* take finish entry 0UL into account */
remain = storage_size - sizeof(__u32);
+ region = region_create(0, storage_size);
+ if (!region) {
+ fix_problem(ctx, PR_1_EA_ALLOC_REGION_ABORT, pctx);
+ problem = 0;
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
+ }
+ if (region_allocate(region, 0, sizeof(__u32))) {
+ problem = PR_1_INODE_EA_ALLOC_COLLISION;
+ goto fix;
+ }
+
while (remain >= sizeof(struct ext2_ext_attr_entry) &&
!EXT2_EXT_IS_LAST_ENTRY(entry)) {
__u32 hash;
+ if (region_allocate(region, (char *)entry - (char *)header,
+ EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
+ problem = PR_1_INODE_EA_ALLOC_COLLISION;
+ goto fix;
+ }
+
/* header eats this space */
remain -= sizeof(struct ext2_ext_attr_entry);
@@ -333,6 +353,13 @@ static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
goto fix;
}
+ if (entry->e_value_size &&
+ region_allocate(region, sizeof(__u32) + entry->e_value_offs,
+ EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
+ problem = PR_1_INODE_EA_ALLOC_COLLISION;
+ goto fix;
+ }
+
hash = ext2fs_ext_attr_hash_entry(entry,
start + entry->e_value_offs);
@@ -347,7 +374,15 @@ static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
entry = EXT2_EXT_ATTR_NEXT(entry);
}
+
+ if (region_allocate(region, (char *)entry - (char *)header,
+ sizeof(__u32))) {
+ problem = PR_1_INODE_EA_ALLOC_COLLISION;
+ goto fix;
+ }
fix:
+ if (region)
+ region_free(region);
/*
* it seems like a corruption. it's very unlikely we could repair
* EA(s) in automatic fashion -bzzz
diff --git a/e2fsck/problem.c b/e2fsck/problem.c
index 2d29c35..b982a27 100644
--- a/e2fsck/problem.c
+++ b/e2fsck/problem.c
@@ -977,6 +977,11 @@ static struct e2fsck_problem problem_table[] = {
N_("@i %i passes checks, but checksum does not match @i. "),
PROMPT_FIX, PR_PREEN_OK },
+ /* Inode extended attribute is corrupt (allocation collision) */
+ { PR_1_INODE_EA_ALLOC_COLLISION,
+ N_("@i %i @a is corrupt (allocation collision). "),
+ PROMPT_CLEAR, 0},
+
/*
* Inode extent block passes checks, but checksum does not match
* extent
diff --git a/e2fsck/problem.h b/e2fsck/problem.h
index 89146ec..f051c11 100644
--- a/e2fsck/problem.h
+++ b/e2fsck/problem.h
@@ -577,6 +577,9 @@ struct problem_context {
/* inode passes checks, but checksum does not match inode */
#define PR_1_INODE_ONLY_CSUM_INVALID 0x010068
+/* Inode EA allocation collision */
+#define PR_1_INODE_EA_ALLOC_COLLISION 0x010069
+
/* extent block passes checks, but checksum does not match extent block */
#define PR_1_EXTENT_ONLY_CSUM_INVALID 0x01006A
diff --git a/tests/f_inode_ea_collision/expect.1 b/tests/f_inode_ea_collision/expect.1
new file mode 100644
index 0000000..a67a5f1
--- /dev/null
+++ b/tests/f_inode_ea_collision/expect.1
@@ -0,0 +1,15 @@
+Pass 1: Checking inodes, blocks, and sizes
+Inode 12 extended attribute is corrupt (allocation collision). Clear? yes
+
+Inode 13 extended attribute is corrupt (allocation collision). Clear? yes
+
+Inode 14 extended attribute is corrupt (allocation collision). Clear? yes
+
+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: 14/128 files (0.0% non-contiguous), 18/512 blocks
+Exit status is 1
diff --git a/tests/f_inode_ea_collision/expect.2 b/tests/f_inode_ea_collision/expect.2
new file mode 100644
index 0000000..5a7ca86
--- /dev/null
+++ b/tests/f_inode_ea_collision/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: 14/128 files (0.0% non-contiguous), 18/512 blocks
+Exit status is 0
diff --git a/tests/f_inode_ea_collision/image.gz b/tests/f_inode_ea_collision/image.gz
new file mode 100644
index 0000000000000000000000000000000000000000..5217f6503404864944a88bfc36b7d75a305aafb8
GIT binary patch
literal 2602
zcmb2|=3rRTdo!4c`Ry(1jNn8Oh6n%E1ihnk1;sZu?eJW<NUv+f#j`7&rz`1+%6Chx
z=yzP$zj61~h22d*Bw~&@...CYH8poTn;&#Na(uyTr@...7j4w~mb&)7_&M9}GoL+C
zGk@...=BTul$ZKafv}@r^f(vpkBHY&x}B)u->fWbo2immwCQ=R(4%*W3VPSyYikyH
zZ``1|?Dt2%b4UJs`SxP5`rf<qk6jPBKPPtAKflM1ZxnpF(YbTo*E?sW`@...t1C!M
z`g-u=^W<936>Zmo_PxDrmFDffM>TlO`Xe_UFJ)&q5I<qte(j_+r+@wbw<G4~uC?|#
zcOOVHF)%dL-%klvt<gLGpn`#cA>p9+|Nr-;CIy9`sOP>Q<+XI(x<BT7w4IAzdc6J7
zdCqz3<l}rxZf~lc+-s<>{mlI69-Cu#x2fEG^I8O`IbuST)Up5aw?BQf2l6(Y*iy{}
zq!0X%2a*Q=*nuRGpkb%!&drIEK-Cc?HOxRqk_!&ZmynqGV&(DwA>VJu7G9cn-9Ex)
z-%^=bo9>7_cgpxTq2-kMan+l0#@...yMF(gCH3|5gR2~8+7~{w*cm?e(XaU;*Z057
z&W!M@...%LN2Vw&q3(|N@A<Dn{>E#r(fu{w!1aHyW|G;j`TKwV+ix=G`9b+#`+r?s
zr8ztMpTXa%^)Y*{{yhEf{nO2F^^e8ndMp3^ovC;3;OnAI>tDDPw`Xk)@T=PVQ}yVs
zzqQN%|1gw&XD!<Qdj9lZ>;J9$x8;BAuL5_e$iIgFSN+p<{rgaU<^NmnU)kI5+HJ>n
z;+6g}CVTt;_t($%{7Y`ojOrT=fzc2c4S~@...85Z5Fii&8zgEO|2Qt4#K54y004(2
BL%09{
literal 0
HcmV?d00001
diff --git a/tests/f_inode_ea_collision/name b/tests/f_inode_ea_collision/name
new file mode 100644
index 0000000..b64119e
--- /dev/null
+++ b/tests/f_inode_ea_collision/name
@@ -0,0 +1 @@
+collisions in the inode ea area
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists