Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 955

kernel-2.6.18-238.el5.src.rpm

From: Eric Sandeen <sandeen@redhat.com>
Date: Wed, 27 Aug 2008 15:18:44 -0500
Subject: [fs] ecryptfs: disallow mounts on nfs, cifs, ecryptfs
Message-id: 48B5B6A4.4000709@redhat.com
O-Subject: [PATCH RHEL5.3 UPDATED] ecryptfs: disallow mounts on nfs, cifs, ecryptfs
Bugzilla: 435115
RH-Acked-by: Jarod Wilson <jwilson@redhat.com>
RH-Acked-by: Josef Bacik <jbacik@redhat.com>

File this one under:

 Bug 435115 - kernel freezes when running script which features ecryptfs parts of kernel

Parts of ecryptfs are still a bit fragile, and it breaks in various
different ways when mounted over nfs, cifs, or over ecryptfs itself.

I plan to eventually resolve these issues, but it won't be done in
time for RHEL5.3.  So in addition to release note warnings, here is
a patch from the upstream  maintainer (though the patch itself is
not upstream) to disallow mounting ecryptfs on top of filesystems
which are known to cause problems with ecryptfs.  There are mount
options to force the mount to succeed, just in case anyone wants to
try their workload to see if it passes, I supose.

When IBM shipped ecryptfs, they shipped with this patch, as I
understand it.

Thanks,

-Eric

diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index d69e6c1..da39d0a 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -336,6 +336,9 @@ struct ecryptfs_mount_crypt_stat {
 #define ECRYPTFS_XATTR_METADATA_ENABLED        0x00000002
 #define ECRYPTFS_ENCRYPTED_VIEW_ENABLED        0x00000004
 #define ECRYPTFS_MOUNT_CRYPT_STAT_INITIALIZED  0x00000008
+#define ECRYPTFS_FORCE_NFS                     0x00000010
+#define ECRYPTFS_FORCE_CIFS                    0x00000020
+#define ECRYPTFS_FORCE_ECRYPTFS                0x00000040
 	u32 flags;
 	struct list_head global_auth_tok_list;
 	struct mutex global_auth_tok_list_mutex;
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 3f0220f..85db664 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -209,7 +209,9 @@ enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig,
        ecryptfs_opt_cipher, ecryptfs_opt_ecryptfs_cipher,
        ecryptfs_opt_ecryptfs_key_bytes,
        ecryptfs_opt_passthrough, ecryptfs_opt_xattr_metadata,
-       ecryptfs_opt_encrypted_view, ecryptfs_opt_err };
+       ecryptfs_opt_encrypted_view, ecryptfs_opt_force_nfs,
+       ecryptfs_opt_force_cifs, ecryptfs_opt_force_ecryptfs,
+       ecryptfs_opt_err };
 
 static match_table_t tokens = {
 	{ecryptfs_opt_sig, "sig=%s"},
@@ -220,6 +222,9 @@ static match_table_t tokens = {
 	{ecryptfs_opt_passthrough, "ecryptfs_passthrough"},
 	{ecryptfs_opt_xattr_metadata, "ecryptfs_xattr_metadata"},
 	{ecryptfs_opt_encrypted_view, "ecryptfs_encrypted_view"},
+	{ecryptfs_opt_force_nfs, "ecryptfs_force_nfs"},
+	{ecryptfs_opt_force_cifs, "ecryptfs_force_cifs"},
+	{ecryptfs_opt_force_ecryptfs, "ecryptfs_force_ecryptfs"},
 	{ecryptfs_opt_err, NULL}
 };
 
@@ -464,6 +469,111 @@ out:
 	return rc;
 }
 
