bc092b9
From 734668238fcc0ef691a080839e04f33854fa133a Mon Sep 17 00:00:00 2001
bc092b9
From: Eric Biggers <ebiggers@google.com>
bc092b9
Date: Thu, 29 Jun 2017 13:27:49 +0000
6f1e3d5
Subject: [PATCH 043/198] Allow GRUB to mount ext2/3/4 filesystems that have
bc092b9
 the encryption feature.
bc092b9
bc092b9
On such a filesystem, inodes may have EXT4_ENCRYPT_FLAG set.
bc092b9
For a regular file, this means its contents are encrypted; for a
bc092b9
directory, this means the filenames in its directory entries are
bc092b9
encrypted; and for a symlink, this means its target is encrypted.  Since
bc092b9
GRUB cannot decrypt encrypted contents or filenames, just issue an error
bc092b9
if it would need to do so.  This is sufficient to allow unencrypted boot
bc092b9
files to co-exist with encrypted files elsewhere on the filesystem.
bc092b9
bc092b9
(Note that encrypted regular files and symlinks will not normally be
bc092b9
encountered outside an encrypted directory; however, it's possible via
bc092b9
hard links, so they still need to be handled.)
bc092b9
bc092b9
Tested by booting from an ext4 /boot partition on which I had run
bc092b9
'tune2fs -O encrypt'.  I also verified that the expected error messages
bc092b9
are printed when trying to access encrypted directories, files, and
bc092b9
symlinks from the GRUB command line.  Also ran 'sudo ./grub-fs-tester
bc092b9
ext4_encrypt'; note that this requires e2fsprogs v1.43+ and Linux v4.1+.
bc092b9
bc092b9
Signed-off-by: Eric Biggers <ebiggers@google.com>
bc092b9
---
bc092b9
 grub-core/fs/ext2.c          | 23 ++++++++++++++++++++++-
bc092b9
 tests/ext234_test.in         |  1 +
bc092b9
 tests/util/grub-fs-tester.in | 10 ++++++++++
bc092b9
 3 files changed, 33 insertions(+), 1 deletion(-)
bc092b9
bc092b9
diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c
bc092b9
index cdce63bcc..b8ad75a0f 100644
bc092b9
--- a/grub-core/fs/ext2.c
bc092b9
+++ b/grub-core/fs/ext2.c
bc092b9
@@ -102,6 +102,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
bc092b9
 #define EXT4_FEATURE_INCOMPAT_64BIT		0x0080
bc092b9
 #define EXT4_FEATURE_INCOMPAT_MMP		0x0100
bc092b9
 #define EXT4_FEATURE_INCOMPAT_FLEX_BG		0x0200
bc092b9
+#define EXT4_FEATURE_INCOMPAT_ENCRYPT          0x10000
bc092b9
 
bc092b9
 /* The set of back-incompatible features this driver DOES support. Add (OR)
bc092b9
  * flags here as the related features are implemented into the driver.  */
bc092b9
@@ -109,7 +110,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
bc092b9
                                        | EXT4_FEATURE_INCOMPAT_EXTENTS  \
bc092b9
                                        | EXT4_FEATURE_INCOMPAT_FLEX_BG \
bc092b9
                                        | EXT2_FEATURE_INCOMPAT_META_BG \
bc092b9
-                                       | EXT4_FEATURE_INCOMPAT_64BIT)
bc092b9
+                                       | EXT4_FEATURE_INCOMPAT_64BIT \
bc092b9
+                                       | EXT4_FEATURE_INCOMPAT_ENCRYPT)
bc092b9
 /* List of rationales for the ignored "incompatible" features:
bc092b9
  * needs_recovery: Not really back-incompatible - was added as such to forbid
bc092b9
  *                 ext2 drivers from mounting an ext3 volume with a dirty
bc092b9
@@ -138,6 +140,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
bc092b9
 #define EXT3_JOURNAL_FLAG_DELETED	4
bc092b9
 #define EXT3_JOURNAL_FLAG_LAST_TAG	8
bc092b9
 
bc092b9
+#define EXT4_ENCRYPT_FLAG              0x800
bc092b9
 #define EXT4_EXTENTS_FLAG		0x80000
bc092b9
 
bc092b9
 /* The ext2 superblock.  */
bc092b9
@@ -706,6 +709,12 @@ grub_ext2_read_symlink (grub_fshelp_node_t node)
bc092b9
       grub_ext2_read_inode (diro->data, diro->ino, &diro->inode);
bc092b9
       if (grub_errno)
bc092b9
 	return 0;
bc092b9
+
bc092b9
+      if (diro->inode.flags & grub_cpu_to_le32_compile_time (EXT4_ENCRYPT_FLAG))
bc092b9
+       {
bc092b9
+         grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "symlink is encrypted");
bc092b9
+         return 0;
bc092b9
+       }
bc092b9
     }
