summaryrefslogtreecommitdiffstats
path: root/fs/ecryptfs
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2008-02-03 18:29:41 +1100
committerDavid Woodhouse <dwmw2@infradead.org>2008-02-03 18:30:32 +1100
commitc1f3ee120bb61045b1c0a3ead620d1d65af47130 (patch)
tree908430bf2b47fe8e96ac623ae7ab6dd5698d0938 /fs/ecryptfs
parente619a75ff6201b567a539e787aa9af9bc63a3187 (diff)
parent9135f1901ee6449dfe338adf6e40e9c2025b8150 (diff)
downloadop-kernel-dev-c1f3ee120bb61045b1c0a3ead620d1d65af47130.zip
op-kernel-dev-c1f3ee120bb61045b1c0a3ead620d1d65af47130.tar.gz
Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Diffstat (limited to 'fs/ecryptfs')
-rw-r--r--fs/ecryptfs/crypto.c37
-rw-r--r--fs/ecryptfs/inode.c20
-rw-r--r--fs/ecryptfs/keystore.c2
-rw-r--r--fs/ecryptfs/main.c135
-rw-r--r--fs/ecryptfs/messaging.c1
-rw-r--r--fs/ecryptfs/mmap.c31
-rw-r--r--fs/ecryptfs/netlink.c3
-rw-r--r--fs/ecryptfs/read_write.c29
-rw-r--r--fs/ecryptfs/super.c1
9 files changed, 100 insertions, 159 deletions
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 9d70289..f8ef0af 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -115,11 +115,29 @@ static int ecryptfs_calculate_md5(char *dst,
}
crypt_stat->hash_tfm = desc.tfm;
}
- crypto_hash_init(&desc);
- crypto_hash_update(&desc, &sg, len);
- crypto_hash_final(&desc, dst);
- mutex_unlock(&crypt_stat->cs_hash_tfm_mutex);
+ rc = crypto_hash_init(&desc);
+ if (rc) {
+ printk(KERN_ERR
+ "%s: Error initializing crypto hash; rc = [%d]\n",
+ __FUNCTION__, rc);
+ goto out;
+ }
+ rc = crypto_hash_update(&desc, &sg, len);
+ if (rc) {
+ printk(KERN_ERR
+ "%s: Error updating crypto hash; rc = [%d]\n",
+ __FUNCTION__, rc);
+ goto out;
+ }
+ rc = crypto_hash_final(&desc, dst);
+ if (rc) {
+ printk(KERN_ERR
+ "%s: Error finalizing crypto hash; rc = [%d]\n",
+ __FUNCTION__, rc);
+ goto out;
+ }
out:
+ mutex_unlock(&crypt_stat->cs_hash_tfm_mutex);
return rc;
}
@@ -504,7 +522,6 @@ int ecryptfs_encrypt_page(struct page *page)
"\n", rc);
goto out;
}
- extent_offset++;
}
out:
kfree(enc_extent_virt);
@@ -640,7 +657,6 @@ int ecryptfs_decrypt_page(struct page *page)
"rc = [%d]\n", __FUNCTION__, rc);
goto out;
}
- extent_offset++;
}
out:
kfree(enc_extent_virt);
@@ -783,7 +799,7 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat)
rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name,
crypt_stat->cipher, "cbc");
if (rc)
- goto out;
+ goto out_unlock;
crypt_stat->tfm = crypto_alloc_blkcipher(full_alg_name, 0,
CRYPTO_ALG_ASYNC);
kfree(full_alg_name);
@@ -792,12 +808,12 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat)
ecryptfs_printk(KERN_ERR, "cryptfs: init_crypt_ctx(): "
"Error initializing cipher [%s]\n",
crypt_stat->cipher);
- mutex_unlock(&crypt_stat->cs_tfm_mutex);
- goto out;
+ goto out_unlock;
}
crypto_blkcipher_set_flags(crypt_stat->tfm, CRYPTO_TFM_REQ_WEAK_KEY);
- mutex_unlock(&crypt_stat->cs_tfm_mutex);
rc = 0;
+out_unlock:
+ mutex_unlock(&crypt_stat->cs_tfm_mutex);
out:
return rc;
}
@@ -1831,6 +1847,7 @@ ecryptfs_add_new_key_tfm(struct ecryptfs_key_tfm **key_tfm, char *cipher_name,
mutex_init(&tmp_tfm->key_tfm_mutex);
strncpy(tmp_tfm->cipher_name, cipher_name,
ECRYPTFS_MAX_CIPHER_NAME_SIZE);
+ tmp_tfm->cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE] = '\0';
tmp_tfm->key_size = key_size;
rc = ecryptfs_process_key_cipher(&tmp_tfm->key_tfm,
tmp_tfm->cipher_name,
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 0b1ab01..5a71918 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -120,22 +120,9 @@ ecryptfs_do_create(struct inode *directory_inode,
rc = ecryptfs_create_underlying_file(lower_dir_dentry->d_inode,
ecryptfs_dentry, mode, nd);
if (rc) {
- struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode;
- struct ecryptfs_inode_info *inode_info =
- ecryptfs_inode_to_private(ecryptfs_inode);
-
- printk(KERN_WARNING "%s: Error creating underlying file; "
- "rc = [%d]; checking for existing\n", __FUNCTION__, rc);
- if (inode_info) {
- mutex_lock(&inode_info->lower_file_mutex);
- if (!inode_info->lower_file) {
- mutex_unlock(&inode_info->lower_file_mutex);
- printk(KERN_ERR "%s: Failure to set underlying "
- "file; rc = [%d]\n", __FUNCTION__, rc);
- goto out_lock;
- }
- mutex_unlock(&inode_info->lower_file_mutex);
- }
+ printk(KERN_ERR "%s: Failure to create dentry in lower fs; "
+ "rc = [%d]\n", __FUNCTION__, rc);
+ goto out_lock;
}
rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry,
directory_inode->i_sb, 0);
@@ -451,6 +438,7 @@ static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry)
dentry->d_inode->i_nlink =
ecryptfs_inode_to_lower(dentry->d_inode)->i_nlink;
dentry->d_inode->i_ctime = dir->i_ctime;
+ d_drop(dentry);
out_unlock:
unlock_parent(lower_dentry);
return rc;
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index 263fed8..f458c1f 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -1860,7 +1860,7 @@ ecryptfs_add_global_auth_tok(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
struct ecryptfs_global_auth_tok *new_auth_tok;
int rc = 0;
- new_auth_tok = kmem_cache_alloc(ecryptfs_global_auth_tok_cache,
+ new_auth_tok = kmem_cache_zalloc(ecryptfs_global_auth_tok_cache,
GFP_KERNEL);
if (!new_auth_tok) {
rc = -ENOMEM;
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index b83a512..0249aa4 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -138,11 +138,14 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
inode_info->lower_file = dentry_open(lower_dentry,
lower_mnt,
(O_RDWR | O_LARGEFILE));
- if (IS_ERR(inode_info->lower_file))
+ if (IS_ERR(inode_info->lower_file)) {
+ dget(lower_dentry);
+ mntget(lower_mnt);
inode_info->lower_file = dentry_open(lower_dentry,
lower_mnt,
(O_RDONLY
| O_LARGEFILE));
+ }
if (IS_ERR(inode_info->lower_file)) {
printk(KERN_ERR "Error opening lower persistent file "
"for lower_dentry [0x%p] and lower_mnt [0x%p]\n",
@@ -523,6 +526,7 @@ static int ecryptfs_read_super(struct super_block *sb, const char *dev_name)
lower_mnt = nd.mnt;
ecryptfs_set_superblock_lower(sb, lower_root->d_sb);
sb->s_maxbytes = lower_root->d_sb->s_maxbytes;
+ sb->s_blocksize = lower_root->d_sb->s_blocksize;
ecryptfs_set_dentry_lower(sb->s_root, lower_root);
ecryptfs_set_dentry_lower_mnt(sb->s_root, lower_mnt);
rc = ecryptfs_interpose(lower_root, sb->s_root, sb, 0);
@@ -730,127 +734,40 @@ static int ecryptfs_init_kmem_caches(void)
return 0;
}
-struct ecryptfs_obj {
- char *name;
- struct list_head slot_list;
- struct kobject kobj;
-};
-
-struct ecryptfs_attribute {
- struct attribute attr;
- ssize_t(*show) (struct ecryptfs_obj *, char *);
- ssize_t(*store) (struct ecryptfs_obj *, const char *, size_t);
-};
-
-static ssize_t
-ecryptfs_attr_store(struct kobject *kobj,
- struct attribute *attr, const char *buf, size_t len)
-{
- struct ecryptfs_obj *obj = container_of(kobj, struct ecryptfs_obj,
- kobj);
- struct ecryptfs_attribute *attribute =
- container_of(attr, struct ecryptfs_attribute, attr);
-
- return (attribute->store ? attribute->store(obj, buf, len) : 0);
-}
+static struct kobject *ecryptfs_kobj;
-static ssize_t
-ecryptfs_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
+static ssize_t version_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buff)
{
- struct ecryptfs_obj *obj = container_of(kobj, struct ecryptfs_obj,
- kobj);
- struct ecryptfs_attribute *attribute =
- container_of(attr, struct ecryptfs_attribute, attr);
-
- return (attribute->show ? attribute->show(obj, buf) : 0);
+ return snprintf(buff, PAGE_SIZE, "%d\n", ECRYPTFS_VERSIONING_MASK);
}
-static struct sysfs_ops ecryptfs_sysfs_ops = {
- .show = ecryptfs_attr_show,
- .store = ecryptfs_attr_store
-};
+static struct kobj_attribute version_attr = __ATTR_RO(version);
-static struct kobj_type ecryptfs_ktype = {
- .sysfs_ops = &ecryptfs_sysfs_ops
+static struct attribute *attributes[] = {
+ &version_attr.attr,
+ NULL,
};
-static decl_subsys(ecryptfs, &ecryptfs_ktype, NULL);
-
-static ssize_t version_show(struct ecryptfs_obj *obj, char *buff)
-{
- return snprintf(buff, PAGE_SIZE, "%d\n", ECRYPTFS_VERSIONING_MASK);
-}
-
-static struct ecryptfs_attribute sysfs_attr_version = __ATTR_RO(version);
-
-static struct ecryptfs_version_str_map_elem {
- u32 flag;
- char *str;
-} ecryptfs_version_str_map[] = {
- {ECRYPTFS_VERSIONING_PASSPHRASE, "passphrase"},
- {ECRYPTFS_VERSIONING_PUBKEY, "pubkey"},
- {ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH, "plaintext passthrough"},
- {ECRYPTFS_VERSIONING_POLICY, "policy"},
- {ECRYPTFS_VERSIONING_XATTR, "metadata in extended attribute"},
- {ECRYPTFS_VERSIONING_MULTKEY, "multiple keys per file"}
+static struct attribute_group attr_group = {
+ .attrs = attributes,
};
-static ssize_t version_str_show(struct ecryptfs_obj *obj, char *buff)
-{
- int i;
- int remaining = PAGE_SIZE;
- int total_written = 0;
-
- buff[0] = '\0';
- for (i = 0; i < ARRAY_SIZE(ecryptfs_version_str_map); i++) {
- int entry_size;
-
- if (!(ECRYPTFS_VERSIONING_MASK
- & ecryptfs_version_str_map[i].flag))
- continue;
- entry_size = strlen(ecryptfs_version_str_map[i].str);
- if ((entry_size + 2) > remaining)
- goto out;
- memcpy(buff, ecryptfs_version_str_map[i].str, entry_size);
- buff[entry_size++] = '\n';
- buff[entry_size] = '\0';
- buff += entry_size;
- total_written += entry_size;
- remaining -= entry_size;
- }
-out:
- return total_written;
-}
-
-static struct ecryptfs_attribute sysfs_attr_version_str = __ATTR_RO(version_str);
-
static int do_sysfs_registration(void)
{
int rc;
- rc = subsystem_register(&ecryptfs_subsys);
- if (rc) {
- printk(KERN_ERR
- "Unable to register ecryptfs sysfs subsystem\n");
- goto out;
- }
- rc = sysfs_create_file(&ecryptfs_subsys.kobj,
- &sysfs_attr_version.attr);
- if (rc) {
- printk(KERN_ERR
- "Unable to create ecryptfs version attribute\n");
- subsystem_unregister(&ecryptfs_subsys);
+ ecryptfs_kobj = kobject_create_and_add("ecryptfs", fs_kobj);
+ if (!ecryptfs_kobj) {
+ printk(KERN_ERR "Unable to create ecryptfs kset\n");
+ rc = -ENOMEM;
goto out;
}
- rc = sysfs_create_file(&ecryptfs_subsys.kobj,
- &sysfs_attr_version_str.attr);
+ rc = sysfs_create_group(ecryptfs_kobj, &attr_group);
if (rc) {
printk(KERN_ERR
- "Unable to create ecryptfs version_str attribute\n");
- sysfs_remove_file(&ecryptfs_subsys.kobj,
- &sysfs_attr_version.attr);
- subsystem_unregister(&ecryptfs_subsys);
- goto out;
+ "Unable to create ecryptfs version attributes\n");
+ kobject_put(ecryptfs_kobj);
}
out:
return rc;
@@ -858,11 +775,8 @@ out:
static void do_sysfs_unregistration(void)
{
- sysfs_remove_file(&ecryptfs_subsys.kobj,
- &sysfs_attr_version.attr);
- sysfs_remove_file(&ecryptfs_subsys.kobj,
- &sysfs_attr_version_str.attr);
- subsystem_unregister(&ecryptfs_subsys);
+ sysfs_remove_group(ecryptfs_kobj, &attr_group);
+ kobject_put(ecryptfs_kobj);
}
static int __init ecryptfs_init(void)
@@ -890,7 +804,6 @@ static int __init ecryptfs_init(void)
printk(KERN_ERR "Failed to register filesystem\n");
goto out_free_kmem_caches;
}
- kobj_set_kset_s(&ecryptfs_subsys, fs_subsys);
rc = do_sysfs_registration();
if (rc) {
printk(KERN_ERR "sysfs registration failed\n");
diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c
index a96d341..9cc2aec 100644
--- a/fs/ecryptfs/messaging.c
+++ b/fs/ecryptfs/messaging.c
@@ -427,6 +427,7 @@ int ecryptfs_init_messaging(unsigned int transport)
if (!ecryptfs_daemon_id_hash) {
rc = -ENOMEM;
ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n");
+ mutex_unlock(&ecryptfs_daemon_id_hash_mux);
goto out;
}
for (i = 0; i < ecryptfs_hash_buckets; i++)
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 16a7a55..32c5711 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -263,14 +263,13 @@ out:
return 0;
}
+/* This function must zero any hole we create */
static int ecryptfs_prepare_write(struct file *file, struct page *page,
unsigned from, unsigned to)
{
int rc = 0;
+ loff_t prev_page_end_size;
- if (from == 0 && to == PAGE_CACHE_SIZE)
- goto out; /* If we are writing a full page, it will be
- up to date. */
if (!PageUptodate(page)) {
rc = ecryptfs_read_lower_page_segment(page, page->index, 0,
PAGE_CACHE_SIZE,
@@ -283,22 +282,32 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page,
} else
SetPageUptodate(page);
}
- if (page->index != 0) {
- loff_t end_of_prev_pg_pos =
- (((loff_t)page->index << PAGE_CACHE_SHIFT) - 1);
- if (end_of_prev_pg_pos > i_size_read(page->mapping->host)) {
+ prev_page_end_size = ((loff_t)page->index << PAGE_CACHE_SHIFT);
+
+ /*
+ * If creating a page or more of holes, zero them out via truncate.
+ * Note, this will increase i_size.
+ */
+ if (page->index != 0) {
+ if (prev_page_end_size > i_size_read(page->mapping->host)) {
rc = ecryptfs_truncate(file->f_path.dentry,
- end_of_prev_pg_pos);
+ prev_page_end_size);
if (rc) {
printk(KERN_ERR "Error on attempt to "
"truncate to (higher) offset [%lld];"
- " rc = [%d]\n", end_of_prev_pg_pos, rc);
+ " rc = [%d]\n", prev_page_end_size, rc);
goto out;
}
}
- if (end_of_prev_pg_pos + 1 > i_size_read(page->mapping->host))
- zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
+ }
+ /*
+ * Writing to a new page, and creating a small hole from start of page?
+ * Zero it out.
+ */
+ if ((i_size_read(page->mapping->host) == prev_page_end_size) &&
+ (from != 0)) {
+ zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
}
out:
return rc;
diff --git a/fs/ecryptfs/netlink.c b/fs/ecryptfs/netlink.c
index 9aa3451..f638a69 100644
--- a/fs/ecryptfs/netlink.c
+++ b/fs/ecryptfs/netlink.c
@@ -237,7 +237,6 @@ out:
*/
void ecryptfs_release_netlink(void)
{
- if (ecryptfs_nl_sock && ecryptfs_nl_sock->sk_socket)
- sock_release(ecryptfs_nl_sock->sk_socket);
+ netlink_kernel_release(ecryptfs_nl_sock);
ecryptfs_nl_sock = NULL;
}
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c
index 2150edf..948f576 100644
--- a/fs/ecryptfs/read_write.c
+++ b/fs/ecryptfs/read_write.c
@@ -87,7 +87,7 @@ int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode,
loff_t offset;
int rc;
- offset = ((((off_t)page_for_lower->index) << PAGE_CACHE_SHIFT)
+ offset = ((((loff_t)page_for_lower->index) << PAGE_CACHE_SHIFT)
+ offset_in_page);
virt = kmap(page_for_lower);
rc = ecryptfs_write_lower(ecryptfs_inode, virt, offset, size);
@@ -124,6 +124,10 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
loff_t pos;
int rc = 0;
+ /*
+ * if we are writing beyond current size, then start pos
+ * at the current size - we'll fill in zeros from there.
+ */
if (offset > ecryptfs_file_size)
pos = ecryptfs_file_size;
else
@@ -137,6 +141,7 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
if (num_bytes > total_remaining_bytes)
num_bytes = total_remaining_bytes;
if (pos < offset) {
+ /* remaining zeros to write, up to destination offset */
size_t total_remaining_zeros = (offset - pos);
if (num_bytes > total_remaining_zeros)
@@ -167,17 +172,27 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
}
}
ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0);
+
+ /*
+ * pos: where we're now writing, offset: where the request was
+ * If current pos is before request, we are filling zeros
+ * If we are at or beyond request, we are writing the *data*
+ * If we're in a fresh page beyond eof, zero it in either case
+ */
+ if (pos < offset || !start_offset_in_page) {
+ /* We are extending past the previous end of the file.
+ * Fill in zero values to the end of the page */
+ memset(((char *)ecryptfs_page_virt
+ + start_offset_in_page), 0,
+ PAGE_CACHE_SIZE - start_offset_in_page);
+ }
+
+ /* pos >= offset, we are now writing the data request */
if (pos >= offset) {
memcpy(((char *)ecryptfs_page_virt
+ start_offset_in_page),
(data + data_offset), num_bytes);
data_offset += num_bytes;
- } else {
- /* We are extending past the previous end of the file.
- * Fill in zero values up to the start of where we
- * will be writing data. */
- memset(((char *)ecryptfs_page_virt
- + start_offset_in_page), 0, num_bytes);
}
kunmap_atomic(ecryptfs_page_virt, KM_USER0);
flush_dcache_page(ecryptfs_page);
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c
index f8cdab2b..4859c4e 100644
--- a/fs/ecryptfs/super.c
+++ b/fs/ecryptfs/super.c
@@ -86,7 +86,6 @@ static void ecryptfs_destroy_inode(struct inode *inode)
fput(inode_info->lower_file);
inode_info->lower_file = NULL;
d_drop(lower_dentry);
- d_delete(lower_dentry);
}
}
mutex_unlock(&inode_info->lower_file_mutex);
OpenPOWER on IntegriCloud