aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ecryptfs/file.c
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/file.c
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/file.c')
-rw-r--r--fs/ecryptfs/file.c149
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,