bc092b9
 
bc092b9
   symlink = grub_malloc (grub_le_to_cpu32 (diro->inode.size) + 1);
bc092b9
@@ -749,6 +758,12 @@ grub_ext2_iterate_dir (grub_fshelp_node_t dir,
bc092b9
 	return 0;
bc092b9
     }
bc092b9
 
bc092b9
+  if (diro->inode.flags & grub_cpu_to_le32_compile_time (EXT4_ENCRYPT_FLAG))
bc092b9
+    {
bc092b9
+      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "directory is encrypted");
bc092b9
+      return 0;
bc092b9
+    }
bc092b9
+
bc092b9
   /* Search the file.  */
bc092b9
   while (fpos < grub_le_to_cpu32 (diro->inode.size))
bc092b9
     {
bc092b9
@@ -859,6 +874,12 @@ grub_ext2_open (struct grub_file *file, const char *name)
bc092b9
 	goto fail;
bc092b9
     }
bc092b9
 
bc092b9
+  if (fdiro->inode.flags & grub_cpu_to_le32_compile_time (EXT4_ENCRYPT_FLAG))
bc092b9
+    {
bc092b9
+      err = grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "file is encrypted");
bc092b9
+      goto fail;
bc092b9
+    }
bc092b9
+
bc092b9
   grub_memcpy (data->inode, &fdiro->inode, sizeof (struct grub_ext2_inode));
bc092b9
   grub_free (fdiro);
bc092b9
 
bc092b9
diff --git a/tests/ext234_test.in b/tests/ext234_test.in
bc092b9
index 892b99cbd..4f1eb527e 100644
bc092b9
--- a/tests/ext234_test.in
bc092b9
+++ b/tests/ext234_test.in
bc092b9
@@ -30,3 +30,4 @@ fi
bc092b9
 "@builddir@/grub-fs-tester" ext3
bc092b9
 "@builddir@/grub-fs-tester" ext4
bc092b9
 "@builddir@/grub-fs-tester" ext4_metabg
bc092b9
+"@builddir@/grub-fs-tester" ext4_encrypt
bc092b9
diff --git a/tests/util/grub-fs-tester.in b/tests/util/grub-fs-tester.in
bc092b9
index 88cbe7365..fd7e0f14b 100644
bc092b9
--- a/tests/util/grub-fs-tester.in
bc092b9
+++ b/tests/util/grub-fs-tester.in
bc092b9
@@ -156,6 +156,12 @@ for LOGSECSIZE in $(range "$MINLOGSECSIZE" "$MAXLOGSECSIZE" 1); do
bc092b9
 		# Could go further but what's the point?
bc092b9
 	    MAXBLKSIZE=$((65536*1024))
bc092b9
 	    ;;
bc092b9
+       xext4_encrypt)
bc092b9
+           # OS LIMITATION: Linux currently only allows the 'encrypt' feature
bc092b9
+           # in combination with block_size = PAGE_SIZE (4096 bytes on x86).
bc092b9
+           MINBLKSIZE=$(getconf PAGE_SIZE)
bc092b9
+           MAXBLKSIZE=$MINBLKSIZE
bc092b9
+           ;;
bc092b9
 	xext*)
bc092b9
 	    MINBLKSIZE=1024
bc092b9
 	    if [ $MINBLKSIZE -lt $SECSIZE ]; then
bc092b9
@@ -796,6 +802,10 @@ for LOGSECSIZE in $(range "$MINLOGSECSIZE" "$MAXLOGSECSIZE" 1); do
bc092b9
 		    MKE2FS_DEVICE_SECTSIZE=$SECSIZE "mkfs.ext4" -O meta_bg,^resize_inode -b $BLKSIZE -L "$FSLABEL" -q "${MOUNTDEVICE}"
bc092b9
 		    MOUNTFS=ext4
bc092b9
 		    ;;
bc092b9
+               xext4_encrypt)
bc092b9
+                   MKE2FS_DEVICE_SECTSIZE=$SECSIZE "mkfs.ext4" -O encrypt -b $BLKSIZE -L "$FSLABEL" -q "${MOUNTDEVICE}"
bc092b9
+                   MOUNTFS=ext4
bc092b9
+                   ;;
bc092b9
 		xext*)
bc092b9
 		    MKE2FS_DEVICE_SECTSIZE=$SECSIZE "mkfs.$fs" -b $BLKSIZE -L "$FSLABEL" -q "${MOUNTDEVICE}" ;;
bc092b9
 		xxfs)
bc092b9
-- 
da63b36
2.14.3
bc092b9