aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ecryptfs
diff options
context:
space:
mode:
authorcodeworkx <daniel.hillenbrand@codeworkx.de>2012-06-02 13:09:29 +0200
committercodeworkx <daniel.hillenbrand@codeworkx.de>2012-06-02 13:09:29 +0200
commitc6da2cfeb05178a11c6d062a06f8078150ee492f (patch)
treef3b4021d252c52d6463a9b3c1bb7245e399b009c /fs/ecryptfs
parentc6d7c4dbff353eac7919342ae6b3299a378160a6 (diff)
downloadkernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.zip
kernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.tar.gz
kernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.tar.bz2
samsung update 1
Diffstat (limited to 'fs/ecryptfs')
-rw-r--r--fs/ecryptfs/Kconfig7
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h26
-rw-r--r--fs/ecryptfs/file.c149
-rw-r--r--fs/ecryptfs/inode.c33
-rw-r--r--fs/ecryptfs/keystore.c6
-rw-r--r--fs/ecryptfs/main.c76
-rw-r--r--fs/ecryptfs/super.c4
7 files changed, 298 insertions, 3 deletions
diff --git a/fs/ecryptfs/Kconfig b/fs/ecryptfs/Kconfig
index 1cd6d9d..710f341 100644
--- a/fs/ecryptfs/Kconfig
+++ b/fs/ecryptfs/Kconfig
@@ -12,3 +12,10 @@ config ECRYPT_FS
To compile this file system support as a module, choose M here: the
module will be called ecryptfs.
+
+config WTL_ENCRYPTION_FILTER
+ bool "Enables filtering for some files not to encrypt on eCryptfs"
+ default n
+ depends on ECRYPT_FS
+ help
+ Modification of encrypted filesystem for SD card encryption
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 43c7c43..700775d 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -37,6 +37,13 @@
#include <linux/nsproxy.h>
#include <linux/backing-dev.h>
+#ifdef CONFIG_WTL_ENCRYPTION_FILTER
+#define ENC_NAME_FILTER_MAX_INSTANCE 5
+#define ENC_NAME_FILTER_MAX_LEN (256*5)
+#define ENC_EXT_FILTER_MAX_INSTANCE 60
+#define ENC_EXT_FILTER_MAX_LEN 16
+#endif
+
/* Version verification for shared data structures w/ userspace */
#define ECRYPTFS_VERSION_MAJOR 0x00
#define ECRYPTFS_VERSION_MINOR 0x04
@@ -379,6 +386,10 @@ struct ecryptfs_mount_crypt_stat {
#define ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK 0x00000020
#define ECRYPTFS_GLOBAL_ENCFN_USE_FEK 0x00000040
#define ECRYPTFS_GLOBAL_MOUNT_AUTH_TOK_ONLY 0x00000080
+#ifdef CONFIG_WTL_ENCRYPTION_FILTER
+#define ECRYPTFS_ENABLE_FILTERING 0x00000100
+#define ECRYPTFS_ENABLE_NEW_PASSTHROUGH 0x00000200
+#endif
u32 flags;
struct list_head global_auth_tok_list;
struct mutex global_auth_tok_list_mutex;
@@ -389,6 +400,14 @@ struct ecryptfs_mount_crypt_stat {
unsigned char global_default_fn_cipher_name[
ECRYPTFS_MAX_CIPHER_NAME_SIZE + 1];
char global_default_fnek_sig[ECRYPTFS_SIG_SIZE_HEX + 1];
+#ifdef CONFIG_WTL_ENCRYPTION_FILTER
+ int max_name_filter_len;
+ char enc_filter_name[ENC_NAME_FILTER_MAX_INSTANCE]
+ [ENC_NAME_FILTER_MAX_LEN];
+ char enc_filter_ext[ENC_EXT_FILTER_MAX_INSTANCE]
+ [ENC_EXT_FILTER_MAX_LEN];
+#endif
+
};
/* superblock private data. */
@@ -768,4 +787,11 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
loff_t offset);
+#ifdef CONFIG_WTL_ENCRYPTION_FILTER
+extern int is_file_name_match(struct ecryptfs_mount_crypt_stat *mcs,
+ struct dentry *fp_dentry);
+extern int is_file_ext_match(struct ecryptfs_mount_crypt_stat *mcs,
+ char *str);
+#endif
+
#endif /* #ifndef ECRYPTFS_KERNEL_H */
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 0c1a652..620b608 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -33,6 +33,13 @@
#include <linux/fs_stack.h>
#include "ecryptfs_kernel.h"
+#ifdef CONFIG_WTL_ENCRYPTION_FILTER
+#include <linux/ctype.h>
+#define ECRYPTFS_IOCTL_GET_ATTRIBUTES _IOR('l', 0x10, __u32)
+#define ECRYPTFS_WAS_ENCRYPTED 128
+#endif
+
+
/**
* ecryptfs_read_update_atime
*
@@ -237,6 +244,37 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
rc = 0;
goto out;
}
+#ifdef CONFIG_WTL_ENCRYPTION_FILTER
+ mutex_lock(&crypt_stat->cs_mutex);
+ if ((mount_crypt_stat->flags & ECRYPTFS_ENABLE_NEW_PASSTHROUGH)
+ && (crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
+ if (ecryptfs_read_metadata(ecryptfs_dentry)) {
+ crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED
+ | ECRYPTFS_ENCRYPTED);
+ mutex_unlock(&crypt_stat->cs_mutex);
+ goto out;
+ }
+ } else if ((mount_crypt_stat->flags & ECRYPTFS_ENABLE_FILTERING)
+ && (crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
+ struct dentry *fp_dentry =
+ ecryptfs_inode_to_private(inode)->lower_file->f_dentry;
+ char filename[NAME_MAX+1] = {0};
+ if (fp_dentry->d_name.len <= NAME_MAX)
+ memcpy(filename, fp_dentry->d_name.name,
+ fp_dentry->d_name.len + 1);
+
+ if (is_file_name_match(mount_crypt_stat, fp_dentry)
+ || is_file_ext_match(mount_crypt_stat, filename)) {
+ if (ecryptfs_read_metadata(ecryptfs_dentry))
+ crypt_stat->flags &=
+ ~(ECRYPTFS_I_SIZE_INITIALIZED
+ | ECRYPTFS_ENCRYPTED);
+ mutex_unlock(&crypt_stat->cs_mutex);
+ goto out;
+ }
+ }
+ mutex_unlock(&crypt_stat->cs_mutex);
+#endif
mutex_lock(&crypt_stat->cs_mutex);
if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)
|| !(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {
@@ -319,7 +357,36 @@ ecryptfs_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct file *lower_file = NULL;
long rc = -ENOTTY;
+#ifdef CONFIG_WTL_ENCRYPTION_FILTER
+ if (cmd == ECRYPTFS_IOCTL_GET_ATTRIBUTES) {
+ u32 __user *user_attr = (u32 __user *)arg;
+ u32 attr = 0;
+ char filename[NAME_MAX+1] = {0};
+ struct dentry *ecryptfs_dentry = file->f_path.dentry;
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
+ &ecryptfs_superblock_to_private(ecryptfs_dentry->d_sb)
+ ->mount_crypt_stat;
+
+ struct inode *inode = ecryptfs_dentry->d_inode;
+ struct ecryptfs_crypt_stat *crypt_stat =
+ &ecryptfs_inode_to_private(inode)->crypt_stat;
+ struct dentry *fp_dentry =
+ ecryptfs_inode_to_private(inode)->lower_file->f_dentry;
+ if (fp_dentry->d_name.len <= NAME_MAX)
+ memcpy(filename, fp_dentry->d_name.name,
+ fp_dentry->d_name.len + 1);
+ mutex_lock(&crypt_stat->cs_mutex);
+ if ((crypt_stat->flags & ECRYPTFS_ENCRYPTED) ||
+ ((mount_crypt_stat->flags & ECRYPTFS_ENABLE_FILTERING)
+ && (is_file_name_match(mount_crypt_stat, fp_dentry)
+ || is_file_ext_match(mount_crypt_stat, filename))))
+ attr = ECRYPTFS_WAS_ENCRYPTED;
+ mutex_unlock(&crypt_stat->cs_mutex);
+ put_user(attr, user_attr);
+ return 0;
+ }
+#endif
if (ecryptfs_file_to_private(file))
lower_file = ecryptfs_file_to_lower(file);
if (lower_file && lower_file->f_op && lower_file->f_op->unlocked_ioctl)
@@ -342,6 +409,88 @@ ecryptfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
#endif
+#ifdef CONFIG_WTL_ENCRYPTION_FILTER
+int is_file_name_match(struct ecryptfs_mount_crypt_stat *mcs,
+ struct dentry *fp_dentry)
+{
+ int i;
+ char *str = NULL;
+ if (!(strcmp("/", fp_dentry->d_name.name))
+ || !(strcmp("", fp_dentry->d_name.name)))
+ return 0;
+ str = kzalloc(mcs->max_name_filter_len + 1, GFP_KERNEL);
+ if (!str) {
+ printk(KERN_ERR "%s: Out of memory whilst attempting "
+ "to kzalloc [%zd] bytes\n", __func__,
+ (mcs->max_name_filter_len + 1));
+ return 0;
+ }
+
+ for (i = 0; i < ENC_NAME_FILTER_MAX_INSTANCE; i++) {
+ int len = 0;
+ struct dentry *p = fp_dentry;
+ if (!mcs->enc_filter_name[i] ||
+ !strlen(mcs->enc_filter_name[i]))
+ break;
+
+ while (1) {
+ if (len == 0) {
+ len = strlen(p->d_name.name);
+ if (len > mcs->max_name_filter_len)
+ break;
+ strcpy(str, p->d_name.name);
+ } else {
+ len = len + 1 + strlen(p->d_name.name) ;
+ if (len > mcs->max_name_filter_len)
+ break;
+ strcat(str, "/");
+ strcat(str, p->d_name.name);
+ }
+
+ if (strnicmp(str, mcs->enc_filter_name[i], len))
+ break;
+ p = p->d_parent;
+
+ if (!(strcmp("/", p->d_name.name))
+ || !(strcmp("", p->d_name.name))) {
+ if (len == strlen(mcs->enc_filter_name[i])) {
+ kfree(str);
+ return 1;
+ }
+ break;
+ }
+ }
+ }
+ kfree(str);
+ return 0;
+}
+
+int is_file_ext_match(struct ecryptfs_mount_crypt_stat *mcs, char *str)
+{
+ int i;
+ char ext[NAME_MAX + 1] = {0};
+
+ char *token;
+ int count = 0;
+ while ((token = strsep(&str, ".")) != NULL) {
+ strncpy(ext, token, NAME_MAX);
+ count++;
+ }
+ if (count <= 1)
+ return 0;
+
+ for (i = 0; i < ENC_EXT_FILTER_MAX_INSTANCE; i++) {
+ if (!mcs->enc_filter_ext[i] || !strlen(mcs->enc_filter_ext[i]))
+ return 0;
+ if (strlen(ext) != strlen(mcs->enc_filter_ext[i]))
+ continue;
+ if (!strnicmp(ext, mcs->enc_filter_ext[i], strlen(ext)))
+ return 1;
+ }
+ return 0;
+}
+#endif
+
const struct file_operations ecryptfs_dir_fops = {
.readdir = ecryptfs_readdir,
.read = generic_read_dir,
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 4a4fad7..876b25c 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -269,10 +269,43 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)
ecryptfs_dentry->d_name.name, rc);
goto out;
}
+#ifdef CONFIG_WTL_ENCRYPTION_FILTER
+ mutex_lock(&crypt_stat->cs_mutex);
+ if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) {
+ struct dentry *fp_dentry =
+ ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)
+ ->lower_file->f_dentry;
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
+ &ecryptfs_superblock_to_private(ecryptfs_dentry->d_sb)
+ ->mount_crypt_stat;
+ char filename[NAME_MAX+1] = {0};
+ if (fp_dentry->d_name.len <= NAME_MAX)
+ memcpy(filename, fp_dentry->d_name.name,
+ fp_dentry->d_name.len + 1);
+
+ if ((mount_crypt_stat->flags & ECRYPTFS_ENABLE_NEW_PASSTHROUGH)
+ || ((mount_crypt_stat->flags & ECRYPTFS_ENABLE_FILTERING) &&
+ (is_file_name_match(mount_crypt_stat, fp_dentry) ||
+ is_file_ext_match(mount_crypt_stat, filename)))) {
+ crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED
+ | ECRYPTFS_ENCRYPTED);
+ ecryptfs_put_lower_file(ecryptfs_dentry->d_inode);
+ } else {
+ rc = ecryptfs_write_metadata(ecryptfs_dentry);
+ if (rc)
+ printk(
+ KERN_ERR "Error writing headers; rc = [%d]\n"
+ , rc);
+ ecryptfs_put_lower_file(ecryptfs_dentry->d_inode);
+ }
+ }
+ mutex_unlock(&crypt_stat->cs_mutex);
+#else
rc = ecryptfs_write_metadata(ecryptfs_dentry);
if (rc)
printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc);
ecryptfs_put_lower_file(ecryptfs_dentry->d_inode);
+#endif
out:
return rc;
}
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index 89dc18e..8618569 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -1762,8 +1762,8 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
size_t found_auth_tok;
size_t next_packet_is_auth_tok_packet;
struct list_head auth_tok_list;
- struct ecryptfs_auth_tok *matching_auth_tok;
- struct ecryptfs_auth_tok *candidate_auth_tok;
+ struct ecryptfs_auth_tok *matching_auth_tok = NULL;
+ struct ecryptfs_auth_tok *candidate_auth_tok = NULL;
char *candidate_auth_tok_sig;
size_t packet_size;
struct ecryptfs_auth_tok *new_auth_tok;
@@ -1970,7 +1970,7 @@ pki_encrypt_session_key(struct key *auth_tok_key,
{
struct ecryptfs_msg_ctx *msg_ctx = NULL;
char *payload = NULL;
- size_t payload_len;
+ size_t payload_len = 0;
struct ecryptfs_message *msg;
int rc;
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index b4a6bef..02d0e8d 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -39,6 +39,12 @@
#include <linux/magic.h>
#include "ecryptfs_kernel.h"
+
+#ifdef CONFIG_WTL_ENCRYPTION_FILTER
+#include <linux/ctype.h>
+#endif
+
+
/**
* Module parameter that defines the ecryptfs_verbosity level.
*/
@@ -176,6 +182,9 @@ enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig,
ecryptfs_opt_fn_cipher, ecryptfs_opt_fn_cipher_key_bytes,
ecryptfs_opt_unlink_sigs, ecryptfs_opt_mount_auth_tok_only,
ecryptfs_opt_check_dev_ruid,
+#ifdef CONFIG_WTL_ENCRYPTION_FILTER
+ ecryptfs_opt_enable_filtering,
+#endif
ecryptfs_opt_err };
static const match_table_t tokens = {
@@ -193,6 +202,9 @@ static const match_table_t tokens = {
{ecryptfs_opt_unlink_sigs, "ecryptfs_unlink_sigs"},
{ecryptfs_opt_mount_auth_tok_only, "ecryptfs_mount_auth_tok_only"},
{ecryptfs_opt_check_dev_ruid, "ecryptfs_check_dev_ruid"},
+#ifdef CONFIG_WTL_ENCRYPTION_FILTER
+ {ecryptfs_opt_enable_filtering, "ecryptfs_enable_filtering=%s"},
+#endif
{ecryptfs_opt_err, NULL}
};
@@ -233,7 +245,57 @@ static void ecryptfs_init_mount_crypt_stat(
mutex_init(&mount_crypt_stat->global_auth_tok_list_mutex);
mount_crypt_stat->flags |= ECRYPTFS_MOUNT_CRYPT_STAT_INITIALIZED;
}
+#ifdef CONFIG_WTL_ENCRYPTION_FILTER
+
+static int parse_enc_file_filter_parms(
+ struct ecryptfs_mount_crypt_stat *mcs, char *str)
+{
+ char *token = NULL;
+ int count = 0;
+ mcs->max_name_filter_len = 0;
+ while ((token = strsep(&str, "|")) != NULL) {
+ if (count >= ENC_NAME_FILTER_MAX_INSTANCE)
+ return -1;
+ strncpy(mcs->enc_filter_name[count++],
+ token, ENC_NAME_FILTER_MAX_LEN);
+ if (mcs->max_name_filter_len < strlen(token))
+ mcs->max_name_filter_len = strlen(token);
+ }
+ return 0;
+}
+
+static int parse_enc_ext_filter_parms(
+ struct ecryptfs_mount_crypt_stat *mcs, char *str)
+{
+ char *token = NULL;
+ int count = 0;
+ while ((token = strsep(&str, "|")) != NULL) {
+ if (count >= ENC_EXT_FILTER_MAX_INSTANCE)
+ return -1;
+ strncpy(mcs->enc_filter_ext[count++],
+ token, ENC_EXT_FILTER_MAX_LEN);
+ }
+ return 0;
+}
+
+static int parse_enc_filter_parms(
+ struct ecryptfs_mount_crypt_stat *mcs, char *str)
+{
+ char *token = NULL;
+ if (!strcmp("*", str)) {
+ mcs->flags |= ECRYPTFS_ENABLE_NEW_PASSTHROUGH;
+ return 0;
+ }
+ token = strsep(&str, ":");
+ if (token != NULL)
+ parse_enc_file_filter_parms(mcs, token);
+ token = strsep(&str, ":");
+ if (token != NULL)
+ parse_enc_ext_filter_parms(mcs, token);
+ return 0;
+}
+#endif
/**
* ecryptfs_parse_options
* @sb: The ecryptfs super block
@@ -389,6 +451,19 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options,
case ecryptfs_opt_check_dev_ruid:
*check_ruid = 1;
break;
+#ifdef CONFIG_WTL_ENCRYPTION_FILTER
+ case ecryptfs_opt_enable_filtering:
+ rc = parse_enc_filter_parms(mount_crypt_stat,
+ args[0].from);
+ if (rc) {
+ printk(KERN_ERR "Error attempting to parse encryption "
+ "filtering parameters.\n");
+ rc = -EINVAL;
+ goto out;
+ }
+ mount_crypt_stat->flags |= ECRYPTFS_ENABLE_FILTERING;
+ break;
+#endif
case ecryptfs_opt_err:
default:
printk(KERN_WARNING
@@ -858,6 +933,7 @@ static void __exit ecryptfs_exit(void)
ecryptfs_free_kmem_caches();
}
+
MODULE_AUTHOR("Michael A. Halcrow <mhalcrow@us.ibm.com>");
MODULE_DESCRIPTION("eCryptfs");
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c
index dbd52d40..4cf8da6 100644
--- a/fs/ecryptfs/super.c
+++ b/fs/ecryptfs/super.c
@@ -156,6 +156,10 @@ static int ecryptfs_show_options(struct seq_file *m, struct vfsmount *mnt)
if (mount_crypt_stat->global_default_cipher_key_size)
seq_printf(m, ",ecryptfs_key_bytes=%zd",
mount_crypt_stat->global_default_cipher_key_size);
+#ifdef CONFIG_WTL_ENCRYPTION_FILTER
+ if (mount_crypt_stat->flags & ECRYPTFS_ENABLE_FILTERING)
+ seq_printf(m, ",ecryptfs_enable_filtering");
+#endif
if (mount_crypt_stat->flags & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)
seq_printf(m, ",ecryptfs_passthrough");
if (mount_crypt_stat->flags & ECRYPTFS_XATTR_METADATA_ENABLED)