+static struct ecryptfs_lower_filesystem {
+       char *name;
+       u32 flag;
+} ecryptfs_invalid_lower_filesystems[] = {
+       {
+	       .name = "nfs",
+	       .flag = ECRYPTFS_FORCE_NFS,
+       },
+       {
+	       .name = "cifs",
+	       .flag = ECRYPTFS_FORCE_CIFS,
+       },
+       {
+	       .name = "ecryptfs",
+	       .flag = ECRYPTFS_FORCE_ECRYPTFS,
+       },
+};
+
+/**
+ * This is a temporary hack to prevent inadvertent mounting on lower
+ * filesystems that are known to be currently incompatible with
+ * eCryptfs. This mainly includes networked filesystems.
+ */
+static int
+ecryptfs_validate_lower(const char *dev_name, char *options)
+{
+       struct super_block *lower_sb;
+       struct nameidata nd;
+       int i;
+       char *p;
+       int token;
+       u32 flags = 0;
+       substring_t args[MAX_OPT_ARGS];
+       char *opts_tmp;
+       char *opts_orig = NULL;
+       int options_len;
+       int rc;
+
+       if (!options) {
+	       rc = -EINVAL;
+	       goto out;
+       }
+       options_len = (strlen(options) + 1);
+       if ((opts_tmp = opts_orig = kmalloc(options_len, GFP_KERNEL)) == NULL) {
+	       rc = -ENOMEM;
+	       goto out;
+       }
+       memcpy(opts_orig, options, options_len);
+       opts_orig[options_len] = '\0';
+       rc = path_lookup(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &nd);
+       if (rc) {
+	       printk(KERN_WARNING
+		      "path_lookup() failed on dev_name = [%s]\n", dev_name);
+	       goto out;
+       }
+       lower_sb = nd.dentry->d_sb;
+       while ((p = strsep(&opts_tmp, ",")) != NULL) {
+	       if (!*p)
+		       continue;
+	       token = match_token(p, tokens, args);
+	       switch (token) {
+	       case ecryptfs_opt_force_nfs:
+		       flags |= ECRYPTFS_FORCE_NFS;
+		       break;
+	       case ecryptfs_opt_force_cifs:
+		       flags |= ECRYPTFS_FORCE_CIFS;
+		       break;
+	       case ecryptfs_opt_force_ecryptfs:
+		       flags |= ECRYPTFS_FORCE_ECRYPTFS;
+		       break;
+	       }
+       }
+       for (i = 0; i < ARRAY_SIZE(ecryptfs_invalid_lower_filesystems); i++) {
+	       struct ecryptfs_lower_filesystem *lower_fs;
+
+	       lower_fs = &ecryptfs_invalid_lower_filesystems[i];
+	       if (strcmp(lower_sb->s_type->name, lower_fs->name) == 0) {
+		       printk(KERN_WARNING
+			      "Mount request on top of filesystem type [%s]\n",
+			      lower_sb->s_type->name);
+		       if (lower_fs->flag & flags) {
+			       printk(KERN_WARNING "Mount on filesystem of "
+				      "type [%s] forced\n",
+				      lower_sb->s_type->name);
+			       path_release(&nd);
+			       goto out;
+		       } else {
+			       rc = -EINVAL;
+			       printk(KERN_ERR "Mount on filesystem of type "
+				      "[%s] explicitly disallowed due to "
+				      "known incompatibilities\n",
+				       lower_sb->s_type->name);
+			       path_release(&nd);
+			       goto out;
+		       }
+	       }
+       }
+       path_release(&nd);
+out:
+       if (opts_orig)
+	       kfree(opts_orig);
+       return rc;
+}
+
+
 /**
  * ecryptfs_read_super
  * @sb: The ecryptfs super block
@@ -527,6 +637,11 @@ static int ecryptfs_get_sb(struct file_system_type *fs_type, int flags,
 	int rc;
 	struct super_block *sb;
 
+	if ((rc = ecryptfs_validate_lower(dev_name, raw_data))) {
+		printk(KERN_ERR "Invalid lower filesystem type\n");
+		goto out;
+	}
+
 	rc = get_sb_nodev(fs_type, flags, raw_data, ecryptfs_fill_super, mnt);
 	if (rc < 0) {
 		printk(KERN_ERR "Getting sb failed; rc = [%d]\n", rc);