diff options
Diffstat (limited to 'fs/ecryptfs')
-rw-r--r-- | fs/ecryptfs/crypto.c | 9 | ||||
-rw-r--r-- | fs/ecryptfs/inode.c | 20 | ||||
-rw-r--r-- | fs/ecryptfs/keystore.c | 2 | ||||
-rw-r--r-- | fs/ecryptfs/main.c | 6 | ||||
-rw-r--r-- | fs/ecryptfs/messaging.c | 1 | ||||
-rw-r--r-- | fs/ecryptfs/mmap.c | 31 | ||||
-rw-r--r-- | fs/ecryptfs/read_write.c | 27 | ||||
-rw-r--r-- | fs/ecryptfs/super.c | 1 |
8 files changed, 57 insertions, 40 deletions
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index bbed2fd40fd..f8ef0af919e 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -799,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); @@ -808,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; } @@ -1847,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 0b1ab016fa2..5a719180983 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 263fed88c0c..f458c1f3556 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 b83a512b7e0..e5580bcb923 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); diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c index a96d341d154..9cc2aec27b0 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 16a7a555f39..32c5711d79a 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/read_write.c b/fs/ecryptfs/read_write.c index 6b7474a4336..948f57624c0 100644 --- a/fs/ecryptfs/read_write.c +++ b/fs/ecryptfs/read_write.c @@ -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 f8cdab2bee3..4859c4eecd6 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); |