[PATCH] eCryptfs: Enable plaintext passthrough

From: Michael Halcrow
Date: Thu Sep 28 2006 - 14:32:21 EST


Code that is currently unused in mmap.c can simply pass through
unencrypted data. This patch adds a mount option to enable that
functionality.

Note that, with this patch, one can encrypt a directory full of
unencrypted files by doing something like this for each file:

cp file.txt .file.txt; mv .file.txt file.txt

Signed-off-by: Michael Halcrow <mhalcrow@xxxxxxxxxx>

---

fs/ecryptfs/crypto.c | 4 ----
fs/ecryptfs/ecryptfs_kernel.h | 5 ++++-
fs/ecryptfs/file.c | 40 +++++++++++++++++++++++++++++-----------
fs/ecryptfs/inode.c | 4 ++--
fs/ecryptfs/main.c | 7 ++++++-
5 files changed, 41 insertions(+), 19 deletions(-)

39a20eb2e87eb501c849a78f41640f11c6a0a01d
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 39d7ec0..ed35a97 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -1394,8 +1394,6 @@ static int ecryptfs_read_headers_virt(ch
offset = ECRYPTFS_FILE_SIZE_BYTES;
rc = contains_ecryptfs_marker(page_virt + offset);
if (rc == 0) {
- ecryptfs_printk(KERN_WARNING, "Valid eCryptfs marker not "
- "found\n");
rc = -EINVAL;
goto out;
}
@@ -1463,8 +1461,6 @@ int ecryptfs_read_headers(struct dentry
&lower_file->f_pos);
set_fs(oldfs);
if (bytes_read != ECRYPTFS_DEFAULT_EXTENT_SIZE) {
- ecryptfs_printk(KERN_ERR, "Expected size of header not read."
- "Instead [%d] bytes were read\n", bytes_read);
rc = -EINVAL;
goto out;
}
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index bae19ea..3911219 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -42,7 +42,8 @@ #define ECRYPTFS_VERSIONING_PASSPHRASE 0
#define ECRYPTFS_VERSIONING_PUBKEY 0x00000002
#define ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH 0x00000004
#define ECRYPTFS_VERSIONING_POLICY 0x00000008
-#define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE)
+#define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \
+ | ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH)

