diff options
author | codeworkx <daniel.hillenbrand@codeworkx.de> | 2012-06-02 13:09:29 +0200 |
---|---|---|
committer | codeworkx <daniel.hillenbrand@codeworkx.de> | 2012-06-02 13:09:29 +0200 |
commit | c6da2cfeb05178a11c6d062a06f8078150ee492f (patch) | |
tree | f3b4021d252c52d6463a9b3c1bb7245e399b009c /fs/ecryptfs | |
parent | c6d7c4dbff353eac7919342ae6b3299a378160a6 (diff) | |
download | kernel_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/Kconfig | 7 | ||||
-rw-r--r-- | fs/ecryptfs/ecryptfs_kernel.h | 26 | ||||
-rw-r--r-- | fs/ecryptfs/file.c | 149 | ||||
-rw-r--r-- | fs/ecryptfs/inode.c | 33 | ||||
-rw-r--r-- | fs/ecryptfs/keystore.c | 6 | ||||
-rw-r--r-- | fs/ecryptfs/main.c | 76 | ||||
-rw-r--r-- | fs/ecryptfs/super.c | 4 |
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) |