linux-ext4.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] e2fsck: check for an encrypted lost+found directory
@ 2015-07-16 22:05 Theodore Ts'o
  2015-07-16 22:05 ` [PATCH 2/2] e2fsck: check for encrypted directory entries with too-short file names Theodore Ts'o
  0 siblings, 1 reply; 2+ messages in thread
From: Theodore Ts'o @ 2015-07-16 22:05 UTC (permalink / raw)
  To: Ext4 Developers List; +Cc: Theodore Ts'o

The /lost+found directory must not be encrypted, since e2fsck won't
have any keys.  If we find an encrypted lost+found directory, we
should delete the directory and recreate it.

Signed-off-by: Theodore Ts'o <tytso@mit.edu>
---
 e2fsck/pass3.c                 |  18 +++++++++++++++++-
 e2fsck/problem.c               |   5 +++++
 e2fsck/problem.h               |   3 +++
 tests/f_encrypted_lpf/expect.1 |  27 +++++++++++++++++++++++++++
 tests/f_encrypted_lpf/expect.2 |   7 +++++++
 tests/f_encrypted_lpf/image.gz | Bin 0 -> 1123 bytes
 tests/f_encrypted_lpf/name     |   1 +
 7 files changed, 60 insertions(+), 1 deletion(-)
 create mode 100644 tests/f_encrypted_lpf/expect.1
 create mode 100644 tests/f_encrypted_lpf/expect.2
 create mode 100644 tests/f_encrypted_lpf/image.gz
 create mode 100644 tests/f_encrypted_lpf/name

diff --git a/e2fsck/pass3.c b/e2fsck/pass3.c
index 1d5255f..d7b8802 100644
--- a/e2fsck/pass3.c
+++ b/e2fsck/pass3.c
@@ -100,7 +100,8 @@ void e2fsck_pass3(e2fsck_t ctx)
 
 	iter = e2fsck_dir_info_iter_begin(ctx);
 	while ((dir = e2fsck_dir_info_iter(ctx, iter)) != 0) {
-		if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+		if (ctx->flags & E2F_FLAG_SIGNAL_MASK ||
+		    ctx->flags & E2F_FLAG_RESTART)
 			goto abort_exit;
 		if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
 			goto abort_exit;
@@ -415,6 +416,12 @@ ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
 			goto unlink;
 		}
 
+		if (fix && (inode.i_flags & EXT4_ENCRYPT_FL)) {
+			if (!fix_problem(ctx, PR_3_LPF_ENCRYPTED, &pctx))
+				return 0;
+			goto unlink;
+		}
+
 		if (ext2fs_check_directory(fs, ino) == 0) {
 			ctx->lost_and_found = ino;
 			return ino;
@@ -437,6 +444,15 @@ unlink:
 		}
 		(void) e2fsck_dir_info_set_parent(ctx, ino, 0);
 		e2fsck_adjust_inode_count(ctx, ino, -1);
+		/*
+		 * If the old lost+found was a directory, we've just
+		 * disconnected it from the directory tree, which
+		 * means we need to restart the directory tree scan.
+		 * The simplest way to do this is restart the whole
+		 * e2fsck operation.
+		 */
+		if (LINUX_S_ISDIR(inode.i_mode))
+			ctx->flags |= E2F_FLAG_RESTART;
 	} else if (retval != EXT2_ET_FILE_NOT_FOUND) {
 		pctx.errcode = retval;
 		fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
diff --git a/e2fsck/problem.c b/e2fsck/problem.c
index 23d2183..084131a 100644
--- a/e2fsck/problem.c
+++ b/e2fsck/problem.c
@@ -1750,6 +1750,11 @@ static struct e2fsck_problem problem_table[] = {
 	  N_("Insufficient space to recover lost files!\nMove data off the @f and re-run e2fsck.\n\n"),
 	  PROMPT_NONE, 0 },
 
+	/* Lost+found is encrypted */
+	{ PR_3_LPF_ENCRYPTED,
+	  N_("/@l is encrypted\n"),
+	  PROMPT_CLEAR, 0 },
+
 	/* Pass 3A Directory Optimization	*/
 
 	/* Pass 3A: Optimizing directories */
diff --git a/e2fsck/problem.h b/e2fsck/problem.h
index e0b5d14..5af3edf 100644
--- a/e2fsck/problem.h
+++ b/e2fsck/problem.h
@@ -1048,6 +1048,9 @@ struct problem_context {
 /* Insufficient space to recover lost files */
 #define PR_3_NO_SPACE_TO_RECOVER	0x03001A
 
+/* Lost+found is encrypted */
+#define PR_3_LPF_ENCRYPTED		0x03001B
+
 /*
  * Pass 3a --- rehashing diretories
  */
diff --git a/tests/f_encrypted_lpf/expect.1 b/tests/f_encrypted_lpf/expect.1
new file mode 100644
index 0000000..7e215b7
--- /dev/null
+++ b/tests/f_encrypted_lpf/expect.1
@@ -0,0 +1,27 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Unconnected directory inode 12 (/???)
+Connect to /lost+found? yes
+
+/lost+found is encrypted
+Clear? yes
+
+/lost+found not found.  Create? yes
+
+Restarting e2fsck from the beginning...
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Unconnected directory inode 11 (/???)
+Connect to /lost+found? yes
+
+Pass 3A: Optimizing directories
+Pass 4: Checking reference counts
+Inode 12 ref count is 3, should be 2.  Fix? yes
+
+Pass 5: Checking group summary information
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 13/64 files (0.0% non-contiguous), 13/100 blocks
+Exit status is 1
diff --git a/tests/f_encrypted_lpf/expect.2 b/tests/f_encrypted_lpf/expect.2
new file mode 100644
index 0000000..6a59947
--- /dev/null
+++ b/tests/f_encrypted_lpf/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: 13/64 files (0.0% non-contiguous), 13/100 blocks
+Exit status is 0
diff --git a/tests/f_encrypted_lpf/image.gz b/tests/f_encrypted_lpf/image.gz
new file mode 100644
index 0000000000000000000000000000000000000000..7c89e07a5d96ecaef3d7ba57a5bb627760f0580f
GIT binary patch
literal 1123
zc-oWi=3pp!y*!kO`RyJ544F^~h7aG>q<t?r%v!M}L-EB*jbqM1AMY!!)!@+DCZ*5C
z)tTwN<f2;By&%C?OBFZ-T~*Y(uQqW7>9S^v8n!oevFEBTV2QpgYT7H_x-P$5-K<4d
zOgHb&zq${pY4>j5?5{MQ`R03>xgvx3>VG26nzMp=mb^H9d$Y|U7t>SyyI)<o*Ql$R
zq%rl~f6KNRx2!IIdsKY1W~bKux64G_H%Yj0Df-0SwysQid+g9cX>*(1U(c0Sy)ImH
zH+ub@t<PrfZeMO^WAfv*^Zfk2mn&|4-naC4q2f`g+}0}<#mw=+hI8NdAMdOEc(S(K
z_QS7v)BE=QIdhP8f2Q{NS?gN8dzctvYEG^HxH~8&xbp9P@mWp_Fa5i^`2F46;&D5E
z#r)2lIlJoC3q}Tp1OJ_0Ui!BG9`o;|EDQ_`CW}7({{L1n&Gu(H<1OcDU%!OdAO4-|
z9{ugdiyJ>m4=?tAE5S9jvgy24)TWQej~$bjytVK08&06cH90G%&A<8Q_`K)gx~u>D
zmxa8p2Z}B*eD(j$yoKVYUvtYIV+IOHZT+X;7xQo8FL@y6%6}l?kPM*?pJ)E@AEf8P
zj?({Uc<=Yt%w6?w=ZtNqFaCZxdHeeRMIWXv?eAW@d1^lUn$y48d1XPCdKiiwiYUC_
zc<<-4zn7OUpZDYKwUf{Ds`p#m6`j>51yX_w{HR{qR|9gm$r^!8J7>K5UsPjYVg2XY
zvfRzy&)Jh+=cKkJ#NM;dI0Xuouq6`QiEDPecX(g(`JZq3neu-des9gSm%C&8>)n}$
z+k5#K$OGa*&sXkc?*176)TT(OWxm<6saF+qJSum8Uhz%L$vgF?P|~lPWme0kZ9bLj
z``_sQIqg^0&(hCbG5>$~{&n;JtM7h2TmLtMLwNV4QxE@1U9Ug0et&)5&wqtC%RZ;n
z_SgSz{(AQRvDshG?*CR{_4Vm*|9Xz?OFr+DxOz`#&H6b<UPZ>#{nva_xKD5O#c95C
w_Wr+mYQNR_`gOnKUspc67x>2NX4vAt-!tpKGmHWTsk`%=8_wl3IIuAQ03~OkqyPW_

literal 0
Hc-jL100001

diff --git a/tests/f_encrypted_lpf/name b/tests/f_encrypted_lpf/name
new file mode 100644
index 0000000..b74259c
--- /dev/null
+++ b/tests/f_encrypted_lpf/name
@@ -0,0 +1 @@
+encrypted lost+found directory
-- 
2.3.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [PATCH 2/2] e2fsck: check for encrypted directory entries with too-short file names
  2015-07-16 22:05 [PATCH 1/2] e2fsck: check for an encrypted lost+found directory Theodore Ts'o
@ 2015-07-16 22:05 ` Theodore Ts'o
  0 siblings, 0 replies; 2+ messages in thread
From: Theodore Ts'o @ 2015-07-16 22:05 UTC (permalink / raw)
  To: Ext4 Developers List; +Cc: Theodore Ts'o

If there are directory entries with file names which are less than 16
bytes, it turns out that passing less than the crypto block size to
the kernel's crypto layer will cause the kernel to crash.

However, since there never should be encrypted directory entries where
the file name is less than 16 bytes (the AES block size), change
e2fsck to offer to address this corruption by deleting the directory
entry.

(We need to checks for this condition into the kernel as well.)

Signed-off-by: Theodore Ts'o <tytso@mit.edu>
---
 e2fsck/pass2.c                          |  20 ++++++++++++++++++++
 e2fsck/problem.c                        |   5 +++++
 e2fsck/problem.h                        |   3 +++
 lib/ext2fs/ext2_fs.h                    |   1 +
 tests/f_short_encrypted_dirent/expect.1 |  17 +++++++++++++++++
 tests/f_short_encrypted_dirent/expect.2 |   7 +++++++
 tests/f_short_encrypted_dirent/image.gz | Bin 0 -> 925 bytes
 tests/f_short_encrypted_dirent/name     |   1 +
 8 files changed, 54 insertions(+)
 create mode 100644 tests/f_short_encrypted_dirent/expect.1
 create mode 100644 tests/f_short_encrypted_dirent/expect.2
 create mode 100644 tests/f_short_encrypted_dirent/image.gz
 create mode 100644 tests/f_short_encrypted_dirent/name

diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c
index f4913f6..2e9a90d 100644
--- a/e2fsck/pass2.c
+++ b/e2fsck/pass2.c
@@ -494,6 +494,20 @@ static int check_name(e2fsck_t ctx,
 	return ret;
 }
 
+static int encrypted_check_name(e2fsck_t ctx,
+				struct ext2_dir_entry *dirent,
+				struct problem_context *pctx)
+{
+	if (ext2fs_dirent_name_len(dirent) < EXT4_CRYPTO_BLOCK_SIZE) {
+		if (fix_problem(ctx, PR_2_BAD_ENCRYPTED_NAME, pctx)) {
+			dirent->inode = 0;
+			return 1;
+		}
+		ext2fs_unmark_valid(ctx->fs);
+	}
+	return 0;
+}
+
 /*
  * Check the directory filetype (if present)
  */
@@ -1383,6 +1397,12 @@ skip_checksum:
 		if (!encrypted && check_name(ctx, dirent, &cd->pctx))
 			dir_modified++;
 
+		if (encrypted && (dot_state) > 1 &&
+		    encrypted_check_name(ctx, dirent, &cd->pctx)) {
+			dir_modified++;
+			goto next;
+		}
+
 		if (check_filetype(ctx, dirent, ino, &cd->pctx))
 			dir_modified++;
 
diff --git a/e2fsck/problem.c b/e2fsck/problem.c
index 084131a..9ef689a 100644
--- a/e2fsck/problem.c
+++ b/e2fsck/problem.c
@@ -1613,6 +1613,11 @@ static struct e2fsck_problem problem_table[] = {
 	  N_("Fixing size of inline @d @i %i failed.\n"),
 	  PROMPT_TRUNCATE, 0 },
 
+	/* Encrypted directory entry is too short */
+	{ PR_2_BAD_ENCRYPTED_NAME,
+	  N_("Encrypted @E is too short.\n"),
+	  PROMPT_CLEAR, 0 },
+
 	/* Pass 3 errors */
 
 	/* Pass 3: Checking directory connectivity */
diff --git a/e2fsck/problem.h b/e2fsck/problem.h
index 5af3edf..2ff0f5e 100644
--- a/e2fsck/problem.h
+++ b/e2fsck/problem.h
@@ -963,6 +963,9 @@ struct problem_context {
 /* fixing inline dir size failed */
 #define PR_2_FIX_INLINE_DIR_FAILED	0x02004F
 
+/* Encrypted directory entry is too short */
+#define PR_2_BAD_ENCRYPTED_NAME		0x020050
+
 /*
  * Pass 3 errors
  */
diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h
index 918ae70..cfeaa05 100644
--- a/lib/ext2fs/ext2_fs.h
+++ b/lib/ext2fs/ext2_fs.h
@@ -579,6 +579,7 @@ struct ext2_inode_large {
 #define EXT4_MAX_KEY_SIZE			64
 
 #define EXT4_KEY_DESCRIPTOR_SIZE		8
+#define EXT4_CRYPTO_BLOCK_SIZE			16
 
 /* Password derivation constants */
 #define EXT4_MAX_PASSPHRASE_SIZE		1024
diff --git a/tests/f_short_encrypted_dirent/expect.1 b/tests/f_short_encrypted_dirent/expect.1
new file mode 100644
index 0000000..bc64922
--- /dev/null
+++ b/tests/f_short_encrypted_dirent/expect.1
@@ -0,0 +1,17 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Encrypted entry 'motd' in /get_shorty (12) is too short.
+Clear? yes
+
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Unattached inode 13
+Connect to /lost+found? yes
+
+Inode 13 ref count is 2, should be 1.  Fix? yes
+
+Pass 5: Checking group summary information
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 13/16 files (0.0% non-contiguous), 23/100 blocks
+Exit status is 1
diff --git a/tests/f_short_encrypted_dirent/expect.2 b/tests/f_short_encrypted_dirent/expect.2
new file mode 100644
index 0000000..636c6e9
--- /dev/null
+++ b/tests/f_short_encrypted_dirent/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: 13/16 files (0.0% non-contiguous), 23/100 blocks
+Exit status is 0
diff --git a/tests/f_short_encrypted_dirent/image.gz b/tests/f_short_encrypted_dirent/image.gz
new file mode 100644
index 0000000000000000000000000000000000000000..a35bfb23b51aee75da142886a39380915d629f8e
GIT binary patch
literal 925
zc-oWi=3qF(vLcj;`RyIw4(U)Ch7Tv*7cN<Qtu)ZTbOZa+SIgM>n-pR<c5KL7_%>*j
z(^<96yPY?mG@E&2T}X!Do{B($mj@T0>XKJ?{i2}6)upf~U_w`g;2sfC+aD)?O?q=J
zYdhCEiS56CAGEKWTxtB@{P6GnCsjL@687GbS|pa_+)?c$;`HR)dx7uCuP;5j+uGWx
z5fyXid+ECC?@RXWzPr8V&N2aYr#n)Q-qz?@#q=yXo>pI1dOdh|TfEJ`k9))GH$6V<
z81wqw>b{ziJ$tHepT6FI_MCm;s{*}SqPcOm%Kw%AnO&q^6UHOY7kj8!D?B7T`(UI0
z{Q6zd@59?}+*|$MY5l+5$MWj_EOh#EtY6&v+fw!ZIfd+rxzRCu{@gMC(C(UGd$N7k
zeVM19lppTBf9|=v+pqf%+ZPAzyO)!0?q_P<8+9dG{hs!ePnSK*R@h$7N&Wm;EFhxU
zNw>c4KJ)cbv%f3<?brJ9T7Jit*Z(K-$3?%`wqJjT{Dyn4{$HQ3_CEaof`5!(`B&6C
z{AGS6AMn577yA|a1^*hiM*csrE0#U%&)@sgF8o^)aOSMp=2^R0rr-PgzkBohBi+}3
z@tUj&U;5YB)8=}X-*&CdZ!K~|UeApR>h525(`Qa=Y`NOx%%y_&P3;2Zyrt(R7gq0^
ztGc;x>C_{^YgIaLpI!MT<HoMFSKiK(Ssk)@$Fyym!>n$eyp*PVZc>=V=a9{!>Qi5x
zDOz`rGs|<g)UVc>%*C_UPBF`R*_^pHc;)fnOxu@y8hYio))rN(ebK)@>*}YzqOF$Z
z_q~><Z<-kNvgu*y?9C51-234E{>Jw7oTUHnHa36!G4IEL7x(rqe*ByNo=E!H9rjmr
zGE<iBG}vQu`jCX$^T(&|#MrJ4Q+w?hvtCA4v(k?N1sF&y|I96X`eXdlnuh@*b7gsZ
zA9?-k-uqv<b5ZZ!>zB%R=4~%7`g=I+>BV@q>hs(08{GJ#o-dj6@8Wm%+5cx>U;N_8
z$qP3kb>b}k7kPhvKY#b5{BQpD<~Lr~KRuH0Ih~*1?EmiQMK9LA`?a}v=~s36*w5mx
z{lC{wHd|x#|H9k->+9p&_MF~0XTSM>v$&eS(ow1Z_~-X7N<Z}HzL?*)+!MQH>gW6y
gKX1S1)Su;gpYO0TPy!nMPrlFaZb6X&!vsbK0CU{d761SM

literal 0
Hc-jL100001

diff --git a/tests/f_short_encrypted_dirent/name b/tests/f_short_encrypted_dirent/name
new file mode 100644
index 0000000..a35028a
--- /dev/null
+++ b/tests/f_short_encrypted_dirent/name
@@ -0,0 +1 @@
+short encrypted directory entry
-- 
2.3.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2015-07-16 22:05 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-07-16 22:05 [PATCH 1/2] e2fsck: check for an encrypted lost+found directory Theodore Ts'o
2015-07-16 22:05 ` [PATCH 2/2] e2fsck: check for encrypted directory entries with too-short file names Theodore Ts'o

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).