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/file.c | |
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/file.c')
-rw-r--r-- | fs/ecryptfs/file.c | 149 |
1 files changed, 149 insertions, 0 deletions
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, |