#define ECRYPTFS_MAX_PASSWORD_LENGTH 64
#define ECRYPTFS_MAX_PASSPHRASE_BYTES ECRYPTFS_MAX_PASSWORD_LENGTH
@@ -238,6 +239,8 @@ struct ecryptfs_dentry_info {
*/
struct ecryptfs_mount_crypt_stat {
/* Pointers to memory we do not own, do not free these */
+#define ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED 0x00000001
+ u32 flags;
struct ecryptfs_auth_tok *global_auth_tok;
struct key *global_auth_tok_key;
size_t global_default_cipher_key_size;
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 1cc2cc0..c8550c9 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -211,6 +211,7 @@ static int ecryptfs_open(struct inode *i
{
int rc = 0;
struct ecryptfs_crypt_stat *crypt_stat = NULL;
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
struct dentry *ecryptfs_dentry = file->f_dentry;
/* Private value of ecryptfs_dentry allocated in
* ecryptfs_lookup() */
@@ -233,6 +234,8 @@ static int ecryptfs_open(struct inode *i
memset(file_info, 0, sizeof(*file_info));
lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
+ mount_crypt_stat = &ecryptfs_superblock_to_private(
+ ecryptfs_dentry->d_sb)->mount_crypt_stat;
mutex_lock(&crypt_stat->cs_mutex);
if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) {
ecryptfs_printk(KERN_DEBUG, "Setting flags for stat...\n");
@@ -267,12 +270,21 @@ static int ecryptfs_open(struct inode *i
goto out;
}
mutex_lock(&crypt_stat->cs_mutex);
- if (i_size_read(lower_inode) == 0) {
- ecryptfs_printk(KERN_EMERG, "Zero-length lower file; "
- "ecryptfs_create() had a problem?\n");
- rc = -ENOENT;
+ if (i_size_read(lower_inode) < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) {
+ if (!(mount_crypt_stat->flags
+ & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
+ rc = -EIO;
+ printk(KERN_WARNING "Attempt to read file that is "
+ "not in a valid eCryptfs format, and plaintext "
+ "passthrough mode is not enabled; returning "
+ "-EIO\n");
+ mutex_unlock(&crypt_stat->cs_mutex);
+ goto out_puts;
+ }
+ crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
+ rc = 0;
mutex_unlock(&crypt_stat->cs_mutex);
- goto out_puts;
+ goto out;
} else if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
ECRYPTFS_POLICY_APPLIED)
|| !ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
@@ -281,15 +293,21 @@ static int ecryptfs_open(struct inode *i
if (rc) {
ecryptfs_printk(KERN_DEBUG,
"Valid headers not found\n");
+ if (!(mount_crypt_stat->flags
+ & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
+ rc = -EIO;
+ printk(KERN_WARNING "Attempt to read file that "
+ "is not in a valid eCryptfs format, "
+ "and plaintext passthrough mode is not "
+ "enabled; returning -EIO\n");
+ mutex_unlock(&crypt_stat->cs_mutex);
+ goto out_puts;
+ }
ECRYPTFS_CLEAR_FLAG(crypt_stat->flags,
ECRYPTFS_ENCRYPTED);
- /* At this point, we could just move on and
- * have the encrypted data passed through
- * as-is to userspace. For release 0.1, we are
- * going to default to -EIO. */
- rc = -EIO;
+ rc = 0;
mutex_unlock(&crypt_stat->cs_mutex);
- goto out_puts;
+ goto out;
}
}
mutex_unlock(&crypt_stat->cs_mutex);
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 503fb39..efdd2b7 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -436,8 +436,8 @@ static struct dentry *ecryptfs_lookup(st
} else {
if (!contains_ecryptfs_marker(page_virt
+ ECRYPTFS_FILE_SIZE_BYTES)) {
- ecryptfs_printk(KERN_WARNING, "Underlying file "
- "lacks recognizable eCryptfs marker\n");
+ kmem_cache_free(ecryptfs_header_cache_2, page_virt);
+ goto out;
}
memcpy(&file_size, page_virt, sizeof(file_size));
file_size = be64_to_cpu(file_size);
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index b7e3bd0..c88a8c9 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -126,7 +126,7 @@ out:
enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig, ecryptfs_opt_debug,
ecryptfs_opt_ecryptfs_debug, ecryptfs_opt_cipher,
ecryptfs_opt_ecryptfs_cipher, ecryptfs_opt_ecryptfs_key_bytes,
- ecryptfs_opt_err };
+ ecryptfs_opt_passthrough, ecryptfs_opt_err };

static match_table_t tokens = {
{ecryptfs_opt_sig, "sig=%s"},
@@ -136,6 +136,7 @@ static match_table_t tokens = {
{ecryptfs_opt_cipher, "cipher=%s"},
{ecryptfs_opt_ecryptfs_cipher, "ecryptfs_cipher=%s"},
{ecryptfs_opt_ecryptfs_key_bytes, "ecryptfs_key_bytes=%u"},
+ {ecryptfs_opt_passthrough, "ecryptfs_passthrough"},
{ecryptfs_opt_err, NULL}
};

@@ -273,6 +274,10 @@ static int ecryptfs_parse_options(struct
global_default_cipher_key_size);
cipher_key_bytes_set = 1;
break;
+ case ecryptfs_opt_passthrough:
+ mount_crypt_stat->flags |=
+ ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED;
+ break;
case ecryptfs_opt_err:
default:
ecryptfs_printk(KERN_WARNING,
--
1.3.3

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/