diff options
Diffstat (limited to 'ANDROID_3.4.5/fs/ecryptfs')
-rw-r--r-- | ANDROID_3.4.5/fs/ecryptfs/Kconfig | 14 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/ecryptfs/Makefile | 7 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/ecryptfs/crypto.c | 2295 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/ecryptfs/debug.c | 121 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/ecryptfs/dentry.c | 105 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/ecryptfs/ecryptfs_kernel.h | 713 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/ecryptfs/file.c | 379 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/ecryptfs/inode.c | 1194 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/ecryptfs/keystore.c | 2531 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/ecryptfs/kthread.c | 197 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/ecryptfs/main.c | 866 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/ecryptfs/messaging.c | 578 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/ecryptfs/miscdev.c | 567 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/ecryptfs/mmap.c | 566 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/ecryptfs/read_write.c | 284 | ||||
-rw-r--r-- | ANDROID_3.4.5/fs/ecryptfs/super.c | 191 |
16 files changed, 0 insertions, 10608 deletions
diff --git a/ANDROID_3.4.5/fs/ecryptfs/Kconfig b/ANDROID_3.4.5/fs/ecryptfs/Kconfig deleted file mode 100644 index cc165626..00000000 --- a/ANDROID_3.4.5/fs/ecryptfs/Kconfig +++ /dev/null @@ -1,14 +0,0 @@ -config ECRYPT_FS - tristate "eCrypt filesystem layer support (EXPERIMENTAL)" - depends on EXPERIMENTAL && KEYS && CRYPTO && (ENCRYPTED_KEYS || ENCRYPTED_KEYS=n) - select CRYPTO_ECB - select CRYPTO_CBC - select CRYPTO_MD5 - help - Encrypted filesystem that operates on the VFS layer. See - <file:Documentation/filesystems/ecryptfs.txt> to learn more about - eCryptfs. Userspace components are required and can be - obtained from <http://ecryptfs.sf.net>. - - To compile this file system support as a module, choose M here: the - module will be called ecryptfs. diff --git a/ANDROID_3.4.5/fs/ecryptfs/Makefile b/ANDROID_3.4.5/fs/ecryptfs/Makefile deleted file mode 100644 index 2cc9ee4a..00000000 --- a/ANDROID_3.4.5/fs/ecryptfs/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# Makefile for the Linux 2.6 eCryptfs -# - -obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o - -ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o crypto.o keystore.o messaging.o miscdev.o kthread.o debug.o diff --git a/ANDROID_3.4.5/fs/ecryptfs/crypto.c b/ANDROID_3.4.5/fs/ecryptfs/crypto.c deleted file mode 100644 index ea993128..00000000 --- a/ANDROID_3.4.5/fs/ecryptfs/crypto.c +++ /dev/null @@ -1,2295 +0,0 @@ -/** - * eCryptfs: Linux filesystem encryption layer - * - * Copyright (C) 1997-2004 Erez Zadok - * Copyright (C) 2001-2004 Stony Brook University - * Copyright (C) 2004-2007 International Business Machines Corp. - * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> - * Michael C. Thompson <mcthomps@us.ibm.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <linux/fs.h> -#include <linux/mount.h> -#include <linux/pagemap.h> -#include <linux/random.h> -#include <linux/compiler.h> -#include <linux/key.h> -#include <linux/namei.h> -#include <linux/crypto.h> -#include <linux/file.h> -#include <linux/scatterlist.h> -#include <linux/slab.h> -#include <asm/unaligned.h> -#include "ecryptfs_kernel.h" - -static int -ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, - struct page *dst_page, int dst_offset, - struct page *src_page, int src_offset, int size, - unsigned char *iv); -static int -ecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, - struct page *dst_page, int dst_offset, - struct page *src_page, int src_offset, int size, - unsigned char *iv); - -/** - * ecryptfs_to_hex - * @dst: Buffer to take hex character representation of contents of - * src; must be at least of size (src_size * 2) - * @src: Buffer to be converted to a hex string respresentation - * @src_size: number of bytes to convert - */ -void ecryptfs_to_hex(char *dst, char *src, size_t src_size) -{ - int x; - - for (x = 0; x < src_size; x++) - sprintf(&dst[x * 2], "%.2x", (unsigned char)src[x]); -} - -/** - * ecryptfs_from_hex - * @dst: Buffer to take the bytes from src hex; must be at least of - * size (src_size / 2) - * @src: Buffer to be converted from a hex string respresentation to raw value - * @dst_size: size of dst buffer, or number of hex characters pairs to convert - */ -void ecryptfs_from_hex(char *dst, char *src, int dst_size) -{ - int x; - char tmp[3] = { 0, }; - - for (x = 0; x < dst_size; x++) { - tmp[0] = src[x * 2]; - tmp[1] = src[x * 2 + 1]; - dst[x] = (unsigned char)simple_strtol(tmp, NULL, 16); - } -} - -/** - * ecryptfs_calculate_md5 - calculates the md5 of @src - * @dst: Pointer to 16 bytes of allocated memory - * @crypt_stat: Pointer to crypt_stat struct for the current inode - * @src: Data to be md5'd - * @len: Length of @src - * - * Uses the allocated crypto context that crypt_stat references to - * generate the MD5 sum of the contents of src. - */ -static int ecryptfs_calculate_md5(char *dst, - struct ecryptfs_crypt_stat *crypt_stat, - char *src, int len) -{ - struct scatterlist sg; - struct hash_desc desc = { - .tfm = crypt_stat->hash_tfm, - .flags = CRYPTO_TFM_REQ_MAY_SLEEP - }; - int rc = 0; - - mutex_lock(&crypt_stat->cs_hash_tfm_mutex); - sg_init_one(&sg, (u8 *)src, len); - if (!desc.tfm) { - desc.tfm = crypto_alloc_hash(ECRYPTFS_DEFAULT_HASH, 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(desc.tfm)) { - rc = PTR_ERR(desc.tfm); - ecryptfs_printk(KERN_ERR, "Error attempting to " - "allocate crypto context; rc = [%d]\n", - rc); - goto out; - } - crypt_stat->hash_tfm = desc.tfm; - } - rc = crypto_hash_init(&desc); - if (rc) { - printk(KERN_ERR - "%s: Error initializing crypto hash; rc = [%d]\n", - __func__, rc); - goto out; - } - rc = crypto_hash_update(&desc, &sg, len); - if (rc) { - printk(KERN_ERR - "%s: Error updating crypto hash; rc = [%d]\n", - __func__, rc); - goto out; - } - rc = crypto_hash_final(&desc, dst); - if (rc) { - printk(KERN_ERR - "%s: Error finalizing crypto hash; rc = [%d]\n", - __func__, rc); - goto out; - } -out: - mutex_unlock(&crypt_stat->cs_hash_tfm_mutex); - return rc; -} - -static int ecryptfs_crypto_api_algify_cipher_name(char **algified_name, - char *cipher_name, - char *chaining_modifier) -{ - int cipher_name_len = strlen(cipher_name); - int chaining_modifier_len = strlen(chaining_modifier); - int algified_name_len; - int rc; - - algified_name_len = (chaining_modifier_len + cipher_name_len + 3); - (*algified_name) = kmalloc(algified_name_len, GFP_KERNEL); - if (!(*algified_name)) { - rc = -ENOMEM; - goto out; - } - snprintf((*algified_name), algified_name_len, "%s(%s)", - chaining_modifier, cipher_name); - rc = 0; -out: - return rc; -} - -/** - * ecryptfs_derive_iv - * @iv: destination for the derived iv vale - * @crypt_stat: Pointer to crypt_stat struct for the current inode - * @offset: Offset of the extent whose IV we are to derive - * - * Generate the initialization vector from the given root IV and page - * offset. - * - * Returns zero on success; non-zero on error. - */ -int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat, - loff_t offset) -{ - int rc = 0; - char dst[MD5_DIGEST_SIZE]; - char src[ECRYPTFS_MAX_IV_BYTES + 16]; - - if (unlikely(ecryptfs_verbosity > 0)) { - ecryptfs_printk(KERN_DEBUG, "root iv:\n"); - ecryptfs_dump_hex(crypt_stat->root_iv, crypt_stat->iv_bytes); - } - /* TODO: It is probably secure to just cast the least - * significant bits of the root IV into an unsigned long and - * add the offset to that rather than go through all this - * hashing business. -Halcrow */ - memcpy(src, crypt_stat->root_iv, crypt_stat->iv_bytes); - memset((src + crypt_stat->iv_bytes), 0, 16); - snprintf((src + crypt_stat->iv_bytes), 16, "%lld", offset); - if (unlikely(ecryptfs_verbosity > 0)) { - ecryptfs_printk(KERN_DEBUG, "source:\n"); - ecryptfs_dump_hex(src, (crypt_stat->iv_bytes + 16)); - } - rc = ecryptfs_calculate_md5(dst, crypt_stat, src, - (crypt_stat->iv_bytes + 16)); - if (rc) { - ecryptfs_printk(KERN_WARNING, "Error attempting to compute " - "MD5 while generating IV for a page\n"); - goto out; - } - memcpy(iv, dst, crypt_stat->iv_bytes); - if (unlikely(ecryptfs_verbosity > 0)) { - ecryptfs_printk(KERN_DEBUG, "derived iv:\n"); - ecryptfs_dump_hex(iv, crypt_stat->iv_bytes); - } -out: - return rc; -} - -/** - * ecryptfs_init_crypt_stat - * @crypt_stat: Pointer to the crypt_stat struct to initialize. - * - * Initialize the crypt_stat structure. - */ -void -ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) -{ - memset((void *)crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat)); - INIT_LIST_HEAD(&crypt_stat->keysig_list); - mutex_init(&crypt_stat->keysig_list_mutex); - mutex_init(&crypt_stat->cs_mutex); - mutex_init(&crypt_stat->cs_tfm_mutex); - mutex_init(&crypt_stat->cs_hash_tfm_mutex); - crypt_stat->flags |= ECRYPTFS_STRUCT_INITIALIZED; -} - -/** - * ecryptfs_destroy_crypt_stat - * @crypt_stat: Pointer to the crypt_stat struct to initialize. - * - * Releases all memory associated with a crypt_stat struct. - */ -void ecryptfs_destroy_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) -{ - struct ecryptfs_key_sig *key_sig, *key_sig_tmp; - - if (crypt_stat->tfm) - crypto_free_blkcipher(crypt_stat->tfm); - if (crypt_stat->hash_tfm) - crypto_free_hash(crypt_stat->hash_tfm); - list_for_each_entry_safe(key_sig, key_sig_tmp, - &crypt_stat->keysig_list, crypt_stat_list) { - list_del(&key_sig->crypt_stat_list); - kmem_cache_free(ecryptfs_key_sig_cache, key_sig); - } - memset(crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat)); -} - -void ecryptfs_destroy_mount_crypt_stat( - struct ecryptfs_mount_crypt_stat *mount_crypt_stat) -{ - struct ecryptfs_global_auth_tok *auth_tok, *auth_tok_tmp; - - if (!(mount_crypt_stat->flags & ECRYPTFS_MOUNT_CRYPT_STAT_INITIALIZED)) - return; - mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex); - list_for_each_entry_safe(auth_tok, auth_tok_tmp, - &mount_crypt_stat->global_auth_tok_list, - mount_crypt_stat_list) { - list_del(&auth_tok->mount_crypt_stat_list); - if (auth_tok->global_auth_tok_key - && !(auth_tok->flags & ECRYPTFS_AUTH_TOK_INVALID)) - key_put(auth_tok->global_auth_tok_key); - kmem_cache_free(ecryptfs_global_auth_tok_cache, auth_tok); - } - mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex); - memset(mount_crypt_stat, 0, sizeof(struct ecryptfs_mount_crypt_stat)); -} - -/** - * virt_to_scatterlist - * @addr: Virtual address - * @size: Size of data; should be an even multiple of the block size - * @sg: Pointer to scatterlist array; set to NULL to obtain only - * the number of scatterlist structs required in array - * @sg_size: Max array size - * - * Fills in a scatterlist array with page references for a passed - * virtual address. - * - * Returns the number of scatterlist structs in array used - */ -int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg, - int sg_size) -{ - int i = 0; - struct page *pg; - int offset; - int remainder_of_page; - - sg_init_table(sg, sg_size); - - while (size > 0 && i < sg_size) { - pg = virt_to_page(addr); - offset = offset_in_page(addr); - if (sg) - sg_set_page(&sg[i], pg, 0, offset); - remainder_of_page = PAGE_CACHE_SIZE - offset; - if (size >= remainder_of_page) { - if (sg) - sg[i].length = remainder_of_page; - addr += remainder_of_page; - size -= remainder_of_page; - } else { - if (sg) - sg[i].length = size; - addr += size; - size = 0; - } - i++; - } - if (size > 0) - return -ENOMEM; - return i; -} - -/** - * encrypt_scatterlist - * @crypt_stat: Pointer to the crypt_stat struct to initialize. - * @dest_sg: Destination of encrypted data - * @src_sg: Data to be encrypted - * @size: Length of data to be encrypted - * @iv: iv to use during encryption - * - * Returns the number of bytes encrypted; negative value on error - */ -static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, - struct scatterlist *dest_sg, - struct scatterlist *src_sg, int size, - unsigned char *iv) -{ - struct blkcipher_desc desc = { - .tfm = crypt_stat->tfm, - .info = iv, - .flags = CRYPTO_TFM_REQ_MAY_SLEEP - }; - int rc = 0; - - BUG_ON(!crypt_stat || !crypt_stat->tfm - || !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED)); - if (unlikely(ecryptfs_verbosity > 0)) { - ecryptfs_printk(KERN_DEBUG, "Key size [%zd]; key:\n", - crypt_stat->key_size); - ecryptfs_dump_hex(crypt_stat->key, - crypt_stat->key_size); - } - /* Consider doing this once, when the file is opened */ - mutex_lock(&crypt_stat->cs_tfm_mutex); - if (!(crypt_stat->flags & ECRYPTFS_KEY_SET)) { - rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key, - crypt_stat->key_size); - crypt_stat->flags |= ECRYPTFS_KEY_SET; - } - if (rc) { - ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n", - rc); - mutex_unlock(&crypt_stat->cs_tfm_mutex); - rc = -EINVAL; - goto out; - } - ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes.\n", size); - crypto_blkcipher_encrypt_iv(&desc, dest_sg, src_sg, size); - mutex_unlock(&crypt_stat->cs_tfm_mutex); -out: - return rc; -} - -/** - * ecryptfs_lower_offset_for_extent - * - * Convert an eCryptfs page index into a lower byte offset - */ -static void ecryptfs_lower_offset_for_extent(loff_t *offset, loff_t extent_num, - struct ecryptfs_crypt_stat *crypt_stat) -{ - (*offset) = ecryptfs_lower_header_size(crypt_stat) - + (crypt_stat->extent_size * extent_num); -} - -/** - * ecryptfs_encrypt_extent - * @enc_extent_page: Allocated page into which to encrypt the data in - * @page - * @crypt_stat: crypt_stat containing cryptographic context for the - * encryption operation - * @page: Page containing plaintext data extent to encrypt - * @extent_offset: Page extent offset for use in generating IV - * - * Encrypts one extent of data. - * - * Return zero on success; non-zero otherwise - */ -static int ecryptfs_encrypt_extent(struct page *enc_extent_page, - struct ecryptfs_crypt_stat *crypt_stat, - struct page *page, - unsigned long extent_offset) -{ - loff_t extent_base; - char extent_iv[ECRYPTFS_MAX_IV_BYTES]; - int rc; - - extent_base = (((loff_t)page->index) - * (PAGE_CACHE_SIZE / crypt_stat->extent_size)); - rc = ecryptfs_derive_iv(extent_iv, crypt_stat, - (extent_base + extent_offset)); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error attempting to derive IV for " - "extent [0x%.16llx]; rc = [%d]\n", - (unsigned long long)(extent_base + extent_offset), rc); - goto out; - } - rc = ecryptfs_encrypt_page_offset(crypt_stat, enc_extent_page, 0, - page, (extent_offset - * crypt_stat->extent_size), - crypt_stat->extent_size, extent_iv); - if (rc < 0) { - printk(KERN_ERR "%s: Error attempting to encrypt page with " - "page->index = [%ld], extent_offset = [%ld]; " - "rc = [%d]\n", __func__, page->index, extent_offset, - rc); - goto out; - } - rc = 0; -out: - return rc; -} - -/** - * ecryptfs_encrypt_page - * @page: Page mapped from the eCryptfs inode for the file; contains - * decrypted content that needs to be encrypted (to a temporary - * page; not in place) and written out to the lower file - * - * Encrypt an eCryptfs page. This is done on a per-extent basis. Note - * that eCryptfs pages may straddle the lower pages -- for instance, - * if the file was created on a machine with an 8K page size - * (resulting in an 8K header), and then the file is copied onto a - * host with a 32K page size, then when reading page 0 of the eCryptfs - * file, 24K of page 0 of the lower file will be read and decrypted, - * and then 8K of page 1 of the lower file will be read and decrypted. - * - * Returns zero on success; negative on error - */ -int ecryptfs_encrypt_page(struct page *page) -{ - struct inode *ecryptfs_inode; - struct ecryptfs_crypt_stat *crypt_stat; - char *enc_extent_virt; - struct page *enc_extent_page = NULL; - loff_t extent_offset; - int rc = 0; - - ecryptfs_inode = page->mapping->host; - crypt_stat = - &(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat); - BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)); - enc_extent_page = alloc_page(GFP_USER); - if (!enc_extent_page) { - rc = -ENOMEM; - ecryptfs_printk(KERN_ERR, "Error allocating memory for " - "encrypted extent\n"); - goto out; - } - enc_extent_virt = kmap(enc_extent_page); - for (extent_offset = 0; - extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size); - extent_offset++) { - loff_t offset; - - rc = ecryptfs_encrypt_extent(enc_extent_page, crypt_stat, page, - extent_offset); - if (rc) { - printk(KERN_ERR "%s: Error encrypting extent; " - "rc = [%d]\n", __func__, rc); - goto out; - } - ecryptfs_lower_offset_for_extent( - &offset, ((((loff_t)page->index) - * (PAGE_CACHE_SIZE - / crypt_stat->extent_size)) - + extent_offset), crypt_stat); - rc = ecryptfs_write_lower(ecryptfs_inode, enc_extent_virt, - offset, crypt_stat->extent_size); - if (rc < 0) { - ecryptfs_printk(KERN_ERR, "Error attempting " - "to write lower page; rc = [%d]" - "\n", rc); - goto out; - } - } - rc = 0; -out: - if (enc_extent_page) { - kunmap(enc_extent_page); - __free_page(enc_extent_page); - } - return rc; -} - -static int ecryptfs_decrypt_extent(struct page *page, - struct ecryptfs_crypt_stat *crypt_stat, - struct page *enc_extent_page, - unsigned long extent_offset) -{ - loff_t extent_base; - char extent_iv[ECRYPTFS_MAX_IV_BYTES]; - int rc; - - extent_base = (((loff_t)page->index) - * (PAGE_CACHE_SIZE / crypt_stat->extent_size)); - rc = ecryptfs_derive_iv(extent_iv, crypt_stat, - (extent_base + extent_offset)); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error attempting to derive IV for " - "extent [0x%.16llx]; rc = [%d]\n", - (unsigned long long)(extent_base + extent_offset), rc); - goto out; - } - rc = ecryptfs_decrypt_page_offset(crypt_stat, page, - (extent_offset - * crypt_stat->extent_size), - enc_extent_page, 0, - crypt_stat->extent_size, extent_iv); - if (rc < 0) { - printk(KERN_ERR "%s: Error attempting to decrypt to page with " - "page->index = [%ld], extent_offset = [%ld]; " - "rc = [%d]\n", __func__, page->index, extent_offset, - rc); - goto out; - } - rc = 0; -out: - return rc; -} - -/** - * ecryptfs_decrypt_page - * @page: Page mapped from the eCryptfs inode for the file; data read - * and decrypted from the lower file will be written into this - * page - * - * Decrypt an eCryptfs page. This is done on a per-extent basis. Note - * that eCryptfs pages may straddle the lower pages -- for instance, - * if the file was created on a machine with an 8K page size - * (resulting in an 8K header), and then the file is copied onto a - * host with a 32K page size, then when reading page 0 of the eCryptfs - * file, 24K of page 0 of the lower file will be read and decrypted, - * and then 8K of page 1 of the lower file will be read and decrypted. - * - * Returns zero on success; negative on error - */ -int ecryptfs_decrypt_page(struct page *page) -{ - struct inode *ecryptfs_inode; - struct ecryptfs_crypt_stat *crypt_stat; - char *enc_extent_virt; - struct page *enc_extent_page = NULL; - unsigned long extent_offset; - int rc = 0; - - ecryptfs_inode = page->mapping->host; - crypt_stat = - &(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat); - BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)); - enc_extent_page = alloc_page(GFP_USER); - if (!enc_extent_page) { - rc = -ENOMEM; - ecryptfs_printk(KERN_ERR, "Error allocating memory for " - "encrypted extent\n"); - goto out; - } - enc_extent_virt = kmap(enc_extent_page); - for (extent_offset = 0; - extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size); - extent_offset++) { - loff_t offset; - - ecryptfs_lower_offset_for_extent( - &offset, ((page->index * (PAGE_CACHE_SIZE - / crypt_stat->extent_size)) - + extent_offset), crypt_stat); - rc = ecryptfs_read_lower(enc_extent_virt, offset, - crypt_stat->extent_size, - ecryptfs_inode); - if (rc < 0) { - ecryptfs_printk(KERN_ERR, "Error attempting " - "to read lower page; rc = [%d]" - "\n", rc); - goto out; - } - rc = ecryptfs_decrypt_extent(page, crypt_stat, enc_extent_page, - extent_offset); - if (rc) { - printk(KERN_ERR "%s: Error encrypting extent; " - "rc = [%d]\n", __func__, rc); - goto out; - } - } -out: - if (enc_extent_page) { - kunmap(enc_extent_page); - __free_page(enc_extent_page); - } - return rc; -} - -/** - * decrypt_scatterlist - * @crypt_stat: Cryptographic context - * @dest_sg: The destination scatterlist to decrypt into - * @src_sg: The source scatterlist to decrypt from - * @size: The number of bytes to decrypt - * @iv: The initialization vector to use for the decryption - * - * Returns the number of bytes decrypted; negative value on error - */ -static int decrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, - struct scatterlist *dest_sg, - struct scatterlist *src_sg, int size, - unsigned char *iv) -{ - struct blkcipher_desc desc = { - .tfm = crypt_stat->tfm, - .info = iv, - .flags = CRYPTO_TFM_REQ_MAY_SLEEP - }; - int rc = 0; - - /* Consider doing this once, when the file is opened */ - mutex_lock(&crypt_stat->cs_tfm_mutex); - rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key, - crypt_stat->key_size); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n", - rc); - mutex_unlock(&crypt_stat->cs_tfm_mutex); - rc = -EINVAL; - goto out; - } - ecryptfs_printk(KERN_DEBUG, "Decrypting [%d] bytes.\n", size); - rc = crypto_blkcipher_decrypt_iv(&desc, dest_sg, src_sg, size); - mutex_unlock(&crypt_stat->cs_tfm_mutex); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error decrypting; rc = [%d]\n", - rc); - goto out; - } - rc = size; -out: - return rc; -} - -/** - * ecryptfs_encrypt_page_offset - * @crypt_stat: The cryptographic context - * @dst_page: The page to encrypt into - * @dst_offset: The offset in the page to encrypt into - * @src_page: The page to encrypt from - * @src_offset: The offset in the page to encrypt from - * @size: The number of bytes to encrypt - * @iv: The initialization vector to use for the encryption - * - * Returns the number of bytes encrypted - */ -static int -ecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, - struct page *dst_page, int dst_offset, - struct page *src_page, int src_offset, int size, - unsigned char *iv) -{ - struct scatterlist src_sg, dst_sg; - - sg_init_table(&src_sg, 1); - sg_init_table(&dst_sg, 1); - - sg_set_page(&src_sg, src_page, size, src_offset); - sg_set_page(&dst_sg, dst_page, size, dst_offset); - return encrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv); -} - -/** - * ecryptfs_decrypt_page_offset - * @crypt_stat: The cryptographic context - * @dst_page: The page to decrypt into - * @dst_offset: The offset in the page to decrypt into - * @src_page: The page to decrypt from - * @src_offset: The offset in the page to decrypt from - * @size: The number of bytes to decrypt - * @iv: The initialization vector to use for the decryption - * - * Returns the number of bytes decrypted - */ -static int -ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, - struct page *dst_page, int dst_offset, - struct page *src_page, int src_offset, int size, - unsigned char *iv) -{ - struct scatterlist src_sg, dst_sg; - - sg_init_table(&src_sg, 1); - sg_set_page(&src_sg, src_page, size, src_offset); - - sg_init_table(&dst_sg, 1); - sg_set_page(&dst_sg, dst_page, size, dst_offset); - - return decrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv); -} - -#define ECRYPTFS_MAX_SCATTERLIST_LEN 4 - -/** - * ecryptfs_init_crypt_ctx - * @crypt_stat: Uninitialized crypt stats structure - * - * Initialize the crypto context. - * - * TODO: Performance: Keep a cache of initialized cipher contexts; - * only init if needed - */ -int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat) -{ - char *full_alg_name; - int rc = -EINVAL; - - if (!crypt_stat->cipher) { - ecryptfs_printk(KERN_ERR, "No cipher specified\n"); - goto out; - } - ecryptfs_printk(KERN_DEBUG, - "Initializing cipher [%s]; strlen = [%d]; " - "key_size_bits = [%zd]\n", - crypt_stat->cipher, (int)strlen(crypt_stat->cipher), - crypt_stat->key_size << 3); - if (crypt_stat->tfm) { - rc = 0; - goto out; - } - mutex_lock(&crypt_stat->cs_tfm_mutex); - rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name, - crypt_stat->cipher, "cbc"); - if (rc) - goto out_unlock; - crypt_stat->tfm = crypto_alloc_blkcipher(full_alg_name, 0, - CRYPTO_ALG_ASYNC); - kfree(full_alg_name); - if (IS_ERR(crypt_stat->tfm)) { - rc = PTR_ERR(crypt_stat->tfm); - crypt_stat->tfm = NULL; - ecryptfs_printk(KERN_ERR, "cryptfs: init_crypt_ctx(): " - "Error initializing cipher [%s]\n", - crypt_stat->cipher); - goto out_unlock; - } - crypto_blkcipher_set_flags(crypt_stat->tfm, CRYPTO_TFM_REQ_WEAK_KEY); - rc = 0; -out_unlock: - mutex_unlock(&crypt_stat->cs_tfm_mutex); -out: - return rc; -} - -static void set_extent_mask_and_shift(struct ecryptfs_crypt_stat *crypt_stat) -{ - int extent_size_tmp; - - crypt_stat->extent_mask = 0xFFFFFFFF; - crypt_stat->extent_shift = 0; - if (crypt_stat->extent_size == 0) - return; - extent_size_tmp = crypt_stat->extent_size; - while ((extent_size_tmp & 0x01) == 0) { - extent_size_tmp >>= 1; - crypt_stat->extent_mask <<= 1; - crypt_stat->extent_shift++; - } -} - -void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat) -{ - /* Default values; may be overwritten as we are parsing the - * packets. */ - crypt_stat->extent_size = ECRYPTFS_DEFAULT_EXTENT_SIZE; - set_extent_mask_and_shift(crypt_stat); - crypt_stat->iv_bytes = ECRYPTFS_DEFAULT_IV_BYTES; - if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) - crypt_stat->metadata_size = ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; - else { - if (PAGE_CACHE_SIZE <= ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) - crypt_stat->metadata_size = - ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; - else - crypt_stat->metadata_size = PAGE_CACHE_SIZE; - } -} - -/** - * ecryptfs_compute_root_iv - * @crypt_stats - * - * On error, sets the root IV to all 0's. - */ -int ecryptfs_compute_root_iv(struct ecryptfs_crypt_stat *crypt_stat) -{ - int rc = 0; - char dst[MD5_DIGEST_SIZE]; - - BUG_ON(crypt_stat->iv_bytes > MD5_DIGEST_SIZE); - BUG_ON(crypt_stat->iv_bytes <= 0); - if (!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) { - rc = -EINVAL; - ecryptfs_printk(KERN_WARNING, "Session key not valid; " - "cannot generate root IV\n"); - goto out; - } - rc = ecryptfs_calculate_md5(dst, crypt_stat, crypt_stat->key, - crypt_stat->key_size); - if (rc) { - ecryptfs_printk(KERN_WARNING, "Error attempting to compute " - "MD5 while generating root IV\n"); - goto out; - } - memcpy(crypt_stat->root_iv, dst, crypt_stat->iv_bytes); -out: - if (rc) { - memset(crypt_stat->root_iv, 0, crypt_stat->iv_bytes); - crypt_stat->flags |= ECRYPTFS_SECURITY_WARNING; - } - return rc; -} - -static void ecryptfs_generate_new_key(struct ecryptfs_crypt_stat *crypt_stat) -{ - get_random_bytes(crypt_stat->key, crypt_stat->key_size); - crypt_stat->flags |= ECRYPTFS_KEY_VALID; - ecryptfs_compute_root_iv(crypt_stat); - if (unlikely(ecryptfs_verbosity > 0)) { - ecryptfs_printk(KERN_DEBUG, "Generated new session key:\n"); - ecryptfs_dump_hex(crypt_stat->key, - crypt_stat->key_size); - } -} - -/** - * ecryptfs_copy_mount_wide_flags_to_inode_flags - * @crypt_stat: The inode's cryptographic context - * @mount_crypt_stat: The mount point's cryptographic context - * - * This function propagates the mount-wide flags to individual inode - * flags. - */ -static void ecryptfs_copy_mount_wide_flags_to_inode_flags( - struct ecryptfs_crypt_stat *crypt_stat, - struct ecryptfs_mount_crypt_stat *mount_crypt_stat) -{ - if (mount_crypt_stat->flags & ECRYPTFS_XATTR_METADATA_ENABLED) - crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; - if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) - crypt_stat->flags |= ECRYPTFS_VIEW_AS_ENCRYPTED; - if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) { - crypt_stat->flags |= ECRYPTFS_ENCRYPT_FILENAMES; - if (mount_crypt_stat->flags - & ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK) - crypt_stat->flags |= ECRYPTFS_ENCFN_USE_MOUNT_FNEK; - else if (mount_crypt_stat->flags - & ECRYPTFS_GLOBAL_ENCFN_USE_FEK) - crypt_stat->flags |= ECRYPTFS_ENCFN_USE_FEK; - } -} - -static int ecryptfs_copy_mount_wide_sigs_to_inode_sigs( - struct ecryptfs_crypt_stat *crypt_stat, - struct ecryptfs_mount_crypt_stat *mount_crypt_stat) -{ - struct ecryptfs_global_auth_tok *global_auth_tok; - int rc = 0; - - mutex_lock(&crypt_stat->keysig_list_mutex); - mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex); - - list_for_each_entry(global_auth_tok, - &mount_crypt_stat->global_auth_tok_list, - mount_crypt_stat_list) { - if (global_auth_tok->flags & ECRYPTFS_AUTH_TOK_FNEK) - continue; - rc = ecryptfs_add_keysig(crypt_stat, global_auth_tok->sig); - if (rc) { - printk(KERN_ERR "Error adding keysig; rc = [%d]\n", rc); - goto out; - } - } - -out: - mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex); - mutex_unlock(&crypt_stat->keysig_list_mutex); - return rc; -} - -/** - * ecryptfs_set_default_crypt_stat_vals - * @crypt_stat: The inode's cryptographic context - * @mount_crypt_stat: The mount point's cryptographic context - * - * Default values in the event that policy does not override them. - */ -static void ecryptfs_set_default_crypt_stat_vals( - struct ecryptfs_crypt_stat *crypt_stat, - struct ecryptfs_mount_crypt_stat *mount_crypt_stat) -{ - ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat, - mount_crypt_stat); - ecryptfs_set_default_sizes(crypt_stat); - strcpy(crypt_stat->cipher, ECRYPTFS_DEFAULT_CIPHER); - crypt_stat->key_size = ECRYPTFS_DEFAULT_KEY_BYTES; - crypt_stat->flags &= ~(ECRYPTFS_KEY_VALID); - crypt_stat->file_version = ECRYPTFS_FILE_VERSION; - crypt_stat->mount_crypt_stat = mount_crypt_stat; -} - -/** - * ecryptfs_new_file_context - * @ecryptfs_inode: The eCryptfs inode - * - * If the crypto context for the file has not yet been established, - * this is where we do that. Establishing a new crypto context - * involves the following decisions: - * - What cipher to use? - * - What set of authentication tokens to use? - * Here we just worry about getting enough information into the - * authentication tokens so that we know that they are available. - * We associate the available authentication tokens with the new file - * via the set of signatures in the crypt_stat struct. Later, when - * the headers are actually written out, we may again defer to - * userspace to perform the encryption of the session key; for the - * foreseeable future, this will be the case with public key packets. - * - * Returns zero on success; non-zero otherwise - */ -int ecryptfs_new_file_context(struct inode *ecryptfs_inode) -{ - struct ecryptfs_crypt_stat *crypt_stat = - &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; - struct ecryptfs_mount_crypt_stat *mount_crypt_stat = - &ecryptfs_superblock_to_private( - ecryptfs_inode->i_sb)->mount_crypt_stat; - int cipher_name_len; - int rc = 0; - - ecryptfs_set_default_crypt_stat_vals(crypt_stat, mount_crypt_stat); - crypt_stat->flags |= (ECRYPTFS_ENCRYPTED | ECRYPTFS_KEY_VALID); - ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat, - mount_crypt_stat); - rc = ecryptfs_copy_mount_wide_sigs_to_inode_sigs(crypt_stat, - mount_crypt_stat); - if (rc) { - printk(KERN_ERR "Error attempting to copy mount-wide key sigs " - "to the inode key sigs; rc = [%d]\n", rc); - goto out; - } - cipher_name_len = - strlen(mount_crypt_stat->global_default_cipher_name); - memcpy(crypt_stat->cipher, - mount_crypt_stat->global_default_cipher_name, - cipher_name_len); - crypt_stat->cipher[cipher_name_len] = '\0'; - crypt_stat->key_size = - mount_crypt_stat->global_default_cipher_key_size; - ecryptfs_generate_new_key(crypt_stat); - rc = ecryptfs_init_crypt_ctx(crypt_stat); - if (rc) - ecryptfs_printk(KERN_ERR, "Error initializing cryptographic " - "context for cipher [%s]: rc = [%d]\n", - crypt_stat->cipher, rc); -out: - return rc; -} - -/** - * ecryptfs_validate_marker - check for the ecryptfs marker - * @data: The data block in which to check - * - * Returns zero if marker found; -EINVAL if not found - */ -static int ecryptfs_validate_marker(char *data) -{ - u32 m_1, m_2; - - m_1 = get_unaligned_be32(data); - m_2 = get_unaligned_be32(data + 4); - if ((m_1 ^ MAGIC_ECRYPTFS_MARKER) == m_2) - return 0; - ecryptfs_printk(KERN_DEBUG, "m_1 = [0x%.8x]; m_2 = [0x%.8x]; " - "MAGIC_ECRYPTFS_MARKER = [0x%.8x]\n", m_1, m_2, - MAGIC_ECRYPTFS_MARKER); - ecryptfs_printk(KERN_DEBUG, "(m_1 ^ MAGIC_ECRYPTFS_MARKER) = " - "[0x%.8x]\n", (m_1 ^ MAGIC_ECRYPTFS_MARKER)); - return -EINVAL; -} - -struct ecryptfs_flag_map_elem { - u32 file_flag; - u32 local_flag; -}; - -/* Add support for additional flags by adding elements here. */ -static struct ecryptfs_flag_map_elem ecryptfs_flag_map[] = { - {0x00000001, ECRYPTFS_ENABLE_HMAC}, - {0x00000002, ECRYPTFS_ENCRYPTED}, - {0x00000004, ECRYPTFS_METADATA_IN_XATTR}, - {0x00000008, ECRYPTFS_ENCRYPT_FILENAMES} -}; - -/** - * ecryptfs_process_flags - * @crypt_stat: The cryptographic context - * @page_virt: Source data to be parsed - * @bytes_read: Updated with the number of bytes read - * - * Returns zero on success; non-zero if the flag set is invalid - */ -static int ecryptfs_process_flags(struct ecryptfs_crypt_stat *crypt_stat, - char *page_virt, int *bytes_read) -{ - int rc = 0; - int i; - u32 flags; - - flags = get_unaligned_be32(page_virt); - for (i = 0; i < ((sizeof(ecryptfs_flag_map) - / sizeof(struct ecryptfs_flag_map_elem))); i++) - if (flags & ecryptfs_flag_map[i].file_flag) { - crypt_stat->flags |= ecryptfs_flag_map[i].local_flag; - } else - crypt_stat->flags &= ~(ecryptfs_flag_map[i].local_flag); - /* Version is in top 8 bits of the 32-bit flag vector */ - crypt_stat->file_version = ((flags >> 24) & 0xFF); - (*bytes_read) = 4; - return rc; -} - -/** - * write_ecryptfs_marker - * @page_virt: The pointer to in a page to begin writing the marker - * @written: Number of bytes written - * - * Marker = 0x3c81b7f5 - */ -static void write_ecryptfs_marker(char *page_virt, size_t *written) -{ - u32 m_1, m_2; - - get_random_bytes(&m_1, (MAGIC_ECRYPTFS_MARKER_SIZE_BYTES / 2)); - m_2 = (m_1 ^ MAGIC_ECRYPTFS_MARKER); - put_unaligned_be32(m_1, page_virt); - page_virt += (MAGIC_ECRYPTFS_MARKER_SIZE_BYTES / 2); - put_unaligned_be32(m_2, page_virt); - (*written) = MAGIC_ECRYPTFS_MARKER_SIZE_BYTES; -} - -void ecryptfs_write_crypt_stat_flags(char *page_virt, - struct ecryptfs_crypt_stat *crypt_stat, - size_t *written) -{ - u32 flags = 0; - int i; - - for (i = 0; i < ((sizeof(ecryptfs_flag_map) - / sizeof(struct ecryptfs_flag_map_elem))); i++) - if (crypt_stat->flags & ecryptfs_flag_map[i].local_flag) - flags |= ecryptfs_flag_map[i].file_flag; - /* Version is in top 8 bits of the 32-bit flag vector */ - flags |= ((((u8)crypt_stat->file_version) << 24) & 0xFF000000); - put_unaligned_be32(flags, page_virt); - (*written) = 4; -} - -struct ecryptfs_cipher_code_str_map_elem { - char cipher_str[16]; - u8 cipher_code; -}; - -/* Add support for additional ciphers by adding elements here. The - * cipher_code is whatever OpenPGP applicatoins use to identify the - * ciphers. List in order of probability. */ -static struct ecryptfs_cipher_code_str_map_elem -ecryptfs_cipher_code_str_map[] = { - {"aes",RFC2440_CIPHER_AES_128 }, - {"blowfish", RFC2440_CIPHER_BLOWFISH}, - {"des3_ede", RFC2440_CIPHER_DES3_EDE}, - {"cast5", RFC2440_CIPHER_CAST_5}, - {"twofish", RFC2440_CIPHER_TWOFISH}, - {"cast6", RFC2440_CIPHER_CAST_6}, - {"aes", RFC2440_CIPHER_AES_192}, - {"aes", RFC2440_CIPHER_AES_256} -}; - -/** - * ecryptfs_code_for_cipher_string - * @cipher_name: The string alias for the cipher - * @key_bytes: Length of key in bytes; used for AES code selection - * - * Returns zero on no match, or the cipher code on match - */ -u8 ecryptfs_code_for_cipher_string(char *cipher_name, size_t key_bytes) -{ - int i; - u8 code = 0; - struct ecryptfs_cipher_code_str_map_elem *map = - ecryptfs_cipher_code_str_map; - - if (strcmp(cipher_name, "aes") == 0) { - switch (key_bytes) { - case 16: - code = RFC2440_CIPHER_AES_128; - break; - case 24: - code = RFC2440_CIPHER_AES_192; - break; - case 32: - code = RFC2440_CIPHER_AES_256; - } - } else { - for (i = 0; i < ARRAY_SIZE(ecryptfs_cipher_code_str_map); i++) - if (strcmp(cipher_name, map[i].cipher_str) == 0) { - code = map[i].cipher_code; - break; - } - } - return code; -} - -/** - * ecryptfs_cipher_code_to_string - * @str: Destination to write out the cipher name - * @cipher_code: The code to convert to cipher name string - * - * Returns zero on success - */ -int ecryptfs_cipher_code_to_string(char *str, u8 cipher_code) -{ - int rc = 0; - int i; - - str[0] = '\0'; - for (i = 0; i < ARRAY_SIZE(ecryptfs_cipher_code_str_map); i++) - if (cipher_code == ecryptfs_cipher_code_str_map[i].cipher_code) - strcpy(str, ecryptfs_cipher_code_str_map[i].cipher_str); - if (str[0] == '\0') { - ecryptfs_printk(KERN_WARNING, "Cipher code not recognized: " - "[%d]\n", cipher_code); - rc = -EINVAL; - } - return rc; -} - -int ecryptfs_read_and_validate_header_region(struct inode *inode) -{ - u8 file_size[ECRYPTFS_SIZE_AND_MARKER_BYTES]; - u8 *marker = file_size + ECRYPTFS_FILE_SIZE_BYTES; - int rc; - - rc = ecryptfs_read_lower(file_size, 0, ECRYPTFS_SIZE_AND_MARKER_BYTES, - inode); - if (rc < ECRYPTFS_SIZE_AND_MARKER_BYTES) - return rc >= 0 ? -EINVAL : rc; - rc = ecryptfs_validate_marker(marker); - if (!rc) - ecryptfs_i_size_init(file_size, inode); - return rc; -} - -void -ecryptfs_write_header_metadata(char *virt, - struct ecryptfs_crypt_stat *crypt_stat, - size_t *written) -{ - u32 header_extent_size; - u16 num_header_extents_at_front; - - header_extent_size = (u32)crypt_stat->extent_size; - num_header_extents_at_front = - (u16)(crypt_stat->metadata_size / crypt_stat->extent_size); - put_unaligned_be32(header_extent_size, virt); - virt += 4; - put_unaligned_be16(num_header_extents_at_front, virt); - (*written) = 6; -} - -struct kmem_cache *ecryptfs_header_cache; - -/** - * ecryptfs_write_headers_virt - * @page_virt: The virtual address to write the headers to - * @max: The size of memory allocated at page_virt - * @size: Set to the number of bytes written by this function - * @crypt_stat: The cryptographic context - * @ecryptfs_dentry: The eCryptfs dentry - * - * Format version: 1 - * - * Header Extent: - * Octets 0-7: Unencrypted file size (big-endian) - * Octets 8-15: eCryptfs special marker - * Octets 16-19: Flags - * Octet 16: File format version number (between 0 and 255) - * Octets 17-18: Reserved - * Octet 19: Bit 1 (lsb): Reserved - * Bit 2: Encrypted? - * Bits 3-8: Reserved - * Octets 20-23: Header extent size (big-endian) - * Octets 24-25: Number of header extents at front of file - * (big-endian) - * Octet 26: Begin RFC 2440 authentication token packet set - * Data Extent 0: - * Lower data (CBC encrypted) - * Data Extent 1: - * Lower data (CBC encrypted) - * ... - * - * Returns zero on success - */ -static int ecryptfs_write_headers_virt(char *page_virt, size_t max, - size_t *size, - struct ecryptfs_crypt_stat *crypt_stat, - struct dentry *ecryptfs_dentry) -{ - int rc; - size_t written; - size_t offset; - - offset = ECRYPTFS_FILE_SIZE_BYTES; - write_ecryptfs_marker((page_virt + offset), &written); - offset += written; - ecryptfs_write_crypt_stat_flags((page_virt + offset), crypt_stat, - &written); - offset += written; - ecryptfs_write_header_metadata((page_virt + offset), crypt_stat, - &written); - offset += written; - rc = ecryptfs_generate_key_packet_set((page_virt + offset), crypt_stat, - ecryptfs_dentry, &written, - max - offset); - if (rc) - ecryptfs_printk(KERN_WARNING, "Error generating key packet " - "set; rc = [%d]\n", rc); - if (size) { - offset += written; - *size = offset; - } - return rc; -} - -static int -ecryptfs_write_metadata_to_contents(struct inode *ecryptfs_inode, - char *virt, size_t virt_len) -{ - int rc; - - rc = ecryptfs_write_lower(ecryptfs_inode, virt, - 0, virt_len); - if (rc < 0) - printk(KERN_ERR "%s: Error attempting to write header " - "information to lower file; rc = [%d]\n", __func__, rc); - else - rc = 0; - return rc; -} - -static int -ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry, - char *page_virt, size_t size) -{ - int rc; - - rc = ecryptfs_setxattr(ecryptfs_dentry, ECRYPTFS_XATTR_NAME, page_virt, - size, 0); - return rc; -} - -static unsigned long ecryptfs_get_zeroed_pages(gfp_t gfp_mask, - unsigned int order) -{ - struct page *page; - - page = alloc_pages(gfp_mask | __GFP_ZERO, order); - if (page) - return (unsigned long) page_address(page); - return 0; -} - -/** - * ecryptfs_write_metadata - * @ecryptfs_dentry: The eCryptfs dentry, which should be negative - * @ecryptfs_inode: The newly created eCryptfs inode - * - * Write the file headers out. This will likely involve a userspace - * callout, in which the session key is encrypted with one or more - * public keys and/or the passphrase necessary to do the encryption is - * retrieved via a prompt. Exactly what happens at this point should - * be policy-dependent. - * - * Returns zero on success; non-zero on error - */ -int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry, - struct inode *ecryptfs_inode) -{ - struct ecryptfs_crypt_stat *crypt_stat = - &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; - unsigned int order; - char *virt; - size_t virt_len; - size_t size = 0; - int rc = 0; - - if (likely(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { - if (!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) { - printk(KERN_ERR "Key is invalid; bailing out\n"); - rc = -EINVAL; - goto out; - } - } else { - printk(KERN_WARNING "%s: Encrypted flag not set\n", - __func__); - rc = -EINVAL; - goto out; - } - virt_len = crypt_stat->metadata_size; - order = get_order(virt_len); - /* Released in this function */ - virt = (char *)ecryptfs_get_zeroed_pages(GFP_KERNEL, order); - if (!virt) { - printk(KERN_ERR "%s: Out of memory\n", __func__); - rc = -ENOMEM; - goto out; - } - /* Zeroed page ensures the in-header unencrypted i_size is set to 0 */ - rc = ecryptfs_write_headers_virt(virt, virt_len, &size, crypt_stat, - ecryptfs_dentry); - if (unlikely(rc)) { - printk(KERN_ERR "%s: Error whilst writing headers; rc = [%d]\n", - __func__, rc); - goto out_free; - } - if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) - rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry, virt, - size); - else - rc = ecryptfs_write_metadata_to_contents(ecryptfs_inode, virt, - virt_len); - if (rc) { - printk(KERN_ERR "%s: Error writing metadata out to lower file; " - "rc = [%d]\n", __func__, rc); - goto out_free; - } -out_free: - free_pages((unsigned long)virt, order); -out: - return rc; -} - -#define ECRYPTFS_DONT_VALIDATE_HEADER_SIZE 0 -#define ECRYPTFS_VALIDATE_HEADER_SIZE 1 -static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat, - char *virt, int *bytes_read, - int validate_header_size) -{ - int rc = 0; - u32 header_extent_size; - u16 num_header_extents_at_front; - - header_extent_size = get_unaligned_be32(virt); - virt += sizeof(__be32); - num_header_extents_at_front = get_unaligned_be16(virt); - crypt_stat->metadata_size = (((size_t)num_header_extents_at_front - * (size_t)header_extent_size)); - (*bytes_read) = (sizeof(__be32) + sizeof(__be16)); - if ((validate_header_size == ECRYPTFS_VALIDATE_HEADER_SIZE) - && (crypt_stat->metadata_size - < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)) { - rc = -EINVAL; - printk(KERN_WARNING "Invalid header size: [%zd]\n", - crypt_stat->metadata_size); - } - return rc; -} - -/** - * set_default_header_data - * @crypt_stat: The cryptographic context - * - * For version 0 file format; this function is only for backwards - * compatibility for files created with the prior versions of - * eCryptfs. - */ -static void set_default_header_data(struct ecryptfs_crypt_stat *crypt_stat) -{ - crypt_stat->metadata_size = ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; -} - -void ecryptfs_i_size_init(const char *page_virt, struct inode *inode) -{ - struct ecryptfs_mount_crypt_stat *mount_crypt_stat; - struct ecryptfs_crypt_stat *crypt_stat; - u64 file_size; - - crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; - mount_crypt_stat = - &ecryptfs_superblock_to_private(inode->i_sb)->mount_crypt_stat; - if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { - file_size = i_size_read(ecryptfs_inode_to_lower(inode)); - if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) - file_size += crypt_stat->metadata_size; - } else - file_size = get_unaligned_be64(page_virt); - i_size_write(inode, (loff_t)file_size); - crypt_stat->flags |= ECRYPTFS_I_SIZE_INITIALIZED; -} - -/** - * ecryptfs_read_headers_virt - * @page_virt: The virtual address into which to read the headers - * @crypt_stat: The cryptographic context - * @ecryptfs_dentry: The eCryptfs dentry - * @validate_header_size: Whether to validate the header size while reading - * - * Read/parse the header data. The header format is detailed in the - * comment block for the ecryptfs_write_headers_virt() function. - * - * Returns zero on success - */ -static int ecryptfs_read_headers_virt(char *page_virt, - struct ecryptfs_crypt_stat *crypt_stat, - struct dentry *ecryptfs_dentry, - int validate_header_size) -{ - int rc = 0; - int offset; - int bytes_read; - - ecryptfs_set_default_sizes(crypt_stat); - crypt_stat->mount_crypt_stat = &ecryptfs_superblock_to_private( - ecryptfs_dentry->d_sb)->mount_crypt_stat; - offset = ECRYPTFS_FILE_SIZE_BYTES; - rc = ecryptfs_validate_marker(page_virt + offset); - if (rc) - goto out; - if (!(crypt_stat->flags & ECRYPTFS_I_SIZE_INITIALIZED)) - ecryptfs_i_size_init(page_virt, ecryptfs_dentry->d_inode); - offset += MAGIC_ECRYPTFS_MARKER_SIZE_BYTES; - rc = ecryptfs_process_flags(crypt_stat, (page_virt + offset), - &bytes_read); - if (rc) { - ecryptfs_printk(KERN_WARNING, "Error processing flags\n"); - goto out; - } - if (crypt_stat->file_version > ECRYPTFS_SUPPORTED_FILE_VERSION) { - ecryptfs_printk(KERN_WARNING, "File version is [%d]; only " - "file version [%d] is supported by this " - "version of eCryptfs\n", - crypt_stat->file_version, - ECRYPTFS_SUPPORTED_FILE_VERSION); - rc = -EINVAL; - goto out; - } - offset += bytes_read; - if (crypt_stat->file_version >= 1) { - rc = parse_header_metadata(crypt_stat, (page_virt + offset), - &bytes_read, validate_header_size); - if (rc) { - ecryptfs_printk(KERN_WARNING, "Error reading header " - "metadata; rc = [%d]\n", rc); - } - offset += bytes_read; - } else - set_default_header_data(crypt_stat); - rc = ecryptfs_parse_packet_set(crypt_stat, (page_virt + offset), - ecryptfs_dentry); -out: - return rc; -} - -/** - * ecryptfs_read_xattr_region - * @page_virt: The vitual address into which to read the xattr data - * @ecryptfs_inode: The eCryptfs inode - * - * Attempts to read the crypto metadata from the extended attribute - * region of the lower file. - * - * Returns zero on success; non-zero on error - */ -int ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode) -{ - struct dentry *lower_dentry = - ecryptfs_inode_to_private(ecryptfs_inode)->lower_file->f_dentry; - ssize_t size; - int rc = 0; - - size = ecryptfs_getxattr_lower(lower_dentry, ECRYPTFS_XATTR_NAME, - page_virt, ECRYPTFS_DEFAULT_EXTENT_SIZE); - if (size < 0) { - if (unlikely(ecryptfs_verbosity > 0)) - printk(KERN_INFO "Error attempting to read the [%s] " - "xattr from the lower file; return value = " - "[%zd]\n", ECRYPTFS_XATTR_NAME, size); - rc = -EINVAL; - goto out; - } -out: - return rc; -} - -int ecryptfs_read_and_validate_xattr_region(struct dentry *dentry, - struct inode *inode) -{ - u8 file_size[ECRYPTFS_SIZE_AND_MARKER_BYTES]; - u8 *marker = file_size + ECRYPTFS_FILE_SIZE_BYTES; - int rc; - - rc = ecryptfs_getxattr_lower(ecryptfs_dentry_to_lower(dentry), - ECRYPTFS_XATTR_NAME, file_size, - ECRYPTFS_SIZE_AND_MARKER_BYTES); - if (rc < ECRYPTFS_SIZE_AND_MARKER_BYTES) - return rc >= 0 ? -EINVAL : rc; - rc = ecryptfs_validate_marker(marker); - if (!rc) - ecryptfs_i_size_init(file_size, inode); - return rc; -} - -/** - * ecryptfs_read_metadata - * - * Common entry point for reading file metadata. From here, we could - * retrieve the header information from the header region of the file, - * the xattr region of the file, or some other repostory that is - * stored separately from the file itself. The current implementation - * supports retrieving the metadata information from the file contents - * and from the xattr region. - * - * Returns zero if valid headers found and parsed; non-zero otherwise - */ -int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry) -{ - int rc; - char *page_virt; - struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode; - struct ecryptfs_crypt_stat *crypt_stat = - &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; - struct ecryptfs_mount_crypt_stat *mount_crypt_stat = - &ecryptfs_superblock_to_private( - ecryptfs_dentry->d_sb)->mount_crypt_stat; - - ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat, - mount_crypt_stat); - /* Read the first page from the underlying file */ - page_virt = kmem_cache_alloc(ecryptfs_header_cache, GFP_USER); - if (!page_virt) { - rc = -ENOMEM; - printk(KERN_ERR "%s: Unable to allocate page_virt\n", - __func__); - goto out; - } - rc = ecryptfs_read_lower(page_virt, 0, crypt_stat->extent_size, - ecryptfs_inode); - if (rc >= 0) - rc = ecryptfs_read_headers_virt(page_virt, crypt_stat, - ecryptfs_dentry, - ECRYPTFS_VALIDATE_HEADER_SIZE); - if (rc) { - /* metadata is not in the file header, so try xattrs */ - memset(page_virt, 0, PAGE_CACHE_SIZE); - rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_inode); - if (rc) { - printk(KERN_DEBUG "Valid eCryptfs headers not found in " - "file header region or xattr region, inode %lu\n", - ecryptfs_inode->i_ino); - rc = -EINVAL; - goto out; - } - rc = ecryptfs_read_headers_virt(page_virt, crypt_stat, - ecryptfs_dentry, - ECRYPTFS_DONT_VALIDATE_HEADER_SIZE); - if (rc) { - printk(KERN_DEBUG "Valid eCryptfs headers not found in " - "file xattr region either, inode %lu\n", - ecryptfs_inode->i_ino); - rc = -EINVAL; - } - if (crypt_stat->mount_crypt_stat->flags - & ECRYPTFS_XATTR_METADATA_ENABLED) { - crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; - } else { - printk(KERN_WARNING "Attempt to access file with " - "crypto metadata only in the extended attribute " - "region, but eCryptfs was mounted without " - "xattr support enabled. eCryptfs will not treat " - "this like an encrypted file, inode %lu\n", - ecryptfs_inode->i_ino); - rc = -EINVAL; - } - } -out: - if (page_virt) { - memset(page_virt, 0, PAGE_CACHE_SIZE); - kmem_cache_free(ecryptfs_header_cache, page_virt); - } - return rc; -} - -/** - * ecryptfs_encrypt_filename - encrypt filename - * - * CBC-encrypts the filename. We do not want to encrypt the same - * filename with the same key and IV, which may happen with hard - * links, so we prepend random bits to each filename. - * - * Returns zero on success; non-zero otherwise - */ -static int -ecryptfs_encrypt_filename(struct ecryptfs_filename *filename, - struct ecryptfs_crypt_stat *crypt_stat, - struct ecryptfs_mount_crypt_stat *mount_crypt_stat) -{ - int rc = 0; - - filename->encrypted_filename = NULL; - filename->encrypted_filename_size = 0; - if ((crypt_stat && (crypt_stat->flags & ECRYPTFS_ENCFN_USE_MOUNT_FNEK)) - || (mount_crypt_stat && (mount_crypt_stat->flags - & ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK))) { - size_t packet_size; - size_t remaining_bytes; - - rc = ecryptfs_write_tag_70_packet( - NULL, NULL, - &filename->encrypted_filename_size, - mount_crypt_stat, NULL, - filename->filename_size); - if (rc) { - printk(KERN_ERR "%s: Error attempting to get packet " - "size for tag 72; rc = [%d]\n", __func__, - rc); - filename->encrypted_filename_size = 0; - goto out; - } - filename->encrypted_filename = - kmalloc(filename->encrypted_filename_size, GFP_KERNEL); - if (!filename->encrypted_filename) { - printk(KERN_ERR "%s: Out of memory whilst attempting " - "to kmalloc [%zd] bytes\n", __func__, - filename->encrypted_filename_size); - rc = -ENOMEM; - goto out; - } - remaining_bytes = filename->encrypted_filename_size; - rc = ecryptfs_write_tag_70_packet(filename->encrypted_filename, - &remaining_bytes, - &packet_size, - mount_crypt_stat, - filename->filename, - filename->filename_size); - if (rc) { - printk(KERN_ERR "%s: Error attempting to generate " - "tag 70 packet; rc = [%d]\n", __func__, - rc); - kfree(filename->encrypted_filename); - filename->encrypted_filename = NULL; - filename->encrypted_filename_size = 0; - goto out; - } - filename->encrypted_filename_size = packet_size; - } else { - printk(KERN_ERR "%s: No support for requested filename " - "encryption method in this release\n", __func__); - rc = -EOPNOTSUPP; - goto out; - } -out: - return rc; -} - -static int ecryptfs_copy_filename(char **copied_name, size_t *copied_name_size, - const char *name, size_t name_size) -{ - int rc = 0; - - (*copied_name) = kmalloc((name_size + 1), GFP_KERNEL); - if (!(*copied_name)) { - rc = -ENOMEM; - goto out; - } - memcpy((void *)(*copied_name), (void *)name, name_size); - (*copied_name)[(name_size)] = '\0'; /* Only for convenience - * in printing out the - * string in debug - * messages */ - (*copied_name_size) = name_size; -out: - return rc; -} - -/** - * ecryptfs_process_key_cipher - Perform key cipher initialization. - * @key_tfm: Crypto context for key material, set by this function - * @cipher_name: Name of the cipher - * @key_size: Size of the key in bytes - * - * Returns zero on success. Any crypto_tfm structs allocated here - * should be released by other functions, such as on a superblock put - * event, regardless of whether this function succeeds for fails. - */ -static int -ecryptfs_process_key_cipher(struct crypto_blkcipher **key_tfm, - char *cipher_name, size_t *key_size) -{ - char dummy_key[ECRYPTFS_MAX_KEY_BYTES]; - char *full_alg_name = NULL; - int rc; - - *key_tfm = NULL; - if (*key_size > ECRYPTFS_MAX_KEY_BYTES) { - rc = -EINVAL; - printk(KERN_ERR "Requested key size is [%zd] bytes; maximum " - "allowable is [%d]\n", *key_size, ECRYPTFS_MAX_KEY_BYTES); - goto out; - } - rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name, cipher_name, - "ecb"); - if (rc) - goto out; - *key_tfm = crypto_alloc_blkcipher(full_alg_name, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(*key_tfm)) { - rc = PTR_ERR(*key_tfm); - printk(KERN_ERR "Unable to allocate crypto cipher with name " - "[%s]; rc = [%d]\n", full_alg_name, rc); - goto out; - } - crypto_blkcipher_set_flags(*key_tfm, CRYPTO_TFM_REQ_WEAK_KEY); - if (*key_size == 0) { - struct blkcipher_alg *alg = crypto_blkcipher_alg(*key_tfm); - - *key_size = alg->max_keysize; - } - get_random_bytes(dummy_key, *key_size); - rc = crypto_blkcipher_setkey(*key_tfm, dummy_key, *key_size); - if (rc) { - printk(KERN_ERR "Error attempting to set key of size [%zd] for " - "cipher [%s]; rc = [%d]\n", *key_size, full_alg_name, - rc); - rc = -EINVAL; - goto out; - } -out: - kfree(full_alg_name); - return rc; -} - -struct kmem_cache *ecryptfs_key_tfm_cache; -static struct list_head key_tfm_list; -struct mutex key_tfm_list_mutex; - -int __init ecryptfs_init_crypto(void) -{ - mutex_init(&key_tfm_list_mutex); - INIT_LIST_HEAD(&key_tfm_list); - return 0; -} - -/** - * ecryptfs_destroy_crypto - free all cached key_tfms on key_tfm_list - * - * Called only at module unload time - */ -int ecryptfs_destroy_crypto(void) -{ - struct ecryptfs_key_tfm *key_tfm, *key_tfm_tmp; - - mutex_lock(&key_tfm_list_mutex); - list_for_each_entry_safe(key_tfm, key_tfm_tmp, &key_tfm_list, - key_tfm_list) { - list_del(&key_tfm->key_tfm_list); - if (key_tfm->key_tfm) - crypto_free_blkcipher(key_tfm->key_tfm); - kmem_cache_free(ecryptfs_key_tfm_cache, key_tfm); - } - mutex_unlock(&key_tfm_list_mutex); - return 0; -} - -int -ecryptfs_add_new_key_tfm(struct ecryptfs_key_tfm **key_tfm, char *cipher_name, - size_t key_size) -{ - struct ecryptfs_key_tfm *tmp_tfm; - int rc = 0; - - BUG_ON(!mutex_is_locked(&key_tfm_list_mutex)); - - tmp_tfm = kmem_cache_alloc(ecryptfs_key_tfm_cache, GFP_KERNEL); - if (key_tfm != NULL) - (*key_tfm) = tmp_tfm; - if (!tmp_tfm) { - rc = -ENOMEM; - printk(KERN_ERR "Error attempting to allocate from " - "ecryptfs_key_tfm_cache\n"); - goto out; - } - 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, - &tmp_tfm->key_size); - if (rc) { - printk(KERN_ERR "Error attempting to initialize key TFM " - "cipher with name = [%s]; rc = [%d]\n", - tmp_tfm->cipher_name, rc); - kmem_cache_free(ecryptfs_key_tfm_cache, tmp_tfm); - if (key_tfm != NULL) - (*key_tfm) = NULL; - goto out; - } - list_add(&tmp_tfm->key_tfm_list, &key_tfm_list); -out: - return rc; -} - -/** - * ecryptfs_tfm_exists - Search for existing tfm for cipher_name. - * @cipher_name: the name of the cipher to search for - * @key_tfm: set to corresponding tfm if found - * - * Searches for cached key_tfm matching @cipher_name - * Must be called with &key_tfm_list_mutex held - * Returns 1 if found, with @key_tfm set - * Returns 0 if not found, with @key_tfm set to NULL - */ -int ecryptfs_tfm_exists(char *cipher_name, struct ecryptfs_key_tfm **key_tfm) -{ - struct ecryptfs_key_tfm *tmp_key_tfm; - - BUG_ON(!mutex_is_locked(&key_tfm_list_mutex)); - - list_for_each_entry(tmp_key_tfm, &key_tfm_list, key_tfm_list) { - if (strcmp(tmp_key_tfm->cipher_name, cipher_name) == 0) { - if (key_tfm) - (*key_tfm) = tmp_key_tfm; - return 1; - } - } - if (key_tfm) - (*key_tfm) = NULL; - return 0; -} - -/** - * ecryptfs_get_tfm_and_mutex_for_cipher_name - * - * @tfm: set to cached tfm found, or new tfm created - * @tfm_mutex: set to mutex for cached tfm found, or new tfm created - * @cipher_name: the name of the cipher to search for and/or add - * - * Sets pointers to @tfm & @tfm_mutex matching @cipher_name. - * Searches for cached item first, and creates new if not found. - * Returns 0 on success, non-zero if adding new cipher failed - */ -int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_blkcipher **tfm, - struct mutex **tfm_mutex, - char *cipher_name) -{ - struct ecryptfs_key_tfm *key_tfm; - int rc = 0; - - (*tfm) = NULL; - (*tfm_mutex) = NULL; - - mutex_lock(&key_tfm_list_mutex); - if (!ecryptfs_tfm_exists(cipher_name, &key_tfm)) { - rc = ecryptfs_add_new_key_tfm(&key_tfm, cipher_name, 0); - if (rc) { - printk(KERN_ERR "Error adding new key_tfm to list; " - "rc = [%d]\n", rc); - goto out; - } - } - (*tfm) = key_tfm->key_tfm; - (*tfm_mutex) = &key_tfm->key_tfm_mutex; -out: - mutex_unlock(&key_tfm_list_mutex); - return rc; -} - -/* 64 characters forming a 6-bit target field */ -static unsigned char *portable_filename_chars = ("-.0123456789ABCD" - "EFGHIJKLMNOPQRST" - "UVWXYZabcdefghij" - "klmnopqrstuvwxyz"); - -/* We could either offset on every reverse map or just pad some 0x00's - * at the front here */ -static const unsigned char filename_rev_map[256] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 15 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 23 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 31 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 39 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, /* 47 */ - 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, /* 55 */ - 0x0A, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 63 */ - 0x00, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, /* 71 */ - 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, /* 79 */ - 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, /* 87 */ - 0x23, 0x24, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, /* 95 */ - 0x00, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, /* 103 */ - 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, /* 111 */ - 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, /* 119 */ - 0x3D, 0x3E, 0x3F /* 123 - 255 initialized to 0x00 */ -}; - -/** - * ecryptfs_encode_for_filename - * @dst: Destination location for encoded filename - * @dst_size: Size of the encoded filename in bytes - * @src: Source location for the filename to encode - * @src_size: Size of the source in bytes - */ -void ecryptfs_encode_for_filename(unsigned char *dst, size_t *dst_size, - unsigned char *src, size_t src_size) -{ - size_t num_blocks; - size_t block_num = 0; - size_t dst_offset = 0; - unsigned char last_block[3]; - - if (src_size == 0) { - (*dst_size) = 0; - goto out; - } - num_blocks = (src_size / 3); - if ((src_size % 3) == 0) { - memcpy(last_block, (&src[src_size - 3]), 3); - } else { - num_blocks++; - last_block[2] = 0x00; - switch (src_size % 3) { - case 1: - last_block[0] = src[src_size - 1]; - last_block[1] = 0x00; - break; - case 2: - last_block[0] = src[src_size - 2]; - last_block[1] = src[src_size - 1]; - } - } - (*dst_size) = (num_blocks * 4); - if (!dst) - goto out; - while (block_num < num_blocks) { - unsigned char *src_block; - unsigned char dst_block[4]; - - if (block_num == (num_blocks - 1)) - src_block = last_block; - else - src_block = &src[block_num * 3]; - dst_block[0] = ((src_block[0] >> 2) & 0x3F); - dst_block[1] = (((src_block[0] << 4) & 0x30) - | ((src_block[1] >> 4) & 0x0F)); - dst_block[2] = (((src_block[1] << 2) & 0x3C) - | ((src_block[2] >> 6) & 0x03)); - dst_block[3] = (src_block[2] & 0x3F); - dst[dst_offset++] = portable_filename_chars[dst_block[0]]; - dst[dst_offset++] = portable_filename_chars[dst_block[1]]; - dst[dst_offset++] = portable_filename_chars[dst_block[2]]; - dst[dst_offset++] = portable_filename_chars[dst_block[3]]; - block_num++; - } -out: - return; -} - -static size_t ecryptfs_max_decoded_size(size_t encoded_size) -{ - /* Not exact; conservatively long. Every block of 4 - * encoded characters decodes into a block of 3 - * decoded characters. This segment of code provides - * the caller with the maximum amount of allocated - * space that @dst will need to point to in a - * subsequent call. */ - return ((encoded_size + 1) * 3) / 4; -} - -/** - * ecryptfs_decode_from_filename - * @dst: If NULL, this function only sets @dst_size and returns. If - * non-NULL, this function decodes the encoded octets in @src - * into the memory that @dst points to. - * @dst_size: Set to the size of the decoded string. - * @src: The encoded set of octets to decode. - * @src_size: The size of the encoded set of octets to decode. - */ -static void -ecryptfs_decode_from_filename(unsigned char *dst, size_t *dst_size, - const unsigned char *src, size_t src_size) -{ - u8 current_bit_offset = 0; - size_t src_byte_offset = 0; - size_t dst_byte_offset = 0; - - if (dst == NULL) { - (*dst_size) = ecryptfs_max_decoded_size(src_size); - goto out; - } - while (src_byte_offset < src_size) { - unsigned char src_byte = - filename_rev_map[(int)src[src_byte_offset]]; - - switch (current_bit_offset) { - case 0: - dst[dst_byte_offset] = (src_byte << 2); - current_bit_offset = 6; - break; - case 6: - dst[dst_byte_offset++] |= (src_byte >> 4); - dst[dst_byte_offset] = ((src_byte & 0xF) - << 4); - current_bit_offset = 4; - break; - case 4: - dst[dst_byte_offset++] |= (src_byte >> 2); - dst[dst_byte_offset] = (src_byte << 6); - current_bit_offset = 2; - break; - case 2: - dst[dst_byte_offset++] |= (src_byte); - dst[dst_byte_offset] = 0; - current_bit_offset = 0; - break; - } - src_byte_offset++; - } - (*dst_size) = dst_byte_offset; -out: - return; -} - -/** - * ecryptfs_encrypt_and_encode_filename - converts a plaintext file name to cipher text - * @crypt_stat: The crypt_stat struct associated with the file anem to encode - * @name: The plaintext name - * @length: The length of the plaintext - * @encoded_name: The encypted name - * - * Encrypts and encodes a filename into something that constitutes a - * valid filename for a filesystem, with printable characters. - * - * We assume that we have a properly initialized crypto context, - * pointed to by crypt_stat->tfm. - * - * Returns zero on success; non-zero on otherwise - */ -int ecryptfs_encrypt_and_encode_filename( - char **encoded_name, - size_t *encoded_name_size, - struct ecryptfs_crypt_stat *crypt_stat, - struct ecryptfs_mount_crypt_stat *mount_crypt_stat, - const char *name, size_t name_size) -{ - size_t encoded_name_no_prefix_size; - int rc = 0; - - (*encoded_name) = NULL; - (*encoded_name_size) = 0; - if ((crypt_stat && (crypt_stat->flags & ECRYPTFS_ENCRYPT_FILENAMES)) - || (mount_crypt_stat && (mount_crypt_stat->flags - & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES))) { - struct ecryptfs_filename *filename; - - filename = kzalloc(sizeof(*filename), GFP_KERNEL); - if (!filename) { - printk(KERN_ERR "%s: Out of memory whilst attempting " - "to kzalloc [%zd] bytes\n", __func__, - sizeof(*filename)); - rc = -ENOMEM; - goto out; - } - filename->filename = (char *)name; - filename->filename_size = name_size; - rc = ecryptfs_encrypt_filename(filename, crypt_stat, - mount_crypt_stat); - if (rc) { - printk(KERN_ERR "%s: Error attempting to encrypt " - "filename; rc = [%d]\n", __func__, rc); - kfree(filename); - goto out; - } - ecryptfs_encode_for_filename( - NULL, &encoded_name_no_prefix_size, - filename->encrypted_filename, - filename->encrypted_filename_size); - if ((crypt_stat && (crypt_stat->flags - & ECRYPTFS_ENCFN_USE_MOUNT_FNEK)) - || (mount_crypt_stat - && (mount_crypt_stat->flags - & ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK))) - (*encoded_name_size) = - (ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE - + encoded_name_no_prefix_size); - else - (*encoded_name_size) = - (ECRYPTFS_FEK_ENCRYPTED_FILENAME_PREFIX_SIZE - + encoded_name_no_prefix_size); - (*encoded_name) = kmalloc((*encoded_name_size) + 1, GFP_KERNEL); - if (!(*encoded_name)) { - printk(KERN_ERR "%s: Out of memory whilst attempting " - "to kzalloc [%zd] bytes\n", __func__, - (*encoded_name_size)); - rc = -ENOMEM; - kfree(filename->encrypted_filename); - kfree(filename); - goto out; - } - if ((crypt_stat && (crypt_stat->flags - & ECRYPTFS_ENCFN_USE_MOUNT_FNEK)) - || (mount_crypt_stat - && (mount_crypt_stat->flags - & ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK))) { - memcpy((*encoded_name), - ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX, - ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE); - ecryptfs_encode_for_filename( - ((*encoded_name) - + ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE), - &encoded_name_no_prefix_size, - filename->encrypted_filename, - filename->encrypted_filename_size); - (*encoded_name_size) = - (ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE - + encoded_name_no_prefix_size); - (*encoded_name)[(*encoded_name_size)] = '\0'; - } else { - rc = -EOPNOTSUPP; - } - if (rc) { - printk(KERN_ERR "%s: Error attempting to encode " - "encrypted filename; rc = [%d]\n", __func__, - rc); - kfree((*encoded_name)); - (*encoded_name) = NULL; - (*encoded_name_size) = 0; - } - kfree(filename->encrypted_filename); - kfree(filename); - } else { - rc = ecryptfs_copy_filename(encoded_name, - encoded_name_size, - name, name_size); - } -out: - return rc; -} - -/** - * ecryptfs_decode_and_decrypt_filename - converts the encoded cipher text name to decoded plaintext - * @plaintext_name: The plaintext name - * @plaintext_name_size: The plaintext name size - * @ecryptfs_dir_dentry: eCryptfs directory dentry - * @name: The filename in cipher text - * @name_size: The cipher text name size - * - * Decrypts and decodes the filename. - * - * Returns zero on error; non-zero otherwise - */ -int ecryptfs_decode_and_decrypt_filename(char **plaintext_name, - size_t *plaintext_name_size, - struct dentry *ecryptfs_dir_dentry, - const char *name, size_t name_size) -{ - struct ecryptfs_mount_crypt_stat *mount_crypt_stat = - &ecryptfs_superblock_to_private( - ecryptfs_dir_dentry->d_sb)->mount_crypt_stat; - char *decoded_name; - size_t decoded_name_size; - size_t packet_size; - int rc = 0; - - if ((mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) - && !(mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) - && (name_size > ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE) - && (strncmp(name, ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX, - ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE) == 0)) { - const char *orig_name = name; - size_t orig_name_size = name_size; - - name += ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE; - name_size -= ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE; - ecryptfs_decode_from_filename(NULL, &decoded_name_size, - name, name_size); - decoded_name = kmalloc(decoded_name_size, GFP_KERNEL); - if (!decoded_name) { - printk(KERN_ERR "%s: Out of memory whilst attempting " - "to kmalloc [%zd] bytes\n", __func__, - decoded_name_size); - rc = -ENOMEM; - goto out; - } - ecryptfs_decode_from_filename(decoded_name, &decoded_name_size, - name, name_size); - rc = ecryptfs_parse_tag_70_packet(plaintext_name, - plaintext_name_size, - &packet_size, - mount_crypt_stat, - decoded_name, - decoded_name_size); - if (rc) { - printk(KERN_INFO "%s: Could not parse tag 70 packet " - "from filename; copying through filename " - "as-is\n", __func__); - rc = ecryptfs_copy_filename(plaintext_name, - plaintext_name_size, - orig_name, orig_name_size); - goto out_free; - } - } else { - rc = ecryptfs_copy_filename(plaintext_name, - plaintext_name_size, - name, name_size); - goto out; - } -out_free: - kfree(decoded_name); -out: - return rc; -} - -#define ENC_NAME_MAX_BLOCKLEN_8_OR_16 143 - -int ecryptfs_set_f_namelen(long *namelen, long lower_namelen, - struct ecryptfs_mount_crypt_stat *mount_crypt_stat) -{ - struct blkcipher_desc desc; - struct mutex *tfm_mutex; - size_t cipher_blocksize; - int rc; - - if (!(mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)) { - (*namelen) = lower_namelen; - return 0; - } - - rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&desc.tfm, &tfm_mutex, - mount_crypt_stat->global_default_fn_cipher_name); - if (unlikely(rc)) { - (*namelen) = 0; - return rc; - } - - mutex_lock(tfm_mutex); - cipher_blocksize = crypto_blkcipher_blocksize(desc.tfm); - mutex_unlock(tfm_mutex); - - /* Return an exact amount for the common cases */ - if (lower_namelen == NAME_MAX - && (cipher_blocksize == 8 || cipher_blocksize == 16)) { - (*namelen) = ENC_NAME_MAX_BLOCKLEN_8_OR_16; - return 0; - } - - /* Return a safe estimate for the uncommon cases */ - (*namelen) = lower_namelen; - (*namelen) -= ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE; - /* Since this is the max decoded size, subtract 1 "decoded block" len */ - (*namelen) = ecryptfs_max_decoded_size(*namelen) - 3; - (*namelen) -= ECRYPTFS_TAG_70_MAX_METADATA_SIZE; - (*namelen) -= ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES; - /* Worst case is that the filename is padded nearly a full block size */ - (*namelen) -= cipher_blocksize - 1; - - if ((*namelen) < 0) - (*namelen) = 0; - - return 0; -} diff --git a/ANDROID_3.4.5/fs/ecryptfs/debug.c b/ANDROID_3.4.5/fs/ecryptfs/debug.c deleted file mode 100644 index 3d2bdf54..00000000 --- a/ANDROID_3.4.5/fs/ecryptfs/debug.c +++ /dev/null @@ -1,121 +0,0 @@ -/** - * eCryptfs: Linux filesystem encryption layer - * Functions only useful for debugging. - * - * Copyright (C) 2006 International Business Machines Corp. - * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include "ecryptfs_kernel.h" - -/** - * ecryptfs_dump_auth_tok - debug function to print auth toks - * - * This function will print the contents of an ecryptfs authentication - * token. - */ -void ecryptfs_dump_auth_tok(struct ecryptfs_auth_tok *auth_tok) -{ - char salt[ECRYPTFS_SALT_SIZE * 2 + 1]; - char sig[ECRYPTFS_SIG_SIZE_HEX + 1]; - - ecryptfs_printk(KERN_DEBUG, "Auth tok at mem loc [%p]:\n", - auth_tok); - if (auth_tok->flags & ECRYPTFS_PRIVATE_KEY) { - ecryptfs_printk(KERN_DEBUG, " * private key type\n"); - } else { - ecryptfs_printk(KERN_DEBUG, " * passphrase type\n"); - ecryptfs_to_hex(salt, auth_tok->token.password.salt, - ECRYPTFS_SALT_SIZE); - salt[ECRYPTFS_SALT_SIZE * 2] = '\0'; - ecryptfs_printk(KERN_DEBUG, " * salt = [%s]\n", salt); - if (auth_tok->token.password.flags & - ECRYPTFS_PERSISTENT_PASSWORD) { - ecryptfs_printk(KERN_DEBUG, " * persistent\n"); - } - memcpy(sig, auth_tok->token.password.signature, - ECRYPTFS_SIG_SIZE_HEX); - sig[ECRYPTFS_SIG_SIZE_HEX] = '\0'; - ecryptfs_printk(KERN_DEBUG, " * signature = [%s]\n", sig); - } - ecryptfs_printk(KERN_DEBUG, " * session_key.flags = [0x%x]\n", - auth_tok->session_key.flags); - if (auth_tok->session_key.flags - & ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT) - ecryptfs_printk(KERN_DEBUG, - " * Userspace decrypt request set\n"); - if (auth_tok->session_key.flags - & ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT) - ecryptfs_printk(KERN_DEBUG, - " * Userspace encrypt request set\n"); - if (auth_tok->session_key.flags & ECRYPTFS_CONTAINS_DECRYPTED_KEY) { - ecryptfs_printk(KERN_DEBUG, " * Contains decrypted key\n"); - ecryptfs_printk(KERN_DEBUG, - " * session_key.decrypted_key_size = [0x%x]\n", - auth_tok->session_key.decrypted_key_size); - ecryptfs_printk(KERN_DEBUG, " * Decrypted session key " - "dump:\n"); - if (ecryptfs_verbosity > 0) - ecryptfs_dump_hex(auth_tok->session_key.decrypted_key, - ECRYPTFS_DEFAULT_KEY_BYTES); - } - if (auth_tok->session_key.flags & ECRYPTFS_CONTAINS_ENCRYPTED_KEY) { - ecryptfs_printk(KERN_DEBUG, " * Contains encrypted key\n"); - ecryptfs_printk(KERN_DEBUG, - " * session_key.encrypted_key_size = [0x%x]\n", - auth_tok->session_key.encrypted_key_size); - ecryptfs_printk(KERN_DEBUG, " * Encrypted session key " - "dump:\n"); - if (ecryptfs_verbosity > 0) - ecryptfs_dump_hex(auth_tok->session_key.encrypted_key, - auth_tok->session_key. - encrypted_key_size); - } -} - -/** - * ecryptfs_dump_hex - debug hex printer - * @data: string of bytes to be printed - * @bytes: number of bytes to print - * - * Dump hexadecimal representation of char array - */ -void ecryptfs_dump_hex(char *data, int bytes) -{ - int i = 0; - int add_newline = 1; - - if (ecryptfs_verbosity < 1) - return; - if (bytes != 0) { - printk(KERN_DEBUG "0x%.2x.", (unsigned char)data[i]); - i++; - } - while (i < bytes) { - printk("0x%.2x.", (unsigned char)data[i]); - i++; - if (i % 16 == 0) { - printk("\n"); - add_newline = 0; - } else - add_newline = 1; - } - if (add_newline) - printk("\n"); -} - diff --git a/ANDROID_3.4.5/fs/ecryptfs/dentry.c b/ANDROID_3.4.5/fs/ecryptfs/dentry.c deleted file mode 100644 index 534c1d46..00000000 --- a/ANDROID_3.4.5/fs/ecryptfs/dentry.c +++ /dev/null @@ -1,105 +0,0 @@ -/** - * eCryptfs: Linux filesystem encryption layer - * - * Copyright (C) 1997-2003 Erez Zadok - * Copyright (C) 2001-2003 Stony Brook University - * Copyright (C) 2004-2006 International Business Machines Corp. - * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <linux/dcache.h> -#include <linux/namei.h> -#include <linux/mount.h> -#include <linux/fs_stack.h> -#include <linux/slab.h> -#include "ecryptfs_kernel.h" - -/** - * ecryptfs_d_revalidate - revalidate an ecryptfs dentry - * @dentry: The ecryptfs dentry - * @nd: The associated nameidata - * - * Called when the VFS needs to revalidate a dentry. This - * is called whenever a name lookup finds a dentry in the - * dcache. Most filesystems leave this as NULL, because all their - * dentries in the dcache are valid. - * - * Returns 1 if valid, 0 otherwise. - * - */ -static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd) -{ - struct dentry *lower_dentry; - struct vfsmount *lower_mnt; - struct dentry *dentry_save = NULL; - struct vfsmount *vfsmount_save = NULL; - int rc = 1; - - if (nd && nd->flags & LOOKUP_RCU) - return -ECHILD; - - lower_dentry = ecryptfs_dentry_to_lower(dentry); - lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); - if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate) - goto out; - if (nd) { - dentry_save = nd->path.dentry; - vfsmount_save = nd->path.mnt; - nd->path.dentry = lower_dentry; - nd->path.mnt = lower_mnt; - } - rc = lower_dentry->d_op->d_revalidate(lower_dentry, nd); - if (nd) { - nd->path.dentry = dentry_save; - nd->path.mnt = vfsmount_save; - } - if (dentry->d_inode) { - struct inode *lower_inode = - ecryptfs_inode_to_lower(dentry->d_inode); - - fsstack_copy_attr_all(dentry->d_inode, lower_inode); - } -out: - return rc; -} - -struct kmem_cache *ecryptfs_dentry_info_cache; - -/** - * ecryptfs_d_release - * @dentry: The ecryptfs dentry - * - * Called when a dentry is really deallocated. - */ -static void ecryptfs_d_release(struct dentry *dentry) -{ - if (ecryptfs_dentry_to_private(dentry)) { - if (ecryptfs_dentry_to_lower(dentry)) { - dput(ecryptfs_dentry_to_lower(dentry)); - mntput(ecryptfs_dentry_to_lower_mnt(dentry)); - } - kmem_cache_free(ecryptfs_dentry_info_cache, - ecryptfs_dentry_to_private(dentry)); - } - return; -} - -const struct dentry_operations ecryptfs_dops = { - .d_revalidate = ecryptfs_d_revalidate, - .d_release = ecryptfs_d_release, -}; diff --git a/ANDROID_3.4.5/fs/ecryptfs/ecryptfs_kernel.h b/ANDROID_3.4.5/fs/ecryptfs/ecryptfs_kernel.h deleted file mode 100644 index 867b64c5..00000000 --- a/ANDROID_3.4.5/fs/ecryptfs/ecryptfs_kernel.h +++ /dev/null @@ -1,713 +0,0 @@ -/** - * eCryptfs: Linux filesystem encryption layer - * Kernel declarations. - * - * Copyright (C) 1997-2003 Erez Zadok - * Copyright (C) 2001-2003 Stony Brook University - * Copyright (C) 2004-2008 International Business Machines Corp. - * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> - * Trevor S. Highland <trevor.highland@gmail.com> - * Tyler Hicks <tyhicks@ou.edu> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef ECRYPTFS_KERNEL_H -#define ECRYPTFS_KERNEL_H - -#include <keys/user-type.h> -#include <keys/encrypted-type.h> -#include <linux/fs.h> -#include <linux/fs_stack.h> -#include <linux/namei.h> -#include <linux/scatterlist.h> -#include <linux/hash.h> -#include <linux/nsproxy.h> -#include <linux/backing-dev.h> -#include <linux/ecryptfs.h> - -#define ECRYPTFS_DEFAULT_IV_BYTES 16 -#define ECRYPTFS_DEFAULT_EXTENT_SIZE 4096 -#define ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE 8192 -#define ECRYPTFS_DEFAULT_MSG_CTX_ELEMS 32 -#define ECRYPTFS_DEFAULT_SEND_TIMEOUT HZ -#define ECRYPTFS_MAX_MSG_CTX_TTL (HZ*3) -#define ECRYPTFS_DEFAULT_NUM_USERS 4 -#define ECRYPTFS_MAX_NUM_USERS 32768 -#define ECRYPTFS_XATTR_NAME "user.ecryptfs" - -void ecryptfs_dump_auth_tok(struct ecryptfs_auth_tok *auth_tok); -extern void ecryptfs_to_hex(char *dst, char *src, size_t src_size); -extern void ecryptfs_from_hex(char *dst, char *src, int dst_size); - -struct ecryptfs_key_record { - unsigned char type; - size_t enc_key_size; - unsigned char sig[ECRYPTFS_SIG_SIZE]; - unsigned char enc_key[ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES]; -}; - -struct ecryptfs_auth_tok_list { - struct ecryptfs_auth_tok *auth_tok; - struct list_head list; -}; - -struct ecryptfs_crypt_stat; -struct ecryptfs_mount_crypt_stat; - -struct ecryptfs_page_crypt_context { - struct page *page; -#define ECRYPTFS_PREPARE_COMMIT_MODE 0 -#define ECRYPTFS_WRITEPAGE_MODE 1 - unsigned int mode; - union { - struct file *lower_file; - struct writeback_control *wbc; - } param; -}; - -#if defined(CONFIG_ENCRYPTED_KEYS) || defined(CONFIG_ENCRYPTED_KEYS_MODULE) -static inline struct ecryptfs_auth_tok * -ecryptfs_get_encrypted_key_payload_data(struct key *key) -{ - if (key->type == &key_type_encrypted) - return (struct ecryptfs_auth_tok *) - (&((struct encrypted_key_payload *)key->payload.data)->payload_data); - else - return NULL; -} - -static inline struct key *ecryptfs_get_encrypted_key(char *sig) -{ - return request_key(&key_type_encrypted, sig, NULL); -} - -#else -static inline struct ecryptfs_auth_tok * -ecryptfs_get_encrypted_key_payload_data(struct key *key) -{ - return NULL; -} - -static inline struct key *ecryptfs_get_encrypted_key(char *sig) -{ - return ERR_PTR(-ENOKEY); -} - -#endif /* CONFIG_ENCRYPTED_KEYS */ - -static inline struct ecryptfs_auth_tok * -ecryptfs_get_key_payload_data(struct key *key) -{ - struct ecryptfs_auth_tok *auth_tok; - - auth_tok = ecryptfs_get_encrypted_key_payload_data(key); - if (!auth_tok) - return (struct ecryptfs_auth_tok *) - (((struct user_key_payload *)key->payload.data)->data); - else - return auth_tok; -} - -#define ECRYPTFS_MAX_KEYSET_SIZE 1024 -#define ECRYPTFS_MAX_CIPHER_NAME_SIZE 32 -#define ECRYPTFS_MAX_NUM_ENC_KEYS 64 -#define ECRYPTFS_MAX_IV_BYTES 16 /* 128 bits */ -#define ECRYPTFS_SALT_BYTES 2 -#define MAGIC_ECRYPTFS_MARKER 0x3c81b7f5 -#define MAGIC_ECRYPTFS_MARKER_SIZE_BYTES 8 /* 4*2 */ -#define ECRYPTFS_FILE_SIZE_BYTES (sizeof(u64)) -#define ECRYPTFS_SIZE_AND_MARKER_BYTES (ECRYPTFS_FILE_SIZE_BYTES \ - + MAGIC_ECRYPTFS_MARKER_SIZE_BYTES) -#define ECRYPTFS_DEFAULT_CIPHER "aes" -#define ECRYPTFS_DEFAULT_KEY_BYTES 16 -#define ECRYPTFS_DEFAULT_HASH "md5" -#define ECRYPTFS_TAG_70_DIGEST ECRYPTFS_DEFAULT_HASH -#define ECRYPTFS_TAG_1_PACKET_TYPE 0x01 -#define ECRYPTFS_TAG_3_PACKET_TYPE 0x8C -#define ECRYPTFS_TAG_11_PACKET_TYPE 0xED -#define ECRYPTFS_TAG_64_PACKET_TYPE 0x40 -#define ECRYPTFS_TAG_65_PACKET_TYPE 0x41 -#define ECRYPTFS_TAG_66_PACKET_TYPE 0x42 -#define ECRYPTFS_TAG_67_PACKET_TYPE 0x43 -#define ECRYPTFS_TAG_70_PACKET_TYPE 0x46 /* FNEK-encrypted filename - * as dentry name */ -#define ECRYPTFS_TAG_71_PACKET_TYPE 0x47 /* FNEK-encrypted filename in - * metadata */ -#define ECRYPTFS_TAG_72_PACKET_TYPE 0x48 /* FEK-encrypted filename as - * dentry name */ -#define ECRYPTFS_TAG_73_PACKET_TYPE 0x49 /* FEK-encrypted filename as - * metadata */ -#define ECRYPTFS_MIN_PKT_LEN_SIZE 1 /* Min size to specify packet length */ -#define ECRYPTFS_MAX_PKT_LEN_SIZE 2 /* Pass at least this many bytes to - * ecryptfs_parse_packet_length() and - * ecryptfs_write_packet_length() - */ -/* Constraint: ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES >= - * ECRYPTFS_MAX_IV_BYTES */ -#define ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES 16 -#define ECRYPTFS_NON_NULL 0x42 /* A reasonable substitute for NULL */ -#define MD5_DIGEST_SIZE 16 -#define ECRYPTFS_TAG_70_DIGEST_SIZE MD5_DIGEST_SIZE -#define ECRYPTFS_TAG_70_MIN_METADATA_SIZE (1 + ECRYPTFS_MIN_PKT_LEN_SIZE \ - + ECRYPTFS_SIG_SIZE + 1 + 1) -#define ECRYPTFS_TAG_70_MAX_METADATA_SIZE (1 + ECRYPTFS_MAX_PKT_LEN_SIZE \ - + ECRYPTFS_SIG_SIZE + 1 + 1) -#define ECRYPTFS_FEK_ENCRYPTED_FILENAME_PREFIX "ECRYPTFS_FEK_ENCRYPTED." -#define ECRYPTFS_FEK_ENCRYPTED_FILENAME_PREFIX_SIZE 23 -#define ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX "ECRYPTFS_FNEK_ENCRYPTED." -#define ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE 24 -#define ECRYPTFS_ENCRYPTED_DENTRY_NAME_LEN (18 + 1 + 4 + 1 + 32) - -struct ecryptfs_key_sig { - struct list_head crypt_stat_list; - char keysig[ECRYPTFS_SIG_SIZE_HEX + 1]; -}; - -struct ecryptfs_filename { - struct list_head crypt_stat_list; -#define ECRYPTFS_FILENAME_CONTAINS_DECRYPTED 0x00000001 - u32 flags; - u32 seq_no; - char *filename; - char *encrypted_filename; - size_t filename_size; - size_t encrypted_filename_size; - char fnek_sig[ECRYPTFS_SIG_SIZE_HEX]; - char dentry_name[ECRYPTFS_ENCRYPTED_DENTRY_NAME_LEN + 1]; -}; - -/** - * This is the primary struct associated with each encrypted file. - * - * TODO: cache align/pack? - */ -struct ecryptfs_crypt_stat { -#define ECRYPTFS_STRUCT_INITIALIZED 0x00000001 -#define ECRYPTFS_POLICY_APPLIED 0x00000002 -#define ECRYPTFS_ENCRYPTED 0x00000004 -#define ECRYPTFS_SECURITY_WARNING 0x00000008 -#define ECRYPTFS_ENABLE_HMAC 0x00000010 -#define ECRYPTFS_ENCRYPT_IV_PAGES 0x00000020 -#define ECRYPTFS_KEY_VALID 0x00000040 -#define ECRYPTFS_METADATA_IN_XATTR 0x00000080 -#define ECRYPTFS_VIEW_AS_ENCRYPTED 0x00000100 -#define ECRYPTFS_KEY_SET 0x00000200 -#define ECRYPTFS_ENCRYPT_FILENAMES 0x00000400 -#define ECRYPTFS_ENCFN_USE_MOUNT_FNEK 0x00000800 -#define ECRYPTFS_ENCFN_USE_FEK 0x00001000 -#define ECRYPTFS_UNLINK_SIGS 0x00002000 -#define ECRYPTFS_I_SIZE_INITIALIZED 0x00004000 - u32 flags; - unsigned int file_version; - size_t iv_bytes; - size_t metadata_size; - size_t extent_size; /* Data extent size; default is 4096 */ - size_t key_size; - size_t extent_shift; - unsigned int extent_mask; - struct ecryptfs_mount_crypt_stat *mount_crypt_stat; - struct crypto_blkcipher *tfm; - struct crypto_hash *hash_tfm; /* Crypto context for generating - * the initialization vectors */ - unsigned char cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE]; - unsigned char key[ECRYPTFS_MAX_KEY_BYTES]; - unsigned char root_iv[ECRYPTFS_MAX_IV_BYTES]; - struct list_head keysig_list; - struct mutex keysig_list_mutex; - struct mutex cs_tfm_mutex; - struct mutex cs_hash_tfm_mutex; - struct mutex cs_mutex; -}; - -/* inode private data. */ -struct ecryptfs_inode_info { - struct inode vfs_inode; - struct inode *wii_inode; - struct mutex lower_file_mutex; - atomic_t lower_file_count; - struct file *lower_file; - struct ecryptfs_crypt_stat crypt_stat; -}; - -/* dentry private data. Each dentry must keep track of a lower - * vfsmount too. */ -struct ecryptfs_dentry_info { - struct path lower_path; - struct ecryptfs_crypt_stat *crypt_stat; -}; - -/** - * ecryptfs_global_auth_tok - A key used to encrypt all new files under the mountpoint - * @flags: Status flags - * @mount_crypt_stat_list: These auth_toks hang off the mount-wide - * cryptographic context. Every time a new - * inode comes into existence, eCryptfs copies - * the auth_toks on that list to the set of - * auth_toks on the inode's crypt_stat - * @global_auth_tok_key: The key from the user's keyring for the sig - * @global_auth_tok: The key contents - * @sig: The key identifier - * - * ecryptfs_global_auth_tok structs refer to authentication token keys - * in the user keyring that apply to newly created files. A list of - * these objects hangs off of the mount_crypt_stat struct for any - * given eCryptfs mount. This struct maintains a reference to both the - * key contents and the key itself so that the key can be put on - * unmount. - */ -struct ecryptfs_global_auth_tok { -#define ECRYPTFS_AUTH_TOK_INVALID 0x00000001 -#define ECRYPTFS_AUTH_TOK_FNEK 0x00000002 - u32 flags; - struct list_head mount_crypt_stat_list; - struct key *global_auth_tok_key; - unsigned char sig[ECRYPTFS_SIG_SIZE_HEX + 1]; -}; - -/** - * ecryptfs_key_tfm - Persistent key tfm - * @key_tfm: crypto API handle to the key - * @key_size: Key size in bytes - * @key_tfm_mutex: Mutex to ensure only one operation in eCryptfs is - * using the persistent TFM at any point in time - * @key_tfm_list: Handle to hang this off the module-wide TFM list - * @cipher_name: String name for the cipher for this TFM - * - * Typically, eCryptfs will use the same ciphers repeatedly throughout - * the course of its operations. In order to avoid unnecessarily - * destroying and initializing the same cipher repeatedly, eCryptfs - * keeps a list of crypto API contexts around to use when needed. - */ -struct ecryptfs_key_tfm { - struct crypto_blkcipher *key_tfm; - size_t key_size; - struct mutex key_tfm_mutex; - struct list_head key_tfm_list; - unsigned char cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE + 1]; -}; - -extern struct mutex key_tfm_list_mutex; - -/** - * This struct is to enable a mount-wide passphrase/salt combo. This - * is more or less a stopgap to provide similar functionality to other - * crypto filesystems like EncFS or CFS until full policy support is - * implemented in eCryptfs. - */ -struct ecryptfs_mount_crypt_stat { - /* Pointers to memory we do not own, do not free these */ -#define ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED 0x00000001 -#define ECRYPTFS_XATTR_METADATA_ENABLED 0x00000002 -#define ECRYPTFS_ENCRYPTED_VIEW_ENABLED 0x00000004 -#define ECRYPTFS_MOUNT_CRYPT_STAT_INITIALIZED 0x00000008 -#define ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES 0x00000010 -#define ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK 0x00000020 -#define ECRYPTFS_GLOBAL_ENCFN_USE_FEK 0x00000040 -#define ECRYPTFS_GLOBAL_MOUNT_AUTH_TOK_ONLY 0x00000080 - u32 flags; - struct list_head global_auth_tok_list; - struct mutex global_auth_tok_list_mutex; - size_t global_default_cipher_key_size; - size_t global_default_fn_cipher_key_bytes; - unsigned char global_default_cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE - + 1]; - unsigned char global_default_fn_cipher_name[ - ECRYPTFS_MAX_CIPHER_NAME_SIZE + 1]; - char global_default_fnek_sig[ECRYPTFS_SIG_SIZE_HEX + 1]; -}; - -/* superblock private data. */ -struct ecryptfs_sb_info { - struct super_block *wsi_sb; - struct ecryptfs_mount_crypt_stat mount_crypt_stat; - struct backing_dev_info bdi; -}; - -/* file private data. */ -struct ecryptfs_file_info { - struct file *wfi_file; - struct ecryptfs_crypt_stat *crypt_stat; -}; - -/* auth_tok <=> encrypted_session_key mappings */ -struct ecryptfs_auth_tok_list_item { - unsigned char encrypted_session_key[ECRYPTFS_MAX_KEY_BYTES]; - struct list_head list; - struct ecryptfs_auth_tok auth_tok; -}; - -struct ecryptfs_message { - /* Can never be greater than ecryptfs_message_buf_len */ - /* Used to find the parent msg_ctx */ - /* Inherits from msg_ctx->index */ - u32 index; - u32 data_len; - u8 data[]; -}; - -struct ecryptfs_msg_ctx { -#define ECRYPTFS_MSG_CTX_STATE_FREE 0x01 -#define ECRYPTFS_MSG_CTX_STATE_PENDING 0x02 -#define ECRYPTFS_MSG_CTX_STATE_DONE 0x03 -#define ECRYPTFS_MSG_CTX_STATE_NO_REPLY 0x04 - u8 state; -#define ECRYPTFS_MSG_HELO 100 -#define ECRYPTFS_MSG_QUIT 101 -#define ECRYPTFS_MSG_REQUEST 102 -#define ECRYPTFS_MSG_RESPONSE 103 - u8 type; - u32 index; - /* Counter converts to a sequence number. Each message sent - * out for which we expect a response has an associated - * sequence number. The response must have the same sequence - * number as the counter for the msg_stc for the message to be - * valid. */ - u32 counter; - size_t msg_size; - struct ecryptfs_message *msg; - struct task_struct *task; - struct list_head node; - struct list_head daemon_out_list; - struct mutex mux; -}; - -struct ecryptfs_daemon; - -struct ecryptfs_daemon { -#define ECRYPTFS_DAEMON_IN_READ 0x00000001 -#define ECRYPTFS_DAEMON_IN_POLL 0x00000002 -#define ECRYPTFS_DAEMON_ZOMBIE 0x00000004 -#define ECRYPTFS_DAEMON_MISCDEV_OPEN 0x00000008 - u32 flags; - u32 num_queued_msg_ctx; - struct pid *pid; - uid_t euid; - struct user_namespace *user_ns; - struct task_struct *task; - struct mutex mux; - struct list_head msg_ctx_out_queue; - wait_queue_head_t wait; - struct hlist_node euid_chain; -}; - -extern struct mutex ecryptfs_daemon_hash_mux; - -static inline size_t -ecryptfs_lower_header_size(struct ecryptfs_crypt_stat *crypt_stat) -{ - if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) - return 0; - return crypt_stat->metadata_size; -} - -static inline struct ecryptfs_file_info * -ecryptfs_file_to_private(struct file *file) -{ - return file->private_data; -} - -static inline void -ecryptfs_set_file_private(struct file *file, - struct ecryptfs_file_info *file_info) -{ - file->private_data = file_info; -} - -static inline struct file *ecryptfs_file_to_lower(struct file *file) -{ - return ((struct ecryptfs_file_info *)file->private_data)->wfi_file; -} - -static inline void -ecryptfs_set_file_lower(struct file *file, struct file *lower_file) -{ - ((struct ecryptfs_file_info *)file->private_data)->wfi_file = - lower_file; -} - -static inline struct ecryptfs_inode_info * -ecryptfs_inode_to_private(struct inode *inode) -{ - return container_of(inode, struct ecryptfs_inode_info, vfs_inode); -} - -static inline struct inode *ecryptfs_inode_to_lower(struct inode *inode) -{ - return ecryptfs_inode_to_private(inode)->wii_inode; -} - -static inline void -ecryptfs_set_inode_lower(struct inode *inode, struct inode *lower_inode) -{ - ecryptfs_inode_to_private(inode)->wii_inode = lower_inode; -} - -static inline struct ecryptfs_sb_info * -ecryptfs_superblock_to_private(struct super_block *sb) -{ - return (struct ecryptfs_sb_info *)sb->s_fs_info; -} - -static inline void -ecryptfs_set_superblock_private(struct super_block *sb, - struct ecryptfs_sb_info *sb_info) -{ - sb->s_fs_info = sb_info; -} - -static inline struct super_block * -ecryptfs_superblock_to_lower(struct super_block *sb) -{ - return ((struct ecryptfs_sb_info *)sb->s_fs_info)->wsi_sb; -} - -static inline void -ecryptfs_set_superblock_lower(struct super_block *sb, - struct super_block *lower_sb) -{ - ((struct ecryptfs_sb_info *)sb->s_fs_info)->wsi_sb = lower_sb; -} - -static inline struct ecryptfs_dentry_info * -ecryptfs_dentry_to_private(struct dentry *dentry) -{ - return (struct ecryptfs_dentry_info *)dentry->d_fsdata; -} - -static inline void -ecryptfs_set_dentry_private(struct dentry *dentry, - struct ecryptfs_dentry_info *dentry_info) -{ - dentry->d_fsdata = dentry_info; -} - -static inline struct dentry * -ecryptfs_dentry_to_lower(struct dentry *dentry) -{ - return ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.dentry; -} - -static inline void -ecryptfs_set_dentry_lower(struct dentry *dentry, struct dentry *lower_dentry) -{ - ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.dentry = - lower_dentry; -} - -static inline struct vfsmount * -ecryptfs_dentry_to_lower_mnt(struct dentry *dentry) -{ - return ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.mnt; -} - -static inline void -ecryptfs_set_dentry_lower_mnt(struct dentry *dentry, struct vfsmount *lower_mnt) -{ - ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.mnt = - lower_mnt; -} - -#define ecryptfs_printk(type, fmt, arg...) \ - __ecryptfs_printk(type "%s: " fmt, __func__, ## arg); -__printf(1, 2) -void __ecryptfs_printk(const char *fmt, ...); - -extern const struct file_operations ecryptfs_main_fops; -extern const struct file_operations ecryptfs_dir_fops; -extern const struct inode_operations ecryptfs_main_iops; -extern const struct inode_operations ecryptfs_dir_iops; -extern const struct inode_operations ecryptfs_symlink_iops; -extern const struct super_operations ecryptfs_sops; -extern const struct dentry_operations ecryptfs_dops; -extern const struct address_space_operations ecryptfs_aops; -extern int ecryptfs_verbosity; -extern unsigned int ecryptfs_message_buf_len; -extern signed long ecryptfs_message_wait_timeout; -extern unsigned int ecryptfs_number_of_users; - -extern struct kmem_cache *ecryptfs_auth_tok_list_item_cache; -extern struct kmem_cache *ecryptfs_file_info_cache; -extern struct kmem_cache *ecryptfs_dentry_info_cache; -extern struct kmem_cache *ecryptfs_inode_info_cache; -extern struct kmem_cache *ecryptfs_sb_info_cache; -extern struct kmem_cache *ecryptfs_header_cache; -extern struct kmem_cache *ecryptfs_xattr_cache; -extern struct kmem_cache *ecryptfs_key_record_cache; -extern struct kmem_cache *ecryptfs_key_sig_cache; -extern struct kmem_cache *ecryptfs_global_auth_tok_cache; -extern struct kmem_cache *ecryptfs_key_tfm_cache; -extern struct kmem_cache *ecryptfs_open_req_cache; - -struct ecryptfs_open_req { -#define ECRYPTFS_REQ_PROCESSED 0x00000001 -#define ECRYPTFS_REQ_DROPPED 0x00000002 -#define ECRYPTFS_REQ_ZOMBIE 0x00000004 - u32 flags; - struct file **lower_file; - struct dentry *lower_dentry; - struct vfsmount *lower_mnt; - wait_queue_head_t wait; - struct mutex mux; - struct list_head kthread_ctl_list; -}; - -struct inode *ecryptfs_get_inode(struct inode *lower_inode, - struct super_block *sb); -void ecryptfs_i_size_init(const char *page_virt, struct inode *inode); -int ecryptfs_decode_and_decrypt_filename(char **decrypted_name, - size_t *decrypted_name_size, - struct dentry *ecryptfs_dentry, - const char *name, size_t name_size); -int ecryptfs_fill_zeros(struct file *file, loff_t new_length); -int ecryptfs_encrypt_and_encode_filename( - char **encoded_name, - size_t *encoded_name_size, - struct ecryptfs_crypt_stat *crypt_stat, - struct ecryptfs_mount_crypt_stat *mount_crypt_stat, - const char *name, size_t name_size); -struct dentry *ecryptfs_lower_dentry(struct dentry *this_dentry); -void ecryptfs_dump_hex(char *data, int bytes); -int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg, - int sg_size); -int ecryptfs_compute_root_iv(struct ecryptfs_crypt_stat *crypt_stat); -void ecryptfs_rotate_iv(unsigned char *iv); -void ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat); -void ecryptfs_destroy_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat); -void ecryptfs_destroy_mount_crypt_stat( - struct ecryptfs_mount_crypt_stat *mount_crypt_stat); -int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat); -int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode); -int ecryptfs_encrypt_page(struct page *page); -int ecryptfs_decrypt_page(struct page *page); -int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry, - struct inode *ecryptfs_inode); -int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry); -int ecryptfs_new_file_context(struct inode *ecryptfs_inode); -void ecryptfs_write_crypt_stat_flags(char *page_virt, - struct ecryptfs_crypt_stat *crypt_stat, - size_t *written); -int ecryptfs_read_and_validate_header_region(struct inode *inode); -int ecryptfs_read_and_validate_xattr_region(struct dentry *dentry, - struct inode *inode); -u8 ecryptfs_code_for_cipher_string(char *cipher_name, size_t key_bytes); -int ecryptfs_cipher_code_to_string(char *str, u8 cipher_code); -void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat); -int ecryptfs_generate_key_packet_set(char *dest_base, - struct ecryptfs_crypt_stat *crypt_stat, - struct dentry *ecryptfs_dentry, - size_t *len, size_t max); -int -ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat, - unsigned char *src, struct dentry *ecryptfs_dentry); -int ecryptfs_truncate(struct dentry *dentry, loff_t new_length); -ssize_t -ecryptfs_getxattr_lower(struct dentry *lower_dentry, const char *name, - void *value, size_t size); -int -ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, - size_t size, int flags); -int ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode); -int ecryptfs_process_helo(uid_t euid, struct user_namespace *user_ns, - struct pid *pid); -int ecryptfs_process_quit(uid_t euid, struct user_namespace *user_ns, - struct pid *pid); -int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, - struct user_namespace *user_ns, struct pid *pid, - u32 seq); -int ecryptfs_send_message(char *data, int data_len, - struct ecryptfs_msg_ctx **msg_ctx); -int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx, - struct ecryptfs_message **emsg); -int ecryptfs_init_messaging(void); -void ecryptfs_release_messaging(void); - -void -ecryptfs_write_header_metadata(char *virt, - struct ecryptfs_crypt_stat *crypt_stat, - size_t *written); -int ecryptfs_add_keysig(struct ecryptfs_crypt_stat *crypt_stat, char *sig); -int -ecryptfs_add_global_auth_tok(struct ecryptfs_mount_crypt_stat *mount_crypt_stat, - char *sig, u32 global_auth_tok_flags); -int ecryptfs_get_global_auth_tok_for_sig( - struct ecryptfs_global_auth_tok **global_auth_tok, - struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig); -int -ecryptfs_add_new_key_tfm(struct ecryptfs_key_tfm **key_tfm, char *cipher_name, - size_t key_size); -int ecryptfs_init_crypto(void); -int ecryptfs_destroy_crypto(void); -int ecryptfs_tfm_exists(char *cipher_name, struct ecryptfs_key_tfm **key_tfm); -int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_blkcipher **tfm, - struct mutex **tfm_mutex, - char *cipher_name); -int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key, - struct ecryptfs_auth_tok **auth_tok, - char *sig); -int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data, - loff_t offset, size_t size); -int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode, - struct page *page_for_lower, - size_t offset_in_page, size_t size); -int ecryptfs_write(struct inode *inode, char *data, loff_t offset, size_t size); -int ecryptfs_read_lower(char *data, loff_t offset, size_t size, - struct inode *ecryptfs_inode); -int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs, - pgoff_t page_index, - size_t offset_in_page, size_t size, - struct inode *ecryptfs_inode); -struct page *ecryptfs_get_locked_page(struct inode *inode, loff_t index); -int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon); -int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon, uid_t euid, - struct user_namespace *user_ns); -int ecryptfs_parse_packet_length(unsigned char *data, size_t *size, - size_t *length_size); -int ecryptfs_write_packet_length(char *dest, size_t size, - size_t *packet_size_length); -int ecryptfs_init_ecryptfs_miscdev(void); -void ecryptfs_destroy_ecryptfs_miscdev(void); -int ecryptfs_send_miscdev(char *data, size_t data_size, - struct ecryptfs_msg_ctx *msg_ctx, u8 msg_type, - u16 msg_flags, struct ecryptfs_daemon *daemon); -void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx); -int -ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid, - struct user_namespace *user_ns, struct pid *pid); -int ecryptfs_init_kthread(void); -void ecryptfs_destroy_kthread(void); -int ecryptfs_privileged_open(struct file **lower_file, - struct dentry *lower_dentry, - struct vfsmount *lower_mnt, - const struct cred *cred); -int ecryptfs_get_lower_file(struct dentry *dentry, struct inode *inode); -void ecryptfs_put_lower_file(struct inode *inode); -int -ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, - size_t *packet_size, - struct ecryptfs_mount_crypt_stat *mount_crypt_stat, - char *filename, size_t filename_size); -int -ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size, - size_t *packet_size, - struct ecryptfs_mount_crypt_stat *mount_crypt_stat, - char *data, size_t max_packet_size); -int ecryptfs_set_f_namelen(long *namelen, long lower_namelen, - struct ecryptfs_mount_crypt_stat *mount_crypt_stat); -int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat, - loff_t offset); - -#endif /* #ifndef ECRYPTFS_KERNEL_H */ diff --git a/ANDROID_3.4.5/fs/ecryptfs/file.c b/ANDROID_3.4.5/fs/ecryptfs/file.c deleted file mode 100644 index 2b17f2f9..00000000 --- a/ANDROID_3.4.5/fs/ecryptfs/file.c +++ /dev/null @@ -1,379 +0,0 @@ -/** - * eCryptfs: Linux filesystem encryption layer - * - * Copyright (C) 1997-2004 Erez Zadok - * Copyright (C) 2001-2004 Stony Brook University - * Copyright (C) 2004-2007 International Business Machines Corp. - * Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com> - * Michael C. Thompson <mcthomps@us.ibm.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <linux/file.h> -#include <linux/poll.h> -#include <linux/slab.h> -#include <linux/mount.h> -#include <linux/pagemap.h> -#include <linux/security.h> -#include <linux/compat.h> -#include <linux/fs_stack.h> -#include "ecryptfs_kernel.h" - -/** - * ecryptfs_read_update_atime - * - * generic_file_read updates the atime of upper layer inode. But, it - * doesn't give us a chance to update the atime of the lower layer - * inode. This function is a wrapper to generic_file_read. It - * updates the atime of the lower level inode if generic_file_read - * returns without any errors. This is to be used only for file reads. - * The function to be used for directory reads is ecryptfs_read. - */ -static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb, - const struct iovec *iov, - unsigned long nr_segs, loff_t pos) -{ - ssize_t rc; - struct path lower; - struct file *file = iocb->ki_filp; - - rc = generic_file_aio_read(iocb, iov, nr_segs, pos); - /* - * Even though this is a async interface, we need to wait - * for IO to finish to update atime - */ - if (-EIOCBQUEUED == rc) - rc = wait_on_sync_kiocb(iocb); - if (rc >= 0) { - lower.dentry = ecryptfs_dentry_to_lower(file->f_path.dentry); - lower.mnt = ecryptfs_dentry_to_lower_mnt(file->f_path.dentry); - touch_atime(&lower); - } - return rc; -} - -struct ecryptfs_getdents_callback { - void *dirent; - struct dentry *dentry; - filldir_t filldir; - int filldir_called; - int entries_written; -}; - -/* Inspired by generic filldir in fs/readdir.c */ -static int -ecryptfs_filldir(void *dirent, const char *lower_name, int lower_namelen, - loff_t offset, u64 ino, unsigned int d_type) -{ - struct ecryptfs_getdents_callback *buf = - (struct ecryptfs_getdents_callback *)dirent; - size_t name_size; - char *name; - int rc; - - buf->filldir_called++; - rc = ecryptfs_decode_and_decrypt_filename(&name, &name_size, - buf->dentry, lower_name, - lower_namelen); - if (rc) { - printk(KERN_ERR "%s: Error attempting to decode and decrypt " - "filename [%s]; rc = [%d]\n", __func__, lower_name, - rc); - goto out; - } - rc = buf->filldir(buf->dirent, name, name_size, offset, ino, d_type); - kfree(name); - if (rc >= 0) - buf->entries_written++; -out: - return rc; -} - -/** - * ecryptfs_readdir - * @file: The eCryptfs directory file - * @dirent: Directory entry handle - * @filldir: The filldir callback function - */ -static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir) -{ - int rc; - struct file *lower_file; - struct inode *inode; - struct ecryptfs_getdents_callback buf; - - lower_file = ecryptfs_file_to_lower(file); - lower_file->f_pos = file->f_pos; - inode = file->f_path.dentry->d_inode; - memset(&buf, 0, sizeof(buf)); - buf.dirent = dirent; - buf.dentry = file->f_path.dentry; - buf.filldir = filldir; - buf.filldir_called = 0; - buf.entries_written = 0; - rc = vfs_readdir(lower_file, ecryptfs_filldir, (void *)&buf); - file->f_pos = lower_file->f_pos; - if (rc < 0) - goto out; - if (buf.filldir_called && !buf.entries_written) - goto out; - if (rc >= 0) - fsstack_copy_attr_atime(inode, - lower_file->f_path.dentry->d_inode); -out: - return rc; -} - -static void ecryptfs_vma_close(struct vm_area_struct *vma) -{ - filemap_write_and_wait(vma->vm_file->f_mapping); -} - -static const struct vm_operations_struct ecryptfs_file_vm_ops = { - .close = ecryptfs_vma_close, - .fault = filemap_fault, -}; - -static int ecryptfs_file_mmap(struct file *file, struct vm_area_struct *vma) -{ - int rc; - - rc = generic_file_mmap(file, vma); - if (!rc) - vma->vm_ops = &ecryptfs_file_vm_ops; - - return rc; -} - -struct kmem_cache *ecryptfs_file_info_cache; - -/** - * ecryptfs_open - * @inode: inode speciying file to open - * @file: Structure to return filled in - * - * Opens the file specified by inode. - * - * Returns zero on success; non-zero otherwise - */ -static int ecryptfs_open(struct inode *inode, struct file *file) -{ - int rc = 0; - struct ecryptfs_crypt_stat *crypt_stat = NULL; - struct ecryptfs_mount_crypt_stat *mount_crypt_stat; - struct dentry *ecryptfs_dentry = file->f_path.dentry; - /* Private value of ecryptfs_dentry allocated in - * ecryptfs_lookup() */ - struct dentry *lower_dentry; - struct ecryptfs_file_info *file_info; - - mount_crypt_stat = &ecryptfs_superblock_to_private( - ecryptfs_dentry->d_sb)->mount_crypt_stat; - if ((mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) - && ((file->f_flags & O_WRONLY) || (file->f_flags & O_RDWR) - || (file->f_flags & O_CREAT) || (file->f_flags & O_TRUNC) - || (file->f_flags & O_APPEND))) { - printk(KERN_WARNING "Mount has encrypted view enabled; " - "files may only be read\n"); - rc = -EPERM; - goto out; - } - /* Released in ecryptfs_release or end of function if failure */ - file_info = kmem_cache_zalloc(ecryptfs_file_info_cache, GFP_KERNEL); - ecryptfs_set_file_private(file, file_info); - if (!file_info) { - ecryptfs_printk(KERN_ERR, - "Error attempting to allocate memory\n"); - rc = -ENOMEM; - goto out; - } - lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); - crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; - mutex_lock(&crypt_stat->cs_mutex); - if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)) { - ecryptfs_printk(KERN_DEBUG, "Setting flags for stat...\n"); - /* Policy code enabled in future release */ - crypt_stat->flags |= (ECRYPTFS_POLICY_APPLIED - | ECRYPTFS_ENCRYPTED); - } - mutex_unlock(&crypt_stat->cs_mutex); - rc = ecryptfs_get_lower_file(ecryptfs_dentry, inode); - if (rc) { - printk(KERN_ERR "%s: Error attempting to initialize " - "the lower file for the dentry with name " - "[%s]; rc = [%d]\n", __func__, - ecryptfs_dentry->d_name.name, rc); - goto out_free; - } - if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_ACCMODE) - == O_RDONLY && (file->f_flags & O_ACCMODE) != O_RDONLY) { - rc = -EPERM; - printk(KERN_WARNING "%s: Lower file is RO; eCryptfs " - "file must hence be opened RO\n", __func__); - goto out_put; - } - ecryptfs_set_file_lower( - file, ecryptfs_inode_to_private(inode)->lower_file); - if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { - ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); - mutex_lock(&crypt_stat->cs_mutex); - crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); - mutex_unlock(&crypt_stat->cs_mutex); - rc = 0; - goto out; - } - mutex_lock(&crypt_stat->cs_mutex); - if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED) - || !(crypt_stat->flags & ECRYPTFS_KEY_VALID)) { - rc = ecryptfs_read_metadata(ecryptfs_dentry); - if (rc) { - ecryptfs_printk(KERN_DEBUG, - "Valid headers not found\n"); - if (!(mount_crypt_stat->flags - & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { - rc = -EIO; - printk(KERN_WARNING "Either the lower file " - "is not in a valid eCryptfs format, " - "or the key could not be retrieved. " - "Plaintext passthrough mode is not " - "enabled; returning -EIO\n"); - mutex_unlock(&crypt_stat->cs_mutex); - goto out_put; - } - rc = 0; - crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED - | ECRYPTFS_ENCRYPTED); - mutex_unlock(&crypt_stat->cs_mutex); - goto out; - } - } - mutex_unlock(&crypt_stat->cs_mutex); - ecryptfs_printk(KERN_DEBUG, "inode w/ addr = [0x%p], i_ino = " - "[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino, - (unsigned long long)i_size_read(inode)); - goto out; -out_put: - ecryptfs_put_lower_file(inode); -out_free: - kmem_cache_free(ecryptfs_file_info_cache, - ecryptfs_file_to_private(file)); -out: - return rc; -} - -static int ecryptfs_flush(struct file *file, fl_owner_t td) -{ - return file->f_mode & FMODE_WRITE - ? filemap_write_and_wait(file->f_mapping) : 0; -} - -static int ecryptfs_release(struct inode *inode, struct file *file) -{ - ecryptfs_put_lower_file(inode); - kmem_cache_free(ecryptfs_file_info_cache, - ecryptfs_file_to_private(file)); - return 0; -} - -static int -ecryptfs_fsync(struct file *file, loff_t start, loff_t end, int datasync) -{ - int rc = 0; - - rc = generic_file_fsync(file, start, end, datasync); - if (rc) - goto out; - rc = vfs_fsync_range(ecryptfs_file_to_lower(file), start, end, - datasync); -out: - return rc; -} - -static int ecryptfs_fasync(int fd, struct file *file, int flag) -{ - int rc = 0; - struct file *lower_file = NULL; - - lower_file = ecryptfs_file_to_lower(file); - if (lower_file->f_op && lower_file->f_op->fasync) - rc = lower_file->f_op->fasync(fd, lower_file, flag); - return rc; -} - -static long -ecryptfs_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct file *lower_file = NULL; - long rc = -ENOTTY; - - 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) - rc = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg); - return rc; -} - -#ifdef CONFIG_COMPAT -static long -ecryptfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct file *lower_file = NULL; - long rc = -ENOIOCTLCMD; - - if (ecryptfs_file_to_private(file)) - lower_file = ecryptfs_file_to_lower(file); - if (lower_file && lower_file->f_op && lower_file->f_op->compat_ioctl) - rc = lower_file->f_op->compat_ioctl(lower_file, cmd, arg); - return rc; -} -#endif - -const struct file_operations ecryptfs_dir_fops = { - .readdir = ecryptfs_readdir, - .read = generic_read_dir, - .unlocked_ioctl = ecryptfs_unlocked_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = ecryptfs_compat_ioctl, -#endif - .open = ecryptfs_open, - .flush = ecryptfs_flush, - .release = ecryptfs_release, - .fsync = ecryptfs_fsync, - .fasync = ecryptfs_fasync, - .splice_read = generic_file_splice_read, - .llseek = default_llseek, -}; - -const struct file_operations ecryptfs_main_fops = { - .llseek = generic_file_llseek, - .read = do_sync_read, - .aio_read = ecryptfs_read_update_atime, - .write = do_sync_write, - .aio_write = generic_file_aio_write, - .readdir = ecryptfs_readdir, - .unlocked_ioctl = ecryptfs_unlocked_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = ecryptfs_compat_ioctl, -#endif - .mmap = ecryptfs_file_mmap, - .open = ecryptfs_open, - .flush = ecryptfs_flush, - .release = ecryptfs_release, - .fsync = ecryptfs_fsync, - .fasync = ecryptfs_fasync, - .splice_read = generic_file_splice_read, -}; diff --git a/ANDROID_3.4.5/fs/ecryptfs/inode.c b/ANDROID_3.4.5/fs/ecryptfs/inode.c deleted file mode 100644 index ab35b113..00000000 --- a/ANDROID_3.4.5/fs/ecryptfs/inode.c +++ /dev/null @@ -1,1194 +0,0 @@ -/** - * eCryptfs: Linux filesystem encryption layer - * - * Copyright (C) 1997-2004 Erez Zadok - * Copyright (C) 2001-2004 Stony Brook University - * Copyright (C) 2004-2007 International Business Machines Corp. - * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> - * Michael C. Thompsion <mcthomps@us.ibm.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <linux/file.h> -#include <linux/vmalloc.h> -#include <linux/pagemap.h> -#include <linux/dcache.h> -#include <linux/namei.h> -#include <linux/mount.h> -#include <linux/crypto.h> -#include <linux/fs_stack.h> -#include <linux/slab.h> -#include <linux/xattr.h> -#include <asm/unaligned.h> -#include "ecryptfs_kernel.h" - -static struct dentry *lock_parent(struct dentry *dentry) -{ - struct dentry *dir; - - dir = dget_parent(dentry); - mutex_lock_nested(&(dir->d_inode->i_mutex), I_MUTEX_PARENT); - return dir; -} - -static void unlock_dir(struct dentry *dir) -{ - mutex_unlock(&dir->d_inode->i_mutex); - dput(dir); -} - -static int ecryptfs_inode_test(struct inode *inode, void *lower_inode) -{ - if (ecryptfs_inode_to_lower(inode) == (struct inode *)lower_inode) - return 1; - return 0; -} - -static int ecryptfs_inode_set(struct inode *inode, void *opaque) -{ - struct inode *lower_inode = opaque; - - ecryptfs_set_inode_lower(inode, lower_inode); - fsstack_copy_attr_all(inode, lower_inode); - /* i_size will be overwritten for encrypted regular files */ - fsstack_copy_inode_size(inode, lower_inode); - inode->i_ino = lower_inode->i_ino; - inode->i_version++; - inode->i_mapping->a_ops = &ecryptfs_aops; - inode->i_mapping->backing_dev_info = inode->i_sb->s_bdi; - - if (S_ISLNK(inode->i_mode)) - inode->i_op = &ecryptfs_symlink_iops; - else if (S_ISDIR(inode->i_mode)) - inode->i_op = &ecryptfs_dir_iops; - else - inode->i_op = &ecryptfs_main_iops; - - if (S_ISDIR(inode->i_mode)) - inode->i_fop = &ecryptfs_dir_fops; - else if (special_file(inode->i_mode)) - init_special_inode(inode, inode->i_mode, inode->i_rdev); - else - inode->i_fop = &ecryptfs_main_fops; - - return 0; -} - -static struct inode *__ecryptfs_get_inode(struct inode *lower_inode, - struct super_block *sb) -{ - struct inode *inode; - - if (lower_inode->i_sb != ecryptfs_superblock_to_lower(sb)) - return ERR_PTR(-EXDEV); - if (!igrab(lower_inode)) - return ERR_PTR(-ESTALE); - inode = iget5_locked(sb, (unsigned long)lower_inode, - ecryptfs_inode_test, ecryptfs_inode_set, - lower_inode); - if (!inode) { - iput(lower_inode); - return ERR_PTR(-EACCES); - } - if (!(inode->i_state & I_NEW)) - iput(lower_inode); - - return inode; -} - -struct inode *ecryptfs_get_inode(struct inode *lower_inode, - struct super_block *sb) -{ - struct inode *inode = __ecryptfs_get_inode(lower_inode, sb); - - if (!IS_ERR(inode) && (inode->i_state & I_NEW)) - unlock_new_inode(inode); - - return inode; -} - -/** - * ecryptfs_interpose - * @lower_dentry: Existing dentry in the lower filesystem - * @dentry: ecryptfs' dentry - * @sb: ecryptfs's super_block - * - * Interposes upper and lower dentries. - * - * Returns zero on success; non-zero otherwise - */ -static int ecryptfs_interpose(struct dentry *lower_dentry, - struct dentry *dentry, struct super_block *sb) -{ - struct inode *inode = ecryptfs_get_inode(lower_dentry->d_inode, sb); - - if (IS_ERR(inode)) - return PTR_ERR(inode); - d_instantiate(dentry, inode); - - return 0; -} - -/** - * ecryptfs_do_create - * @directory_inode: inode of the new file's dentry's parent in ecryptfs - * @ecryptfs_dentry: New file's dentry in ecryptfs - * @mode: The mode of the new file - * @nd: nameidata of ecryptfs' parent's dentry & vfsmount - * - * Creates the underlying file and the eCryptfs inode which will link to - * it. It will also update the eCryptfs directory inode to mimic the - * stat of the lower directory inode. - * - * Returns the new eCryptfs inode on success; an ERR_PTR on error condition - */ -static struct inode * -ecryptfs_do_create(struct inode *directory_inode, - struct dentry *ecryptfs_dentry, umode_t mode) -{ - int rc; - struct dentry *lower_dentry; - struct dentry *lower_dir_dentry; - struct inode *inode; - - lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); - lower_dir_dentry = lock_parent(lower_dentry); - if (IS_ERR(lower_dir_dentry)) { - ecryptfs_printk(KERN_ERR, "Error locking directory of " - "dentry\n"); - inode = ERR_CAST(lower_dir_dentry); - goto out; - } - rc = vfs_create(lower_dir_dentry->d_inode, lower_dentry, mode, NULL); - if (rc) { - printk(KERN_ERR "%s: Failure to create dentry in lower fs; " - "rc = [%d]\n", __func__, rc); - inode = ERR_PTR(rc); - goto out_lock; - } - inode = __ecryptfs_get_inode(lower_dentry->d_inode, - directory_inode->i_sb); - if (IS_ERR(inode)) - goto out_lock; - fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode); - fsstack_copy_inode_size(directory_inode, lower_dir_dentry->d_inode); -out_lock: - unlock_dir(lower_dir_dentry); -out: - return inode; -} - -/** - * ecryptfs_initialize_file - * - * Cause the file to be changed from a basic empty file to an ecryptfs - * file with a header and first data page. - * - * Returns zero on success - */ -static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry, - struct inode *ecryptfs_inode) -{ - struct ecryptfs_crypt_stat *crypt_stat = - &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; - int rc = 0; - - if (S_ISDIR(ecryptfs_inode->i_mode)) { - ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); - crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); - goto out; - } - ecryptfs_printk(KERN_DEBUG, "Initializing crypto context\n"); - rc = ecryptfs_new_file_context(ecryptfs_inode); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error creating new file " - "context; rc = [%d]\n", rc); - goto out; - } - rc = ecryptfs_get_lower_file(ecryptfs_dentry, ecryptfs_inode); - if (rc) { - printk(KERN_ERR "%s: Error attempting to initialize " - "the lower file for the dentry with name " - "[%s]; rc = [%d]\n", __func__, - ecryptfs_dentry->d_name.name, rc); - goto out; - } - rc = ecryptfs_write_metadata(ecryptfs_dentry, ecryptfs_inode); - if (rc) - printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc); - ecryptfs_put_lower_file(ecryptfs_inode); -out: - return rc; -} - -/** - * ecryptfs_create - * @dir: The inode of the directory in which to create the file. - * @dentry: The eCryptfs dentry - * @mode: The mode of the new file. - * @nd: nameidata - * - * Creates a new file. - * - * Returns zero on success; non-zero on error condition - */ -static int -ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry, - umode_t mode, struct nameidata *nd) -{ - struct inode *ecryptfs_inode; - int rc; - - ecryptfs_inode = ecryptfs_do_create(directory_inode, ecryptfs_dentry, - mode); - if (unlikely(IS_ERR(ecryptfs_inode))) { - ecryptfs_printk(KERN_WARNING, "Failed to create file in" - "lower filesystem\n"); - rc = PTR_ERR(ecryptfs_inode); - goto out; - } - /* At this point, a file exists on "disk"; we need to make sure - * that this on disk file is prepared to be an ecryptfs file */ - rc = ecryptfs_initialize_file(ecryptfs_dentry, ecryptfs_inode); - if (rc) { - drop_nlink(ecryptfs_inode); - unlock_new_inode(ecryptfs_inode); - iput(ecryptfs_inode); - goto out; - } - d_instantiate(ecryptfs_dentry, ecryptfs_inode); - unlock_new_inode(ecryptfs_inode); -out: - return rc; -} - -static int ecryptfs_i_size_read(struct dentry *dentry, struct inode *inode) -{ - struct ecryptfs_crypt_stat *crypt_stat; - int rc; - - rc = ecryptfs_get_lower_file(dentry, inode); - if (rc) { - printk(KERN_ERR "%s: Error attempting to initialize " - "the lower file for the dentry with name " - "[%s]; rc = [%d]\n", __func__, - dentry->d_name.name, rc); - return rc; - } - - crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; - /* TODO: lock for crypt_stat comparison */ - if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)) - ecryptfs_set_default_sizes(crypt_stat); - - rc = ecryptfs_read_and_validate_header_region(inode); - ecryptfs_put_lower_file(inode); - if (rc) { - rc = ecryptfs_read_and_validate_xattr_region(dentry, inode); - if (!rc) - crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; - } - - /* Must return 0 to allow non-eCryptfs files to be looked up, too */ - return 0; -} - -/** - * ecryptfs_lookup_interpose - Dentry interposition for a lookup - */ -static int ecryptfs_lookup_interpose(struct dentry *dentry, - struct dentry *lower_dentry, - struct inode *dir_inode) -{ - struct inode *inode, *lower_inode = lower_dentry->d_inode; - struct ecryptfs_dentry_info *dentry_info; - struct vfsmount *lower_mnt; - int rc = 0; - - lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent)); - fsstack_copy_attr_atime(dir_inode, lower_dentry->d_parent->d_inode); - BUG_ON(!lower_dentry->d_count); - - dentry_info = kmem_cache_alloc(ecryptfs_dentry_info_cache, GFP_KERNEL); - ecryptfs_set_dentry_private(dentry, dentry_info); - if (!dentry_info) { - printk(KERN_ERR "%s: Out of memory whilst attempting " - "to allocate ecryptfs_dentry_info struct\n", - __func__); - dput(lower_dentry); - mntput(lower_mnt); - d_drop(dentry); - return -ENOMEM; - } - ecryptfs_set_dentry_lower(dentry, lower_dentry); - ecryptfs_set_dentry_lower_mnt(dentry, lower_mnt); - - if (!lower_dentry->d_inode) { - /* We want to add because we couldn't find in lower */ - d_add(dentry, NULL); - return 0; - } - inode = __ecryptfs_get_inode(lower_inode, dir_inode->i_sb); - if (IS_ERR(inode)) { - printk(KERN_ERR "%s: Error interposing; rc = [%ld]\n", - __func__, PTR_ERR(inode)); - return PTR_ERR(inode); - } - if (S_ISREG(inode->i_mode)) { - rc = ecryptfs_i_size_read(dentry, inode); - if (rc) { - make_bad_inode(inode); - return rc; - } - } - - if (inode->i_state & I_NEW) - unlock_new_inode(inode); - d_add(dentry, inode); - - return rc; -} - -/** - * ecryptfs_lookup - * @ecryptfs_dir_inode: The eCryptfs directory inode - * @ecryptfs_dentry: The eCryptfs dentry that we are looking up - * @ecryptfs_nd: nameidata; may be NULL - * - * Find a file on disk. If the file does not exist, then we'll add it to the - * dentry cache and continue on to read it from the disk. - */ -static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, - struct dentry *ecryptfs_dentry, - struct nameidata *ecryptfs_nd) -{ - char *encrypted_and_encoded_name = NULL; - size_t encrypted_and_encoded_name_size; - struct ecryptfs_mount_crypt_stat *mount_crypt_stat = NULL; - struct dentry *lower_dir_dentry, *lower_dentry; - int rc = 0; - - if ((ecryptfs_dentry->d_name.len == 1 - && !strcmp(ecryptfs_dentry->d_name.name, ".")) - || (ecryptfs_dentry->d_name.len == 2 - && !strcmp(ecryptfs_dentry->d_name.name, ".."))) { - goto out_d_drop; - } - lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent); - mutex_lock(&lower_dir_dentry->d_inode->i_mutex); - lower_dentry = lookup_one_len(ecryptfs_dentry->d_name.name, - lower_dir_dentry, - ecryptfs_dentry->d_name.len); - mutex_unlock(&lower_dir_dentry->d_inode->i_mutex); - if (IS_ERR(lower_dentry)) { - rc = PTR_ERR(lower_dentry); - ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " - "[%d] on lower_dentry = [%s]\n", __func__, rc, - encrypted_and_encoded_name); - goto out_d_drop; - } - if (lower_dentry->d_inode) - goto interpose; - mount_crypt_stat = &ecryptfs_superblock_to_private( - ecryptfs_dentry->d_sb)->mount_crypt_stat; - if (!(mount_crypt_stat - && (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES))) - goto interpose; - dput(lower_dentry); - rc = ecryptfs_encrypt_and_encode_filename( - &encrypted_and_encoded_name, &encrypted_and_encoded_name_size, - NULL, mount_crypt_stat, ecryptfs_dentry->d_name.name, - ecryptfs_dentry->d_name.len); - if (rc) { - printk(KERN_ERR "%s: Error attempting to encrypt and encode " - "filename; rc = [%d]\n", __func__, rc); - goto out_d_drop; - } - mutex_lock(&lower_dir_dentry->d_inode->i_mutex); - lower_dentry = lookup_one_len(encrypted_and_encoded_name, - lower_dir_dentry, - encrypted_and_encoded_name_size); - mutex_unlock(&lower_dir_dentry->d_inode->i_mutex); - if (IS_ERR(lower_dentry)) { - rc = PTR_ERR(lower_dentry); - ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " - "[%d] on lower_dentry = [%s]\n", __func__, rc, - encrypted_and_encoded_name); - goto out_d_drop; - } -interpose: - rc = ecryptfs_lookup_interpose(ecryptfs_dentry, lower_dentry, - ecryptfs_dir_inode); - goto out; -out_d_drop: - d_drop(ecryptfs_dentry); -out: - kfree(encrypted_and_encoded_name); - return ERR_PTR(rc); -} - -static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir, - struct dentry *new_dentry) -{ - struct dentry *lower_old_dentry; - struct dentry *lower_new_dentry; - struct dentry *lower_dir_dentry; - u64 file_size_save; - int rc; - - file_size_save = i_size_read(old_dentry->d_inode); - lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry); - lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry); - dget(lower_old_dentry); - dget(lower_new_dentry); - lower_dir_dentry = lock_parent(lower_new_dentry); - rc = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode, - lower_new_dentry); - if (rc || !lower_new_dentry->d_inode) - goto out_lock; - rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb); - if (rc) - goto out_lock; - fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); - fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode); - set_nlink(old_dentry->d_inode, - ecryptfs_inode_to_lower(old_dentry->d_inode)->i_nlink); - i_size_write(new_dentry->d_inode, file_size_save); -out_lock: - unlock_dir(lower_dir_dentry); - dput(lower_new_dentry); - dput(lower_old_dentry); - return rc; -} - -static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry) -{ - int rc = 0; - struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); - struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir); - struct dentry *lower_dir_dentry; - - dget(lower_dentry); - lower_dir_dentry = lock_parent(lower_dentry); - rc = vfs_unlink(lower_dir_inode, lower_dentry); - if (rc) { - printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc); - goto out_unlock; - } - fsstack_copy_attr_times(dir, lower_dir_inode); - set_nlink(dentry->d_inode, - ecryptfs_inode_to_lower(dentry->d_inode)->i_nlink); - dentry->d_inode->i_ctime = dir->i_ctime; - d_drop(dentry); -out_unlock: - unlock_dir(lower_dir_dentry); - dput(lower_dentry); - return rc; -} - -static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry, - const char *symname) -{ - int rc; - struct dentry *lower_dentry; - struct dentry *lower_dir_dentry; - char *encoded_symname; - size_t encoded_symlen; - struct ecryptfs_mount_crypt_stat *mount_crypt_stat = NULL; - - lower_dentry = ecryptfs_dentry_to_lower(dentry); - dget(lower_dentry); - lower_dir_dentry = lock_parent(lower_dentry); - mount_crypt_stat = &ecryptfs_superblock_to_private( - dir->i_sb)->mount_crypt_stat; - rc = ecryptfs_encrypt_and_encode_filename(&encoded_symname, - &encoded_symlen, - NULL, - mount_crypt_stat, symname, - strlen(symname)); - if (rc) - goto out_lock; - rc = vfs_symlink(lower_dir_dentry->d_inode, lower_dentry, - encoded_symname); - kfree(encoded_symname); - if (rc || !lower_dentry->d_inode) - goto out_lock; - rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb); - if (rc) - goto out_lock; - fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); - fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode); -out_lock: - unlock_dir(lower_dir_dentry); - dput(lower_dentry); - if (!dentry->d_inode) - d_drop(dentry); - return rc; -} - -static int ecryptfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) -{ - int rc; - struct dentry *lower_dentry; - struct dentry *lower_dir_dentry; - - lower_dentry = ecryptfs_dentry_to_lower(dentry); - lower_dir_dentry = lock_parent(lower_dentry); - rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, mode); - if (rc || !lower_dentry->d_inode) - goto out; - rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb); - if (rc) - goto out; - fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); - fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode); - set_nlink(dir, lower_dir_dentry->d_inode->i_nlink); -out: - unlock_dir(lower_dir_dentry); - if (!dentry->d_inode) - d_drop(dentry); - return rc; -} - -static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) -{ - struct dentry *lower_dentry; - struct dentry *lower_dir_dentry; - int rc; - - lower_dentry = ecryptfs_dentry_to_lower(dentry); - dget(dentry); - lower_dir_dentry = lock_parent(lower_dentry); - dget(lower_dentry); - rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); - dput(lower_dentry); - if (!rc && dentry->d_inode) - clear_nlink(dentry->d_inode); - fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); - set_nlink(dir, lower_dir_dentry->d_inode->i_nlink); - unlock_dir(lower_dir_dentry); - if (!rc) - d_drop(dentry); - dput(dentry); - return rc; -} - -static int -ecryptfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) -{ - int rc; - struct dentry *lower_dentry; - struct dentry *lower_dir_dentry; - - lower_dentry = ecryptfs_dentry_to_lower(dentry); - lower_dir_dentry = lock_parent(lower_dentry); - rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, mode, dev); - if (rc || !lower_dentry->d_inode) - goto out; - rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb); - if (rc) - goto out; - fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); - fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode); -out: - unlock_dir(lower_dir_dentry); - if (!dentry->d_inode) - d_drop(dentry); - return rc; -} - -static int -ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry) -{ - int rc; - struct dentry *lower_old_dentry; - struct dentry *lower_new_dentry; - struct dentry *lower_old_dir_dentry; - struct dentry *lower_new_dir_dentry; - struct dentry *trap = NULL; - - lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry); - lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry); - dget(lower_old_dentry); - dget(lower_new_dentry); - lower_old_dir_dentry = dget_parent(lower_old_dentry); - lower_new_dir_dentry = dget_parent(lower_new_dentry); - trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry); - /* source should not be ancestor of target */ - if (trap == lower_old_dentry) { - rc = -EINVAL; - goto out_lock; - } - /* target should not be ancestor of source */ - if (trap == lower_new_dentry) { - rc = -ENOTEMPTY; - goto out_lock; - } - rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry, - lower_new_dir_dentry->d_inode, lower_new_dentry); - if (rc) - goto out_lock; - fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode); - if (new_dir != old_dir) - fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode); -out_lock: - unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry); - dput(lower_new_dir_dentry); - dput(lower_old_dir_dentry); - dput(lower_new_dentry); - dput(lower_old_dentry); - return rc; -} - -static int ecryptfs_readlink_lower(struct dentry *dentry, char **buf, - size_t *bufsiz) -{ - struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); - char *lower_buf; - size_t lower_bufsiz = PATH_MAX; - mm_segment_t old_fs; - int rc; - - lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL); - if (!lower_buf) { - rc = -ENOMEM; - goto out; - } - old_fs = get_fs(); - set_fs(get_ds()); - rc = lower_dentry->d_inode->i_op->readlink(lower_dentry, - (char __user *)lower_buf, - lower_bufsiz); - set_fs(old_fs); - if (rc < 0) - goto out; - lower_bufsiz = rc; - rc = ecryptfs_decode_and_decrypt_filename(buf, bufsiz, dentry, - lower_buf, lower_bufsiz); -out: - kfree(lower_buf); - return rc; -} - -static int -ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) -{ - char *kbuf; - size_t kbufsiz, copied; - int rc; - - rc = ecryptfs_readlink_lower(dentry, &kbuf, &kbufsiz); - if (rc) - goto out; - copied = min_t(size_t, bufsiz, kbufsiz); - rc = copy_to_user(buf, kbuf, copied) ? -EFAULT : copied; - kfree(kbuf); - fsstack_copy_attr_atime(dentry->d_inode, - ecryptfs_dentry_to_lower(dentry)->d_inode); -out: - return rc; -} - -static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd) -{ - char *buf; - int len = PAGE_SIZE, rc; - mm_segment_t old_fs; - - /* Released in ecryptfs_put_link(); only release here on error */ - buf = kmalloc(len, GFP_KERNEL); - if (!buf) { - buf = ERR_PTR(-ENOMEM); - goto out; - } - old_fs = get_fs(); - set_fs(get_ds()); - rc = dentry->d_inode->i_op->readlink(dentry, (char __user *)buf, len); - set_fs(old_fs); - if (rc < 0) { - kfree(buf); - buf = ERR_PTR(rc); - } else - buf[rc] = '\0'; -out: - nd_set_link(nd, buf); - return NULL; -} - -static void -ecryptfs_put_link(struct dentry *dentry, struct nameidata *nd, void *ptr) -{ - char *buf = nd_get_link(nd); - if (!IS_ERR(buf)) { - /* Free the char* */ - kfree(buf); - } -} - -/** - * upper_size_to_lower_size - * @crypt_stat: Crypt_stat associated with file - * @upper_size: Size of the upper file - * - * Calculate the required size of the lower file based on the - * specified size of the upper file. This calculation is based on the - * number of headers in the underlying file and the extent size. - * - * Returns Calculated size of the lower file. - */ -static loff_t -upper_size_to_lower_size(struct ecryptfs_crypt_stat *crypt_stat, - loff_t upper_size) -{ - loff_t lower_size; - - lower_size = ecryptfs_lower_header_size(crypt_stat); - if (upper_size != 0) { - loff_t num_extents; - - num_extents = upper_size >> crypt_stat->extent_shift; - if (upper_size & ~crypt_stat->extent_mask) - num_extents++; - lower_size += (num_extents * crypt_stat->extent_size); - } - return lower_size; -} - -/** - * truncate_upper - * @dentry: The ecryptfs layer dentry - * @ia: Address of the ecryptfs inode's attributes - * @lower_ia: Address of the lower inode's attributes - * - * Function to handle truncations modifying the size of the file. Note - * that the file sizes are interpolated. When expanding, we are simply - * writing strings of 0's out. When truncating, we truncate the upper - * inode and update the lower_ia according to the page index - * interpolations. If ATTR_SIZE is set in lower_ia->ia_valid upon return, - * the caller must use lower_ia in a call to notify_change() to perform - * the truncation of the lower inode. - * - * Returns zero on success; non-zero otherwise - */ -static int truncate_upper(struct dentry *dentry, struct iattr *ia, - struct iattr *lower_ia) -{ - int rc = 0; - struct inode *inode = dentry->d_inode; - struct ecryptfs_crypt_stat *crypt_stat; - loff_t i_size = i_size_read(inode); - loff_t lower_size_before_truncate; - loff_t lower_size_after_truncate; - - if (unlikely((ia->ia_size == i_size))) { - lower_ia->ia_valid &= ~ATTR_SIZE; - return 0; - } - rc = ecryptfs_get_lower_file(dentry, inode); - if (rc) - return rc; - crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; - /* Switch on growing or shrinking file */ - if (ia->ia_size > i_size) { - char zero[] = { 0x00 }; - - lower_ia->ia_valid &= ~ATTR_SIZE; - /* Write a single 0 at the last position of the file; - * this triggers code that will fill in 0's throughout - * the intermediate portion of the previous end of the - * file and the new and of the file */ - rc = ecryptfs_write(inode, zero, - (ia->ia_size - 1), 1); - } else { /* ia->ia_size < i_size_read(inode) */ - /* We're chopping off all the pages down to the page - * in which ia->ia_size is located. Fill in the end of - * that page from (ia->ia_size & ~PAGE_CACHE_MASK) to - * PAGE_CACHE_SIZE with zeros. */ - size_t num_zeros = (PAGE_CACHE_SIZE - - (ia->ia_size & ~PAGE_CACHE_MASK)); - - if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { - truncate_setsize(inode, ia->ia_size); - lower_ia->ia_size = ia->ia_size; - lower_ia->ia_valid |= ATTR_SIZE; - goto out; - } - if (num_zeros) { - char *zeros_virt; - - zeros_virt = kzalloc(num_zeros, GFP_KERNEL); - if (!zeros_virt) { - rc = -ENOMEM; - goto out; - } - rc = ecryptfs_write(inode, zeros_virt, - ia->ia_size, num_zeros); - kfree(zeros_virt); - if (rc) { - printk(KERN_ERR "Error attempting to zero out " - "the remainder of the end page on " - "reducing truncate; rc = [%d]\n", rc); - goto out; - } - } - truncate_setsize(inode, ia->ia_size); - rc = ecryptfs_write_inode_size_to_metadata(inode); - if (rc) { - printk(KERN_ERR "Problem with " - "ecryptfs_write_inode_size_to_metadata; " - "rc = [%d]\n", rc); - goto out; - } - /* We are reducing the size of the ecryptfs file, and need to - * know if we need to reduce the size of the lower file. */ - lower_size_before_truncate = - upper_size_to_lower_size(crypt_stat, i_size); - lower_size_after_truncate = - upper_size_to_lower_size(crypt_stat, ia->ia_size); - if (lower_size_after_truncate < lower_size_before_truncate) { - lower_ia->ia_size = lower_size_after_truncate; - lower_ia->ia_valid |= ATTR_SIZE; - } else - lower_ia->ia_valid &= ~ATTR_SIZE; - } -out: - ecryptfs_put_lower_file(inode); - return rc; -} - -static int ecryptfs_inode_newsize_ok(struct inode *inode, loff_t offset) -{ - struct ecryptfs_crypt_stat *crypt_stat; - loff_t lower_oldsize, lower_newsize; - - crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; - lower_oldsize = upper_size_to_lower_size(crypt_stat, - i_size_read(inode)); - lower_newsize = upper_size_to_lower_size(crypt_stat, offset); - if (lower_newsize > lower_oldsize) { - /* - * The eCryptfs inode and the new *lower* size are mixed here - * because we may not have the lower i_mutex held and/or it may - * not be appropriate to call inode_newsize_ok() with inodes - * from other filesystems. - */ - return inode_newsize_ok(inode, lower_newsize); - } - - return 0; -} - -/** - * ecryptfs_truncate - * @dentry: The ecryptfs layer dentry - * @new_length: The length to expand the file to - * - * Simple function that handles the truncation of an eCryptfs inode and - * its corresponding lower inode. - * - * Returns zero on success; non-zero otherwise - */ -int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) -{ - struct iattr ia = { .ia_valid = ATTR_SIZE, .ia_size = new_length }; - struct iattr lower_ia = { .ia_valid = 0 }; - int rc; - - rc = ecryptfs_inode_newsize_ok(dentry->d_inode, new_length); - if (rc) - return rc; - - rc = truncate_upper(dentry, &ia, &lower_ia); - if (!rc && lower_ia.ia_valid & ATTR_SIZE) { - struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); - - mutex_lock(&lower_dentry->d_inode->i_mutex); - rc = notify_change(lower_dentry, &lower_ia); - mutex_unlock(&lower_dentry->d_inode->i_mutex); - } - return rc; -} - -static int -ecryptfs_permission(struct inode *inode, int mask) -{ - return inode_permission(ecryptfs_inode_to_lower(inode), mask); -} - -/** - * ecryptfs_setattr - * @dentry: dentry handle to the inode to modify - * @ia: Structure with flags of what to change and values - * - * Updates the metadata of an inode. If the update is to the size - * i.e. truncation, then ecryptfs_truncate will handle the size modification - * of both the ecryptfs inode and the lower inode. - * - * All other metadata changes will be passed right to the lower filesystem, - * and we will just update our inode to look like the lower. - */ -static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) -{ - int rc = 0; - struct dentry *lower_dentry; - struct iattr lower_ia; - struct inode *inode; - struct inode *lower_inode; - struct ecryptfs_crypt_stat *crypt_stat; - - crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; - if (!(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED)) - ecryptfs_init_crypt_stat(crypt_stat); - inode = dentry->d_inode; - lower_inode = ecryptfs_inode_to_lower(inode); - lower_dentry = ecryptfs_dentry_to_lower(dentry); - mutex_lock(&crypt_stat->cs_mutex); - if (S_ISDIR(dentry->d_inode->i_mode)) - crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); - else if (S_ISREG(dentry->d_inode->i_mode) - && (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED) - || !(crypt_stat->flags & ECRYPTFS_KEY_VALID))) { - struct ecryptfs_mount_crypt_stat *mount_crypt_stat; - - mount_crypt_stat = &ecryptfs_superblock_to_private( - dentry->d_sb)->mount_crypt_stat; - rc = ecryptfs_get_lower_file(dentry, inode); - if (rc) { - mutex_unlock(&crypt_stat->cs_mutex); - goto out; - } - rc = ecryptfs_read_metadata(dentry); - ecryptfs_put_lower_file(inode); - if (rc) { - if (!(mount_crypt_stat->flags - & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { - rc = -EIO; - printk(KERN_WARNING "Either the lower file " - "is not in a valid eCryptfs format, " - "or the key could not be retrieved. " - "Plaintext passthrough mode is not " - "enabled; returning -EIO\n"); - mutex_unlock(&crypt_stat->cs_mutex); - goto out; - } - rc = 0; - crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED - | ECRYPTFS_ENCRYPTED); - } - } - mutex_unlock(&crypt_stat->cs_mutex); - - rc = inode_change_ok(inode, ia); - if (rc) - goto out; - if (ia->ia_valid & ATTR_SIZE) { - rc = ecryptfs_inode_newsize_ok(inode, ia->ia_size); - if (rc) - goto out; - } - - if (S_ISREG(inode->i_mode)) { - rc = filemap_write_and_wait(inode->i_mapping); - if (rc) - goto out; - fsstack_copy_attr_all(inode, lower_inode); - } - memcpy(&lower_ia, ia, sizeof(lower_ia)); - if (ia->ia_valid & ATTR_FILE) - lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file); - if (ia->ia_valid & ATTR_SIZE) { - rc = truncate_upper(dentry, ia, &lower_ia); - if (rc < 0) - goto out; - } - - /* - * mode change is for clearing setuid/setgid bits. Allow lower fs - * to interpret this in its own way. - */ - if (lower_ia.ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) - lower_ia.ia_valid &= ~ATTR_MODE; - - mutex_lock(&lower_dentry->d_inode->i_mutex); - rc = notify_change(lower_dentry, &lower_ia); - mutex_unlock(&lower_dentry->d_inode->i_mutex); -out: - fsstack_copy_attr_all(inode, lower_inode); - return rc; -} - -int ecryptfs_getattr_link(struct vfsmount *mnt, struct dentry *dentry, - struct kstat *stat) -{ - struct ecryptfs_mount_crypt_stat *mount_crypt_stat; - int rc = 0; - - mount_crypt_stat = &ecryptfs_superblock_to_private( - dentry->d_sb)->mount_crypt_stat; - generic_fillattr(dentry->d_inode, stat); - if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) { - char *target; - size_t targetsiz; - - rc = ecryptfs_readlink_lower(dentry, &target, &targetsiz); - if (!rc) { - kfree(target); - stat->size = targetsiz; - } - } - return rc; -} - -int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry, - struct kstat *stat) -{ - struct kstat lower_stat; - int rc; - - rc = vfs_getattr(ecryptfs_dentry_to_lower_mnt(dentry), - ecryptfs_dentry_to_lower(dentry), &lower_stat); - if (!rc) { - fsstack_copy_attr_all(dentry->d_inode, - ecryptfs_inode_to_lower(dentry->d_inode)); - generic_fillattr(dentry->d_inode, stat); - stat->blocks = lower_stat.blocks; - } - return rc; -} - -int -ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, - size_t size, int flags) -{ - int rc = 0; - struct dentry *lower_dentry; - - lower_dentry = ecryptfs_dentry_to_lower(dentry); - if (!lower_dentry->d_inode->i_op->setxattr) { - rc = -EOPNOTSUPP; - goto out; - } - - rc = vfs_setxattr(lower_dentry, name, value, size, flags); - if (!rc) - fsstack_copy_attr_all(dentry->d_inode, lower_dentry->d_inode); -out: - return rc; -} - -ssize_t -ecryptfs_getxattr_lower(struct dentry *lower_dentry, const char *name, - void *value, size_t size) -{ - int rc = 0; - - if (!lower_dentry->d_inode->i_op->getxattr) { - rc = -EOPNOTSUPP; - goto out; - } - mutex_lock(&lower_dentry->d_inode->i_mutex); - rc = lower_dentry->d_inode->i_op->getxattr(lower_dentry, name, value, - size); - mutex_unlock(&lower_dentry->d_inode->i_mutex); -out: - return rc; -} - -static ssize_t -ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value, - size_t size) -{ - return ecryptfs_getxattr_lower(ecryptfs_dentry_to_lower(dentry), name, - value, size); -} - -static ssize_t -ecryptfs_listxattr(struct dentry *dentry, char *list, size_t size) -{ - int rc = 0; - struct dentry *lower_dentry; - - lower_dentry = ecryptfs_dentry_to_lower(dentry); - if (!lower_dentry->d_inode->i_op->listxattr) { - rc = -EOPNOTSUPP; - goto out; - } - mutex_lock(&lower_dentry->d_inode->i_mutex); - rc = lower_dentry->d_inode->i_op->listxattr(lower_dentry, list, size); - mutex_unlock(&lower_dentry->d_inode->i_mutex); -out: - return rc; -} - -static int ecryptfs_removexattr(struct dentry *dentry, const char *name) -{ - int rc = 0; - struct dentry *lower_dentry; - - lower_dentry = ecryptfs_dentry_to_lower(dentry); - if (!lower_dentry->d_inode->i_op->removexattr) { - rc = -EOPNOTSUPP; - goto out; - } - mutex_lock(&lower_dentry->d_inode->i_mutex); - rc = lower_dentry->d_inode->i_op->removexattr(lower_dentry, name); - mutex_unlock(&lower_dentry->d_inode->i_mutex); -out: - return rc; -} - -const struct inode_operations ecryptfs_symlink_iops = { - .readlink = ecryptfs_readlink, - .follow_link = ecryptfs_follow_link, - .put_link = ecryptfs_put_link, - .permission = ecryptfs_permission, - .setattr = ecryptfs_setattr, - .getattr = ecryptfs_getattr_link, - .setxattr = ecryptfs_setxattr, - .getxattr = ecryptfs_getxattr, - .listxattr = ecryptfs_listxattr, - .removexattr = ecryptfs_removexattr -}; - -const struct inode_operations ecryptfs_dir_iops = { - .create = ecryptfs_create, - .lookup = ecryptfs_lookup, - .link = ecryptfs_link, - .unlink = ecryptfs_unlink, - .symlink = ecryptfs_symlink, - .mkdir = ecryptfs_mkdir, - .rmdir = ecryptfs_rmdir, - .mknod = ecryptfs_mknod, - .rename = ecryptfs_rename, - .permission = ecryptfs_permission, - .setattr = ecryptfs_setattr, - .setxattr = ecryptfs_setxattr, - .getxattr = ecryptfs_getxattr, - .listxattr = ecryptfs_listxattr, - .removexattr = ecryptfs_removexattr -}; - -const struct inode_operations ecryptfs_main_iops = { - .permission = ecryptfs_permission, - .setattr = ecryptfs_setattr, - .getattr = ecryptfs_getattr, - .setxattr = ecryptfs_setxattr, - .getxattr = ecryptfs_getxattr, - .listxattr = ecryptfs_listxattr, - .removexattr = ecryptfs_removexattr -}; diff --git a/ANDROID_3.4.5/fs/ecryptfs/keystore.c b/ANDROID_3.4.5/fs/ecryptfs/keystore.c deleted file mode 100644 index 2333203a..00000000 --- a/ANDROID_3.4.5/fs/ecryptfs/keystore.c +++ /dev/null @@ -1,2531 +0,0 @@ -/** - * eCryptfs: Linux filesystem encryption layer - * In-kernel key management code. Includes functions to parse and - * write authentication token-related packets with the underlying - * file. - * - * Copyright (C) 2004-2006 International Business Machines Corp. - * Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com> - * Michael C. Thompson <mcthomps@us.ibm.com> - * Trevor S. Highland <trevor.highland@gmail.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <linux/string.h> -#include <linux/syscalls.h> -#include <linux/pagemap.h> -#include <linux/key.h> -#include <linux/random.h> -#include <linux/crypto.h> -#include <linux/scatterlist.h> -#include <linux/slab.h> -#include "ecryptfs_kernel.h" - -/** - * request_key returned an error instead of a valid key address; - * determine the type of error, make appropriate log entries, and - * return an error code. - */ -static int process_request_key_err(long err_code) -{ - int rc = 0; - - switch (err_code) { - case -ENOKEY: - ecryptfs_printk(KERN_WARNING, "No key\n"); - rc = -ENOENT; - break; - case -EKEYEXPIRED: - ecryptfs_printk(KERN_WARNING, "Key expired\n"); - rc = -ETIME; - break; - case -EKEYREVOKED: - ecryptfs_printk(KERN_WARNING, "Key revoked\n"); - rc = -EINVAL; - break; - default: - ecryptfs_printk(KERN_WARNING, "Unknown error code: " - "[0x%.16lx]\n", err_code); - rc = -EINVAL; - } - return rc; -} - -static int process_find_global_auth_tok_for_sig_err(int err_code) -{ - int rc = err_code; - - switch (err_code) { - case -ENOENT: - ecryptfs_printk(KERN_WARNING, "Missing auth tok\n"); - break; - case -EINVAL: - ecryptfs_printk(KERN_WARNING, "Invalid auth tok\n"); - break; - default: - rc = process_request_key_err(err_code); - break; - } - return rc; -} - -/** - * ecryptfs_parse_packet_length - * @data: Pointer to memory containing length at offset - * @size: This function writes the decoded size to this memory - * address; zero on error - * @length_size: The number of bytes occupied by the encoded length - * - * Returns zero on success; non-zero on error - */ -int ecryptfs_parse_packet_length(unsigned char *data, size_t *size, - size_t *length_size) -{ - int rc = 0; - - (*length_size) = 0; - (*size) = 0; - if (data[0] < 192) { - /* One-byte length */ - (*size) = (unsigned char)data[0]; - (*length_size) = 1; - } else if (data[0] < 224) { - /* Two-byte length */ - (*size) = (((unsigned char)(data[0]) - 192) * 256); - (*size) += ((unsigned char)(data[1]) + 192); - (*length_size) = 2; - } else if (data[0] == 255) { - /* If support is added, adjust ECRYPTFS_MAX_PKT_LEN_SIZE */ - ecryptfs_printk(KERN_ERR, "Five-byte packet length not " - "supported\n"); - rc = -EINVAL; - goto out; - } else { - ecryptfs_printk(KERN_ERR, "Error parsing packet length\n"); - rc = -EINVAL; - goto out; - } -out: - return rc; -} - -/** - * ecryptfs_write_packet_length - * @dest: The byte array target into which to write the length. Must - * have at least ECRYPTFS_MAX_PKT_LEN_SIZE bytes allocated. - * @size: The length to write. - * @packet_size_length: The number of bytes used to encode the packet - * length is written to this address. - * - * Returns zero on success; non-zero on error. - */ -int ecryptfs_write_packet_length(char *dest, size_t size, - size_t *packet_size_length) -{ - int rc = 0; - - if (size < 192) { - dest[0] = size; - (*packet_size_length) = 1; - } else if (size < 65536) { - dest[0] = (((size - 192) / 256) + 192); - dest[1] = ((size - 192) % 256); - (*packet_size_length) = 2; - } else { - /* If support is added, adjust ECRYPTFS_MAX_PKT_LEN_SIZE */ - rc = -EINVAL; - ecryptfs_printk(KERN_WARNING, - "Unsupported packet size: [%zd]\n", size); - } - return rc; -} - -static int -write_tag_64_packet(char *signature, struct ecryptfs_session_key *session_key, - char **packet, size_t *packet_len) -{ - size_t i = 0; - size_t data_len; - size_t packet_size_len; - char *message; - int rc; - - /* - * ***** TAG 64 Packet Format ***** - * | Content Type | 1 byte | - * | Key Identifier Size | 1 or 2 bytes | - * | Key Identifier | arbitrary | - * | Encrypted File Encryption Key Size | 1 or 2 bytes | - * | Encrypted File Encryption Key | arbitrary | - */ - data_len = (5 + ECRYPTFS_SIG_SIZE_HEX - + session_key->encrypted_key_size); - *packet = kmalloc(data_len, GFP_KERNEL); - message = *packet; - if (!message) { - ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n"); - rc = -ENOMEM; - goto out; - } - message[i++] = ECRYPTFS_TAG_64_PACKET_TYPE; - rc = ecryptfs_write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX, - &packet_size_len); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error generating tag 64 packet " - "header; cannot generate packet length\n"); - goto out; - } - i += packet_size_len; - memcpy(&message[i], signature, ECRYPTFS_SIG_SIZE_HEX); - i += ECRYPTFS_SIG_SIZE_HEX; - rc = ecryptfs_write_packet_length(&message[i], - session_key->encrypted_key_size, - &packet_size_len); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error generating tag 64 packet " - "header; cannot generate packet length\n"); - goto out; - } - i += packet_size_len; - memcpy(&message[i], session_key->encrypted_key, - session_key->encrypted_key_size); - i += session_key->encrypted_key_size; - *packet_len = i; -out: - return rc; -} - -static int -parse_tag_65_packet(struct ecryptfs_session_key *session_key, u8 *cipher_code, - struct ecryptfs_message *msg) -{ - size_t i = 0; - char *data; - size_t data_len; - size_t m_size; - size_t message_len; - u16 checksum = 0; - u16 expected_checksum = 0; - int rc; - - /* - * ***** TAG 65 Packet Format ***** - * | Content Type | 1 byte | - * | Status Indicator | 1 byte | - * | File Encryption Key Size | 1 or 2 bytes | - * | File Encryption Key | arbitrary | - */ - message_len = msg->data_len; - data = msg->data; - if (message_len < 4) { - rc = -EIO; - goto out; - } - if (data[i++] != ECRYPTFS_TAG_65_PACKET_TYPE) { - ecryptfs_printk(KERN_ERR, "Type should be ECRYPTFS_TAG_65\n"); - rc = -EIO; - goto out; - } - if (data[i++]) { - ecryptfs_printk(KERN_ERR, "Status indicator has non-zero value " - "[%d]\n", data[i-1]); - rc = -EIO; - goto out; - } - rc = ecryptfs_parse_packet_length(&data[i], &m_size, &data_len); - if (rc) { - ecryptfs_printk(KERN_WARNING, "Error parsing packet length; " - "rc = [%d]\n", rc); - goto out; - } - i += data_len; - if (message_len < (i + m_size)) { - ecryptfs_printk(KERN_ERR, "The message received from ecryptfsd " - "is shorter than expected\n"); - rc = -EIO; - goto out; - } - if (m_size < 3) { - ecryptfs_printk(KERN_ERR, - "The decrypted key is not long enough to " - "include a cipher code and checksum\n"); - rc = -EIO; - goto out; - } - *cipher_code = data[i++]; - /* The decrypted key includes 1 byte cipher code and 2 byte checksum */ - session_key->decrypted_key_size = m_size - 3; - if (session_key->decrypted_key_size > ECRYPTFS_MAX_KEY_BYTES) { - ecryptfs_printk(KERN_ERR, "key_size [%d] larger than " - "the maximum key size [%d]\n", - session_key->decrypted_key_size, - ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES); - rc = -EIO; - goto out; - } - memcpy(session_key->decrypted_key, &data[i], - session_key->decrypted_key_size); - i += session_key->decrypted_key_size; - expected_checksum += (unsigned char)(data[i++]) << 8; - expected_checksum += (unsigned char)(data[i++]); - for (i = 0; i < session_key->decrypted_key_size; i++) - checksum += session_key->decrypted_key[i]; - if (expected_checksum != checksum) { - ecryptfs_printk(KERN_ERR, "Invalid checksum for file " - "encryption key; expected [%x]; calculated " - "[%x]\n", expected_checksum, checksum); - rc = -EIO; - } -out: - return rc; -} - - -static int -write_tag_66_packet(char *signature, u8 cipher_code, - struct ecryptfs_crypt_stat *crypt_stat, char **packet, - size_t *packet_len) -{ - size_t i = 0; - size_t j; - size_t data_len; - size_t checksum = 0; - size_t packet_size_len; - char *message; - int rc; - - /* - * ***** TAG 66 Packet Format ***** - * | Content Type | 1 byte | - * | Key Identifier Size | 1 or 2 bytes | - * | Key Identifier | arbitrary | - * | File Encryption Key Size | 1 or 2 bytes | - * | File Encryption Key | arbitrary | - */ - data_len = (5 + ECRYPTFS_SIG_SIZE_HEX + crypt_stat->key_size); - *packet = kmalloc(data_len, GFP_KERNEL); - message = *packet; - if (!message) { - ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n"); - rc = -ENOMEM; - goto out; - } - message[i++] = ECRYPTFS_TAG_66_PACKET_TYPE; - rc = ecryptfs_write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX, - &packet_size_len); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet " - "header; cannot generate packet length\n"); - goto out; - } - i += packet_size_len; - memcpy(&message[i], signature, ECRYPTFS_SIG_SIZE_HEX); - i += ECRYPTFS_SIG_SIZE_HEX; - /* The encrypted key includes 1 byte cipher code and 2 byte checksum */ - rc = ecryptfs_write_packet_length(&message[i], crypt_stat->key_size + 3, - &packet_size_len); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet " - "header; cannot generate packet length\n"); - goto out; - } - i += packet_size_len; - message[i++] = cipher_code; - memcpy(&message[i], crypt_stat->key, crypt_stat->key_size); - i += crypt_stat->key_size; - for (j = 0; j < crypt_stat->key_size; j++) - checksum += crypt_stat->key[j]; - message[i++] = (checksum / 256) % 256; - message[i++] = (checksum % 256); - *packet_len = i; -out: - return rc; -} - -static int -parse_tag_67_packet(struct ecryptfs_key_record *key_rec, - struct ecryptfs_message *msg) -{ - size_t i = 0; - char *data; - size_t data_len; - size_t message_len; - int rc; - - /* - * ***** TAG 65 Packet Format ***** - * | Content Type | 1 byte | - * | Status Indicator | 1 byte | - * | Encrypted File Encryption Key Size | 1 or 2 bytes | - * | Encrypted File Encryption Key | arbitrary | - */ - message_len = msg->data_len; - data = msg->data; - /* verify that everything through the encrypted FEK size is present */ - if (message_len < 4) { - rc = -EIO; - printk(KERN_ERR "%s: message_len is [%zd]; minimum acceptable " - "message length is [%d]\n", __func__, message_len, 4); - goto out; - } - if (data[i++] != ECRYPTFS_TAG_67_PACKET_TYPE) { - rc = -EIO; - printk(KERN_ERR "%s: Type should be ECRYPTFS_TAG_67\n", - __func__); - goto out; - } - if (data[i++]) { - rc = -EIO; - printk(KERN_ERR "%s: Status indicator has non zero " - "value [%d]\n", __func__, data[i-1]); - - goto out; - } - rc = ecryptfs_parse_packet_length(&data[i], &key_rec->enc_key_size, - &data_len); - if (rc) { - ecryptfs_printk(KERN_WARNING, "Error parsing packet length; " - "rc = [%d]\n", rc); - goto out; - } - i += data_len; - if (message_len < (i + key_rec->enc_key_size)) { - rc = -EIO; - printk(KERN_ERR "%s: message_len [%zd]; max len is [%zd]\n", - __func__, message_len, (i + key_rec->enc_key_size)); - goto out; - } - if (key_rec->enc_key_size > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) { - rc = -EIO; - printk(KERN_ERR "%s: Encrypted key_size [%zd] larger than " - "the maximum key size [%d]\n", __func__, - key_rec->enc_key_size, - ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES); - goto out; - } - memcpy(key_rec->enc_key, &data[i], key_rec->enc_key_size); -out: - return rc; -} - -/** - * ecryptfs_verify_version - * @version: The version number to confirm - * - * Returns zero on good version; non-zero otherwise - */ -static int ecryptfs_verify_version(u16 version) -{ - int rc = 0; - unsigned char major; - unsigned char minor; - - major = ((version >> 8) & 0xFF); - minor = (version & 0xFF); - if (major != ECRYPTFS_VERSION_MAJOR) { - ecryptfs_printk(KERN_ERR, "Major version number mismatch. " - "Expected [%d]; got [%d]\n", - ECRYPTFS_VERSION_MAJOR, major); - rc = -EINVAL; - goto out; - } - if (minor != ECRYPTFS_VERSION_MINOR) { - ecryptfs_printk(KERN_ERR, "Minor version number mismatch. " - "Expected [%d]; got [%d]\n", - ECRYPTFS_VERSION_MINOR, minor); - rc = -EINVAL; - goto out; - } -out: - return rc; -} - -/** - * ecryptfs_verify_auth_tok_from_key - * @auth_tok_key: key containing the authentication token - * @auth_tok: authentication token - * - * Returns zero on valid auth tok; -EINVAL otherwise - */ -static int -ecryptfs_verify_auth_tok_from_key(struct key *auth_tok_key, - struct ecryptfs_auth_tok **auth_tok) -{ - int rc = 0; - - (*auth_tok) = ecryptfs_get_key_payload_data(auth_tok_key); - if (ecryptfs_verify_version((*auth_tok)->version)) { - printk(KERN_ERR "Data structure version mismatch. Userspace " - "tools must match eCryptfs kernel module with major " - "version [%d] and minor version [%d]\n", - ECRYPTFS_VERSION_MAJOR, ECRYPTFS_VERSION_MINOR); - rc = -EINVAL; - goto out; - } - if ((*auth_tok)->token_type != ECRYPTFS_PASSWORD - && (*auth_tok)->token_type != ECRYPTFS_PRIVATE_KEY) { - printk(KERN_ERR "Invalid auth_tok structure " - "returned from key query\n"); - rc = -EINVAL; - goto out; - } -out: - return rc; -} - -static int -ecryptfs_find_global_auth_tok_for_sig( - struct key **auth_tok_key, - struct ecryptfs_auth_tok **auth_tok, - struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig) -{ - struct ecryptfs_global_auth_tok *walker; - int rc = 0; - - (*auth_tok_key) = NULL; - (*auth_tok) = NULL; - mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex); - list_for_each_entry(walker, - &mount_crypt_stat->global_auth_tok_list, - mount_crypt_stat_list) { - if (memcmp(walker->sig, sig, ECRYPTFS_SIG_SIZE_HEX)) - continue; - - if (walker->flags & ECRYPTFS_AUTH_TOK_INVALID) { - rc = -EINVAL; - goto out; - } - - rc = key_validate(walker->global_auth_tok_key); - if (rc) { - if (rc == -EKEYEXPIRED) - goto out; - goto out_invalid_auth_tok; - } - - down_write(&(walker->global_auth_tok_key->sem)); - rc = ecryptfs_verify_auth_tok_from_key( - walker->global_auth_tok_key, auth_tok); - if (rc) - goto out_invalid_auth_tok_unlock; - - (*auth_tok_key) = walker->global_auth_tok_key; - key_get(*auth_tok_key); - goto out; - } - rc = -ENOENT; - goto out; -out_invalid_auth_tok_unlock: - up_write(&(walker->global_auth_tok_key->sem)); -out_invalid_auth_tok: - printk(KERN_WARNING "Invalidating auth tok with sig = [%s]\n", sig); - walker->flags |= ECRYPTFS_AUTH_TOK_INVALID; - key_put(walker->global_auth_tok_key); - walker->global_auth_tok_key = NULL; -out: - mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex); - return rc; -} - -/** - * ecryptfs_find_auth_tok_for_sig - * @auth_tok: Set to the matching auth_tok; NULL if not found - * @crypt_stat: inode crypt_stat crypto context - * @sig: Sig of auth_tok to find - * - * For now, this function simply looks at the registered auth_tok's - * linked off the mount_crypt_stat, so all the auth_toks that can be - * used must be registered at mount time. This function could - * potentially try a lot harder to find auth_tok's (e.g., by calling - * out to ecryptfsd to dynamically retrieve an auth_tok object) so - * that static registration of auth_tok's will no longer be necessary. - * - * Returns zero on no error; non-zero on error - */ -static int -ecryptfs_find_auth_tok_for_sig( - struct key **auth_tok_key, - struct ecryptfs_auth_tok **auth_tok, - struct ecryptfs_mount_crypt_stat *mount_crypt_stat, - char *sig) -{ - int rc = 0; - - rc = ecryptfs_find_global_auth_tok_for_sig(auth_tok_key, auth_tok, - mount_crypt_stat, sig); - if (rc == -ENOENT) { - /* if the flag ECRYPTFS_GLOBAL_MOUNT_AUTH_TOK_ONLY is set in the - * mount_crypt_stat structure, we prevent to use auth toks that - * are not inserted through the ecryptfs_add_global_auth_tok - * function. - */ - if (mount_crypt_stat->flags - & ECRYPTFS_GLOBAL_MOUNT_AUTH_TOK_ONLY) - return -EINVAL; - - rc = ecryptfs_keyring_auth_tok_for_sig(auth_tok_key, auth_tok, - sig); - } - return rc; -} - -/** - * write_tag_70_packet can gobble a lot of stack space. We stuff most - * of the function's parameters in a kmalloc'd struct to help reduce - * eCryptfs' overall stack usage. - */ -struct ecryptfs_write_tag_70_packet_silly_stack { - u8 cipher_code; - size_t max_packet_size; - size_t packet_size_len; - size_t block_aligned_filename_size; - size_t block_size; - size_t i; - size_t j; - size_t num_rand_bytes; - struct mutex *tfm_mutex; - char *block_aligned_filename; - struct ecryptfs_auth_tok *auth_tok; - struct scatterlist src_sg[2]; - struct scatterlist dst_sg[2]; - struct blkcipher_desc desc; - char iv[ECRYPTFS_MAX_IV_BYTES]; - char hash[ECRYPTFS_TAG_70_DIGEST_SIZE]; - char tmp_hash[ECRYPTFS_TAG_70_DIGEST_SIZE]; - struct hash_desc hash_desc; - struct scatterlist hash_sg; -}; - -/** - * write_tag_70_packet - Write encrypted filename (EFN) packet against FNEK - * @filename: NULL-terminated filename string - * - * This is the simplest mechanism for achieving filename encryption in - * eCryptfs. It encrypts the given filename with the mount-wide - * filename encryption key (FNEK) and stores it in a packet to @dest, - * which the callee will encode and write directly into the dentry - * name. - */ -int -ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, - size_t *packet_size, - struct ecryptfs_mount_crypt_stat *mount_crypt_stat, - char *filename, size_t filename_size) -{ - struct ecryptfs_write_tag_70_packet_silly_stack *s; - struct key *auth_tok_key = NULL; - int rc = 0; - - s = kmalloc(sizeof(*s), GFP_KERNEL); - if (!s) { - printk(KERN_ERR "%s: Out of memory whilst trying to kmalloc " - "[%zd] bytes of kernel memory\n", __func__, sizeof(*s)); - rc = -ENOMEM; - goto out; - } - s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; - (*packet_size) = 0; - rc = ecryptfs_find_auth_tok_for_sig( - &auth_tok_key, - &s->auth_tok, mount_crypt_stat, - mount_crypt_stat->global_default_fnek_sig); - if (rc) { - printk(KERN_ERR "%s: Error attempting to find auth tok for " - "fnek sig [%s]; rc = [%d]\n", __func__, - mount_crypt_stat->global_default_fnek_sig, rc); - goto out; - } - rc = ecryptfs_get_tfm_and_mutex_for_cipher_name( - &s->desc.tfm, - &s->tfm_mutex, mount_crypt_stat->global_default_fn_cipher_name); - if (unlikely(rc)) { - printk(KERN_ERR "Internal error whilst attempting to get " - "tfm and mutex for cipher name [%s]; rc = [%d]\n", - mount_crypt_stat->global_default_fn_cipher_name, rc); - goto out; - } - mutex_lock(s->tfm_mutex); - s->block_size = crypto_blkcipher_blocksize(s->desc.tfm); - /* Plus one for the \0 separator between the random prefix - * and the plaintext filename */ - s->num_rand_bytes = (ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES + 1); - s->block_aligned_filename_size = (s->num_rand_bytes + filename_size); - if ((s->block_aligned_filename_size % s->block_size) != 0) { - s->num_rand_bytes += (s->block_size - - (s->block_aligned_filename_size - % s->block_size)); - s->block_aligned_filename_size = (s->num_rand_bytes - + filename_size); - } - /* Octet 0: Tag 70 identifier - * Octets 1-N1: Tag 70 packet size (includes cipher identifier - * and block-aligned encrypted filename size) - * Octets N1-N2: FNEK sig (ECRYPTFS_SIG_SIZE) - * Octet N2-N3: Cipher identifier (1 octet) - * Octets N3-N4: Block-aligned encrypted filename - * - Consists of a minimum number of random characters, a \0 - * separator, and then the filename */ - s->max_packet_size = (ECRYPTFS_TAG_70_MAX_METADATA_SIZE - + s->block_aligned_filename_size); - if (dest == NULL) { - (*packet_size) = s->max_packet_size; - goto out_unlock; - } - if (s->max_packet_size > (*remaining_bytes)) { - printk(KERN_WARNING "%s: Require [%zd] bytes to write; only " - "[%zd] available\n", __func__, s->max_packet_size, - (*remaining_bytes)); - rc = -EINVAL; - goto out_unlock; - } - s->block_aligned_filename = kzalloc(s->block_aligned_filename_size, - GFP_KERNEL); - if (!s->block_aligned_filename) { - printk(KERN_ERR "%s: Out of kernel memory whilst attempting to " - "kzalloc [%zd] bytes\n", __func__, - s->block_aligned_filename_size); - rc = -ENOMEM; - goto out_unlock; - } - s->i = 0; - dest[s->i++] = ECRYPTFS_TAG_70_PACKET_TYPE; - rc = ecryptfs_write_packet_length(&dest[s->i], - (ECRYPTFS_SIG_SIZE - + 1 /* Cipher code */ - + s->block_aligned_filename_size), - &s->packet_size_len); - if (rc) { - printk(KERN_ERR "%s: Error generating tag 70 packet " - "header; cannot generate packet length; rc = [%d]\n", - __func__, rc); - goto out_free_unlock; - } - s->i += s->packet_size_len; - ecryptfs_from_hex(&dest[s->i], - mount_crypt_stat->global_default_fnek_sig, - ECRYPTFS_SIG_SIZE); - s->i += ECRYPTFS_SIG_SIZE; - s->cipher_code = ecryptfs_code_for_cipher_string( - mount_crypt_stat->global_default_fn_cipher_name, - mount_crypt_stat->global_default_fn_cipher_key_bytes); - if (s->cipher_code == 0) { - printk(KERN_WARNING "%s: Unable to generate code for " - "cipher [%s] with key bytes [%zd]\n", __func__, - mount_crypt_stat->global_default_fn_cipher_name, - mount_crypt_stat->global_default_fn_cipher_key_bytes); - rc = -EINVAL; - goto out_free_unlock; - } - dest[s->i++] = s->cipher_code; - /* TODO: Support other key modules than passphrase for - * filename encryption */ - if (s->auth_tok->token_type != ECRYPTFS_PASSWORD) { - rc = -EOPNOTSUPP; - printk(KERN_INFO "%s: Filename encryption only supports " - "password tokens\n", __func__); - goto out_free_unlock; - } - sg_init_one( - &s->hash_sg, - (u8 *)s->auth_tok->token.password.session_key_encryption_key, - s->auth_tok->token.password.session_key_encryption_key_bytes); - s->hash_desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; - s->hash_desc.tfm = crypto_alloc_hash(ECRYPTFS_TAG_70_DIGEST, 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(s->hash_desc.tfm)) { - rc = PTR_ERR(s->hash_desc.tfm); - printk(KERN_ERR "%s: Error attempting to " - "allocate hash crypto context; rc = [%d]\n", - __func__, rc); - goto out_free_unlock; - } - rc = crypto_hash_init(&s->hash_desc); - if (rc) { - printk(KERN_ERR - "%s: Error initializing crypto hash; rc = [%d]\n", - __func__, rc); - goto out_release_free_unlock; - } - rc = crypto_hash_update( - &s->hash_desc, &s->hash_sg, - s->auth_tok->token.password.session_key_encryption_key_bytes); - if (rc) { - printk(KERN_ERR - "%s: Error updating crypto hash; rc = [%d]\n", - __func__, rc); - goto out_release_free_unlock; - } - rc = crypto_hash_final(&s->hash_desc, s->hash); - if (rc) { - printk(KERN_ERR - "%s: Error finalizing crypto hash; rc = [%d]\n", - __func__, rc); - goto out_release_free_unlock; - } - for (s->j = 0; s->j < (s->num_rand_bytes - 1); s->j++) { - s->block_aligned_filename[s->j] = - s->hash[(s->j % ECRYPTFS_TAG_70_DIGEST_SIZE)]; - if ((s->j % ECRYPTFS_TAG_70_DIGEST_SIZE) - == (ECRYPTFS_TAG_70_DIGEST_SIZE - 1)) { - sg_init_one(&s->hash_sg, (u8 *)s->hash, - ECRYPTFS_TAG_70_DIGEST_SIZE); - rc = crypto_hash_init(&s->hash_desc); - if (rc) { - printk(KERN_ERR - "%s: Error initializing crypto hash; " - "rc = [%d]\n", __func__, rc); - goto out_release_free_unlock; - } - rc = crypto_hash_update(&s->hash_desc, &s->hash_sg, - ECRYPTFS_TAG_70_DIGEST_SIZE); - if (rc) { - printk(KERN_ERR - "%s: Error updating crypto hash; " - "rc = [%d]\n", __func__, rc); - goto out_release_free_unlock; - } - rc = crypto_hash_final(&s->hash_desc, s->tmp_hash); - if (rc) { - printk(KERN_ERR - "%s: Error finalizing crypto hash; " - "rc = [%d]\n", __func__, rc); - goto out_release_free_unlock; - } - memcpy(s->hash, s->tmp_hash, - ECRYPTFS_TAG_70_DIGEST_SIZE); - } - if (s->block_aligned_filename[s->j] == '\0') - s->block_aligned_filename[s->j] = ECRYPTFS_NON_NULL; - } - memcpy(&s->block_aligned_filename[s->num_rand_bytes], filename, - filename_size); - rc = virt_to_scatterlist(s->block_aligned_filename, - s->block_aligned_filename_size, s->src_sg, 2); - if (rc < 1) { - printk(KERN_ERR "%s: Internal error whilst attempting to " - "convert filename memory to scatterlist; rc = [%d]. " - "block_aligned_filename_size = [%zd]\n", __func__, rc, - s->block_aligned_filename_size); - goto out_release_free_unlock; - } - rc = virt_to_scatterlist(&dest[s->i], s->block_aligned_filename_size, - s->dst_sg, 2); - if (rc < 1) { - printk(KERN_ERR "%s: Internal error whilst attempting to " - "convert encrypted filename memory to scatterlist; " - "rc = [%d]. block_aligned_filename_size = [%zd]\n", - __func__, rc, s->block_aligned_filename_size); - goto out_release_free_unlock; - } - /* The characters in the first block effectively do the job - * of the IV here, so we just use 0's for the IV. Note the - * constraint that ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES - * >= ECRYPTFS_MAX_IV_BYTES. */ - memset(s->iv, 0, ECRYPTFS_MAX_IV_BYTES); - s->desc.info = s->iv; - rc = crypto_blkcipher_setkey( - s->desc.tfm, - s->auth_tok->token.password.session_key_encryption_key, - mount_crypt_stat->global_default_fn_cipher_key_bytes); - if (rc < 0) { - printk(KERN_ERR "%s: Error setting key for crypto context; " - "rc = [%d]. s->auth_tok->token.password.session_key_" - "encryption_key = [0x%p]; mount_crypt_stat->" - "global_default_fn_cipher_key_bytes = [%zd]\n", __func__, - rc, - s->auth_tok->token.password.session_key_encryption_key, - mount_crypt_stat->global_default_fn_cipher_key_bytes); - goto out_release_free_unlock; - } - rc = crypto_blkcipher_encrypt_iv(&s->desc, s->dst_sg, s->src_sg, - s->block_aligned_filename_size); - if (rc) { - printk(KERN_ERR "%s: Error attempting to encrypt filename; " - "rc = [%d]\n", __func__, rc); - goto out_release_free_unlock; - } - s->i += s->block_aligned_filename_size; - (*packet_size) = s->i; - (*remaining_bytes) -= (*packet_size); -out_release_free_unlock: - crypto_free_hash(s->hash_desc.tfm); -out_free_unlock: - kzfree(s->block_aligned_filename); -out_unlock: - mutex_unlock(s->tfm_mutex); -out: - if (auth_tok_key) { - up_write(&(auth_tok_key->sem)); - key_put(auth_tok_key); - } - kfree(s); - return rc; -} - -struct ecryptfs_parse_tag_70_packet_silly_stack { - u8 cipher_code; - size_t max_packet_size; - size_t packet_size_len; - size_t parsed_tag_70_packet_size; - size_t block_aligned_filename_size; - size_t block_size; - size_t i; - struct mutex *tfm_mutex; - char *decrypted_filename; - struct ecryptfs_auth_tok *auth_tok; - struct scatterlist src_sg[2]; - struct scatterlist dst_sg[2]; - struct blkcipher_desc desc; - char fnek_sig_hex[ECRYPTFS_SIG_SIZE_HEX + 1]; - char iv[ECRYPTFS_MAX_IV_BYTES]; - char cipher_string[ECRYPTFS_MAX_CIPHER_NAME_SIZE]; -}; - -/** - * parse_tag_70_packet - Parse and process FNEK-encrypted passphrase packet - * @filename: This function kmalloc's the memory for the filename - * @filename_size: This function sets this to the amount of memory - * kmalloc'd for the filename - * @packet_size: This function sets this to the the number of octets - * in the packet parsed - * @mount_crypt_stat: The mount-wide cryptographic context - * @data: The memory location containing the start of the tag 70 - * packet - * @max_packet_size: The maximum legal size of the packet to be parsed - * from @data - * - * Returns zero on success; non-zero otherwise - */ -int -ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size, - size_t *packet_size, - struct ecryptfs_mount_crypt_stat *mount_crypt_stat, - char *data, size_t max_packet_size) -{ - struct ecryptfs_parse_tag_70_packet_silly_stack *s; - struct key *auth_tok_key = NULL; - int rc = 0; - - (*packet_size) = 0; - (*filename_size) = 0; - (*filename) = NULL; - s = kmalloc(sizeof(*s), GFP_KERNEL); - if (!s) { - printk(KERN_ERR "%s: Out of memory whilst trying to kmalloc " - "[%zd] bytes of kernel memory\n", __func__, sizeof(*s)); - rc = -ENOMEM; - goto out; - } - s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; - if (max_packet_size < ECRYPTFS_TAG_70_MIN_METADATA_SIZE) { - printk(KERN_WARNING "%s: max_packet_size is [%zd]; it must be " - "at least [%d]\n", __func__, max_packet_size, - ECRYPTFS_TAG_70_MIN_METADATA_SIZE); - rc = -EINVAL; - goto out; - } - /* Octet 0: Tag 70 identifier - * Octets 1-N1: Tag 70 packet size (includes cipher identifier - * and block-aligned encrypted filename size) - * Octets N1-N2: FNEK sig (ECRYPTFS_SIG_SIZE) - * Octet N2-N3: Cipher identifier (1 octet) - * Octets N3-N4: Block-aligned encrypted filename - * - Consists of a minimum number of random numbers, a \0 - * separator, and then the filename */ - if (data[(*packet_size)++] != ECRYPTFS_TAG_70_PACKET_TYPE) { - printk(KERN_WARNING "%s: Invalid packet tag [0x%.2x]; must be " - "tag [0x%.2x]\n", __func__, - data[((*packet_size) - 1)], ECRYPTFS_TAG_70_PACKET_TYPE); - rc = -EINVAL; - goto out; - } - rc = ecryptfs_parse_packet_length(&data[(*packet_size)], - &s->parsed_tag_70_packet_size, - &s->packet_size_len); - if (rc) { - printk(KERN_WARNING "%s: Error parsing packet length; " - "rc = [%d]\n", __func__, rc); - goto out; - } - s->block_aligned_filename_size = (s->parsed_tag_70_packet_size - - ECRYPTFS_SIG_SIZE - 1); - if ((1 + s->packet_size_len + s->parsed_tag_70_packet_size) - > max_packet_size) { - printk(KERN_WARNING "%s: max_packet_size is [%zd]; real packet " - "size is [%zd]\n", __func__, max_packet_size, - (1 + s->packet_size_len + 1 - + s->block_aligned_filename_size)); - rc = -EINVAL; - goto out; - } - (*packet_size) += s->packet_size_len; - ecryptfs_to_hex(s->fnek_sig_hex, &data[(*packet_size)], - ECRYPTFS_SIG_SIZE); - s->fnek_sig_hex[ECRYPTFS_SIG_SIZE_HEX] = '\0'; - (*packet_size) += ECRYPTFS_SIG_SIZE; - s->cipher_code = data[(*packet_size)++]; - rc = ecryptfs_cipher_code_to_string(s->cipher_string, s->cipher_code); - if (rc) { - printk(KERN_WARNING "%s: Cipher code [%d] is invalid\n", - __func__, s->cipher_code); - goto out; - } - rc = ecryptfs_find_auth_tok_for_sig(&auth_tok_key, - &s->auth_tok, mount_crypt_stat, - s->fnek_sig_hex); - if (rc) { - printk(KERN_ERR "%s: Error attempting to find auth tok for " - "fnek sig [%s]; rc = [%d]\n", __func__, s->fnek_sig_hex, - rc); - goto out; - } - rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&s->desc.tfm, - &s->tfm_mutex, - s->cipher_string); - if (unlikely(rc)) { - printk(KERN_ERR "Internal error whilst attempting to get " - "tfm and mutex for cipher name [%s]; rc = [%d]\n", - s->cipher_string, rc); - goto out; - } - mutex_lock(s->tfm_mutex); - rc = virt_to_scatterlist(&data[(*packet_size)], - s->block_aligned_filename_size, s->src_sg, 2); - if (rc < 1) { - printk(KERN_ERR "%s: Internal error whilst attempting to " - "convert encrypted filename memory to scatterlist; " - "rc = [%d]. block_aligned_filename_size = [%zd]\n", - __func__, rc, s->block_aligned_filename_size); - goto out_unlock; - } - (*packet_size) += s->block_aligned_filename_size; - s->decrypted_filename = kmalloc(s->block_aligned_filename_size, - GFP_KERNEL); - if (!s->decrypted_filename) { - printk(KERN_ERR "%s: Out of memory whilst attempting to " - "kmalloc [%zd] bytes\n", __func__, - s->block_aligned_filename_size); - rc = -ENOMEM; - goto out_unlock; - } - rc = virt_to_scatterlist(s->decrypted_filename, - s->block_aligned_filename_size, s->dst_sg, 2); - if (rc < 1) { - printk(KERN_ERR "%s: Internal error whilst attempting to " - "convert decrypted filename memory to scatterlist; " - "rc = [%d]. block_aligned_filename_size = [%zd]\n", - __func__, rc, s->block_aligned_filename_size); - goto out_free_unlock; - } - /* The characters in the first block effectively do the job of - * the IV here, so we just use 0's for the IV. Note the - * constraint that ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES - * >= ECRYPTFS_MAX_IV_BYTES. */ - memset(s->iv, 0, ECRYPTFS_MAX_IV_BYTES); - s->desc.info = s->iv; - /* TODO: Support other key modules than passphrase for - * filename encryption */ - if (s->auth_tok->token_type != ECRYPTFS_PASSWORD) { - rc = -EOPNOTSUPP; - printk(KERN_INFO "%s: Filename encryption only supports " - "password tokens\n", __func__); - goto out_free_unlock; - } - rc = crypto_blkcipher_setkey( - s->desc.tfm, - s->auth_tok->token.password.session_key_encryption_key, - mount_crypt_stat->global_default_fn_cipher_key_bytes); - if (rc < 0) { - printk(KERN_ERR "%s: Error setting key for crypto context; " - "rc = [%d]. s->auth_tok->token.password.session_key_" - "encryption_key = [0x%p]; mount_crypt_stat->" - "global_default_fn_cipher_key_bytes = [%zd]\n", __func__, - rc, - s->auth_tok->token.password.session_key_encryption_key, - mount_crypt_stat->global_default_fn_cipher_key_bytes); - goto out_free_unlock; - } - rc = crypto_blkcipher_decrypt_iv(&s->desc, s->dst_sg, s->src_sg, - s->block_aligned_filename_size); - if (rc) { - printk(KERN_ERR "%s: Error attempting to decrypt filename; " - "rc = [%d]\n", __func__, rc); - goto out_free_unlock; - } - s->i = 0; - while (s->decrypted_filename[s->i] != '\0' - && s->i < s->block_aligned_filename_size) - s->i++; - if (s->i == s->block_aligned_filename_size) { - printk(KERN_WARNING "%s: Invalid tag 70 packet; could not " - "find valid separator between random characters and " - "the filename\n", __func__); - rc = -EINVAL; - goto out_free_unlock; - } - s->i++; - (*filename_size) = (s->block_aligned_filename_size - s->i); - if (!((*filename_size) > 0 && (*filename_size < PATH_MAX))) { - printk(KERN_WARNING "%s: Filename size is [%zd], which is " - "invalid\n", __func__, (*filename_size)); - rc = -EINVAL; - goto out_free_unlock; - } - (*filename) = kmalloc(((*filename_size) + 1), GFP_KERNEL); - if (!(*filename)) { - printk(KERN_ERR "%s: Out of memory whilst attempting to " - "kmalloc [%zd] bytes\n", __func__, - ((*filename_size) + 1)); - rc = -ENOMEM; - goto out_free_unlock; - } - memcpy((*filename), &s->decrypted_filename[s->i], (*filename_size)); - (*filename)[(*filename_size)] = '\0'; -out_free_unlock: - kfree(s->decrypted_filename); -out_unlock: - mutex_unlock(s->tfm_mutex); -out: - if (rc) { - (*packet_size) = 0; - (*filename_size) = 0; - (*filename) = NULL; - } - if (auth_tok_key) { - up_write(&(auth_tok_key->sem)); - key_put(auth_tok_key); - } - kfree(s); - return rc; -} - -static int -ecryptfs_get_auth_tok_sig(char **sig, struct ecryptfs_auth_tok *auth_tok) -{ - int rc = 0; - - (*sig) = NULL; - switch (auth_tok->token_type) { - case ECRYPTFS_PASSWORD: - (*sig) = auth_tok->token.password.signature; - break; - case ECRYPTFS_PRIVATE_KEY: - (*sig) = auth_tok->token.private_key.signature; - break; - default: - printk(KERN_ERR "Cannot get sig for auth_tok of type [%d]\n", - auth_tok->token_type); - rc = -EINVAL; - } - return rc; -} - -/** - * decrypt_pki_encrypted_session_key - Decrypt the session key with the given auth_tok. - * @auth_tok: The key authentication token used to decrypt the session key - * @crypt_stat: The cryptographic context - * - * Returns zero on success; non-zero error otherwise. - */ -static int -decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, - struct ecryptfs_crypt_stat *crypt_stat) -{ - u8 cipher_code = 0; - struct ecryptfs_msg_ctx *msg_ctx; - struct ecryptfs_message *msg = NULL; - char *auth_tok_sig; - char *payload; - size_t payload_len; - int rc; - - rc = ecryptfs_get_auth_tok_sig(&auth_tok_sig, auth_tok); - if (rc) { - printk(KERN_ERR "Unrecognized auth tok type: [%d]\n", - auth_tok->token_type); - goto out; - } - rc = write_tag_64_packet(auth_tok_sig, &(auth_tok->session_key), - &payload, &payload_len); - if (rc) { - ecryptfs_printk(KERN_ERR, "Failed to write tag 64 packet\n"); - goto out; - } - rc = ecryptfs_send_message(payload, payload_len, &msg_ctx); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error sending message to " - "ecryptfsd\n"); - goto out; - } - rc = ecryptfs_wait_for_response(msg_ctx, &msg); - if (rc) { - ecryptfs_printk(KERN_ERR, "Failed to receive tag 65 packet " - "from the user space daemon\n"); - rc = -EIO; - goto out; - } - rc = parse_tag_65_packet(&(auth_tok->session_key), - &cipher_code, msg); - if (rc) { - printk(KERN_ERR "Failed to parse tag 65 packet; rc = [%d]\n", - rc); - goto out; - } - auth_tok->session_key.flags |= ECRYPTFS_CONTAINS_DECRYPTED_KEY; - memcpy(crypt_stat->key, auth_tok->session_key.decrypted_key, - auth_tok->session_key.decrypted_key_size); - crypt_stat->key_size = auth_tok->session_key.decrypted_key_size; - rc = ecryptfs_cipher_code_to_string(crypt_stat->cipher, cipher_code); - if (rc) { - ecryptfs_printk(KERN_ERR, "Cipher code [%d] is invalid\n", - cipher_code) - goto out; - } - crypt_stat->flags |= ECRYPTFS_KEY_VALID; - if (ecryptfs_verbosity > 0) { - ecryptfs_printk(KERN_DEBUG, "Decrypted session key:\n"); - ecryptfs_dump_hex(crypt_stat->key, - crypt_stat->key_size); - } -out: - if (msg) - kfree(msg); - return rc; -} - -static void wipe_auth_tok_list(struct list_head *auth_tok_list_head) -{ - struct ecryptfs_auth_tok_list_item *auth_tok_list_item; - struct ecryptfs_auth_tok_list_item *auth_tok_list_item_tmp; - - list_for_each_entry_safe(auth_tok_list_item, auth_tok_list_item_tmp, - auth_tok_list_head, list) { - list_del(&auth_tok_list_item->list); - kmem_cache_free(ecryptfs_auth_tok_list_item_cache, - auth_tok_list_item); - } -} - -struct kmem_cache *ecryptfs_auth_tok_list_item_cache; - -/** - * parse_tag_1_packet - * @crypt_stat: The cryptographic context to modify based on packet contents - * @data: The raw bytes of the packet. - * @auth_tok_list: eCryptfs parses packets into authentication tokens; - * a new authentication token will be placed at the - * end of this list for this packet. - * @new_auth_tok: Pointer to a pointer to memory that this function - * allocates; sets the memory address of the pointer to - * NULL on error. This object is added to the - * auth_tok_list. - * @packet_size: This function writes the size of the parsed packet - * into this memory location; zero on error. - * @max_packet_size: The maximum allowable packet size - * - * Returns zero on success; non-zero on error. - */ -static int -parse_tag_1_packet(struct ecryptfs_crypt_stat *crypt_stat, - unsigned char *data, struct list_head *auth_tok_list, - struct ecryptfs_auth_tok **new_auth_tok, - size_t *packet_size, size_t max_packet_size) -{ - size_t body_size; - struct ecryptfs_auth_tok_list_item *auth_tok_list_item; - size_t length_size; - int rc = 0; - - (*packet_size) = 0; - (*new_auth_tok) = NULL; - /** - * This format is inspired by OpenPGP; see RFC 2440 - * packet tag 1 - * - * Tag 1 identifier (1 byte) - * Max Tag 1 packet size (max 3 bytes) - * Version (1 byte) - * Key identifier (8 bytes; ECRYPTFS_SIG_SIZE) - * Cipher identifier (1 byte) - * Encrypted key size (arbitrary) - * - * 12 bytes minimum packet size - */ - if (unlikely(max_packet_size < 12)) { - printk(KERN_ERR "Invalid max packet size; must be >=12\n"); - rc = -EINVAL; - goto out; - } - if (data[(*packet_size)++] != ECRYPTFS_TAG_1_PACKET_TYPE) { - printk(KERN_ERR "Enter w/ first byte != 0x%.2x\n", - ECRYPTFS_TAG_1_PACKET_TYPE); - rc = -EINVAL; - goto out; - } - /* Released: wipe_auth_tok_list called in ecryptfs_parse_packet_set or - * at end of function upon failure */ - auth_tok_list_item = - kmem_cache_zalloc(ecryptfs_auth_tok_list_item_cache, - GFP_KERNEL); - if (!auth_tok_list_item) { - printk(KERN_ERR "Unable to allocate memory\n"); - rc = -ENOMEM; - goto out; - } - (*new_auth_tok) = &auth_tok_list_item->auth_tok; - rc = ecryptfs_parse_packet_length(&data[(*packet_size)], &body_size, - &length_size); - if (rc) { - printk(KERN_WARNING "Error parsing packet length; " - "rc = [%d]\n", rc); - goto out_free; - } - if (unlikely(body_size < (ECRYPTFS_SIG_SIZE + 2))) { - printk(KERN_WARNING "Invalid body size ([%td])\n", body_size); - rc = -EINVAL; - goto out_free; - } - (*packet_size) += length_size; - if (unlikely((*packet_size) + body_size > max_packet_size)) { - printk(KERN_WARNING "Packet size exceeds max\n"); - rc = -EINVAL; - goto out_free; - } - if (unlikely(data[(*packet_size)++] != 0x03)) { - printk(KERN_WARNING "Unknown version number [%d]\n", - data[(*packet_size) - 1]); - rc = -EINVAL; - goto out_free; - } - ecryptfs_to_hex((*new_auth_tok)->token.private_key.signature, - &data[(*packet_size)], ECRYPTFS_SIG_SIZE); - *packet_size += ECRYPTFS_SIG_SIZE; - /* This byte is skipped because the kernel does not need to - * know which public key encryption algorithm was used */ - (*packet_size)++; - (*new_auth_tok)->session_key.encrypted_key_size = - body_size - (ECRYPTFS_SIG_SIZE + 2); - if ((*new_auth_tok)->session_key.encrypted_key_size - > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) { - printk(KERN_WARNING "Tag 1 packet contains key larger " - "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES"); - rc = -EINVAL; - goto out; - } - memcpy((*new_auth_tok)->session_key.encrypted_key, - &data[(*packet_size)], (body_size - (ECRYPTFS_SIG_SIZE + 2))); - (*packet_size) += (*new_auth_tok)->session_key.encrypted_key_size; - (*new_auth_tok)->session_key.flags &= - ~ECRYPTFS_CONTAINS_DECRYPTED_KEY; - (*new_auth_tok)->session_key.flags |= - ECRYPTFS_CONTAINS_ENCRYPTED_KEY; - (*new_auth_tok)->token_type = ECRYPTFS_PRIVATE_KEY; - (*new_auth_tok)->flags = 0; - (*new_auth_tok)->session_key.flags &= - ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT); - (*new_auth_tok)->session_key.flags &= - ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT); - list_add(&auth_tok_list_item->list, auth_tok_list); - goto out; -out_free: - (*new_auth_tok) = NULL; - memset(auth_tok_list_item, 0, - sizeof(struct ecryptfs_auth_tok_list_item)); - kmem_cache_free(ecryptfs_auth_tok_list_item_cache, - auth_tok_list_item); -out: - if (rc) - (*packet_size) = 0; - return rc; -} - -/** - * parse_tag_3_packet - * @crypt_stat: The cryptographic context to modify based on packet - * contents. - * @data: The raw bytes of the packet. - * @auth_tok_list: eCryptfs parses packets into authentication tokens; - * a new authentication token will be placed at the end - * of this list for this packet. - * @new_auth_tok: Pointer to a pointer to memory that this function - * allocates; sets the memory address of the pointer to - * NULL on error. This object is added to the - * auth_tok_list. - * @packet_size: This function writes the size of the parsed packet - * into this memory location; zero on error. - * @max_packet_size: maximum number of bytes to parse - * - * Returns zero on success; non-zero on error. - */ -static int -parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat, - unsigned char *data, struct list_head *auth_tok_list, - struct ecryptfs_auth_tok **new_auth_tok, - size_t *packet_size, size_t max_packet_size) -{ - size_t body_size; - struct ecryptfs_auth_tok_list_item *auth_tok_list_item; - size_t length_size; - int rc = 0; - - (*packet_size) = 0; - (*new_auth_tok) = NULL; - /** - *This format is inspired by OpenPGP; see RFC 2440 - * packet tag 3 - * - * Tag 3 identifier (1 byte) - * Max Tag 3 packet size (max 3 bytes) - * Version (1 byte) - * Cipher code (1 byte) - * S2K specifier (1 byte) - * Hash identifier (1 byte) - * Salt (ECRYPTFS_SALT_SIZE) - * Hash iterations (1 byte) - * Encrypted key (arbitrary) - * - * (ECRYPTFS_SALT_SIZE + 7) minimum packet size - */ - if (max_packet_size < (ECRYPTFS_SALT_SIZE + 7)) { - printk(KERN_ERR "Max packet size too large\n"); - rc = -EINVAL; - goto out; - } - if (data[(*packet_size)++] != ECRYPTFS_TAG_3_PACKET_TYPE) { - printk(KERN_ERR "First byte != 0x%.2x; invalid packet\n", - ECRYPTFS_TAG_3_PACKET_TYPE); - rc = -EINVAL; - goto out; - } - /* Released: wipe_auth_tok_list called in ecryptfs_parse_packet_set or - * at end of function upon failure */ - auth_tok_list_item = - kmem_cache_zalloc(ecryptfs_auth_tok_list_item_cache, GFP_KERNEL); - if (!auth_tok_list_item) { - printk(KERN_ERR "Unable to allocate memory\n"); - rc = -ENOMEM; - goto out; - } - (*new_auth_tok) = &auth_tok_list_item->auth_tok; - rc = ecryptfs_parse_packet_length(&data[(*packet_size)], &body_size, - &length_size); - if (rc) { - printk(KERN_WARNING "Error parsing packet length; rc = [%d]\n", - rc); - goto out_free; - } - if (unlikely(body_size < (ECRYPTFS_SALT_SIZE + 5))) { - printk(KERN_WARNING "Invalid body size ([%td])\n", body_size); - rc = -EINVAL; - goto out_free; - } - (*packet_size) += length_size; - if (unlikely((*packet_size) + body_size > max_packet_size)) { - printk(KERN_ERR "Packet size exceeds max\n"); - rc = -EINVAL; - goto out_free; - } - (*new_auth_tok)->session_key.encrypted_key_size = - (body_size - (ECRYPTFS_SALT_SIZE + 5)); - if ((*new_auth_tok)->session_key.encrypted_key_size - > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) { - printk(KERN_WARNING "Tag 3 packet contains key larger " - "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES\n"); - rc = -EINVAL; - goto out_free; - } - if (unlikely(data[(*packet_size)++] != 0x04)) { - printk(KERN_WARNING "Unknown version number [%d]\n", - data[(*packet_size) - 1]); - rc = -EINVAL; - goto out_free; - } - rc = ecryptfs_cipher_code_to_string(crypt_stat->cipher, - (u16)data[(*packet_size)]); - if (rc) - goto out_free; - /* A little extra work to differentiate among the AES key - * sizes; see RFC2440 */ - switch(data[(*packet_size)++]) { - case RFC2440_CIPHER_AES_192: - crypt_stat->key_size = 24; - break; - default: - crypt_stat->key_size = - (*new_auth_tok)->session_key.encrypted_key_size; - } - rc = ecryptfs_init_crypt_ctx(crypt_stat); - if (rc) - goto out_free; - if (unlikely(data[(*packet_size)++] != 0x03)) { - printk(KERN_WARNING "Only S2K ID 3 is currently supported\n"); - rc = -ENOSYS; - goto out_free; - } - /* TODO: finish the hash mapping */ - switch (data[(*packet_size)++]) { - case 0x01: /* See RFC2440 for these numbers and their mappings */ - /* Choose MD5 */ - memcpy((*new_auth_tok)->token.password.salt, - &data[(*packet_size)], ECRYPTFS_SALT_SIZE); - (*packet_size) += ECRYPTFS_SALT_SIZE; - /* This conversion was taken straight from RFC2440 */ - (*new_auth_tok)->token.password.hash_iterations = - ((u32) 16 + (data[(*packet_size)] & 15)) - << ((data[(*packet_size)] >> 4) + 6); - (*packet_size)++; - /* Friendly reminder: - * (*new_auth_tok)->session_key.encrypted_key_size = - * (body_size - (ECRYPTFS_SALT_SIZE + 5)); */ - memcpy((*new_auth_tok)->session_key.encrypted_key, - &data[(*packet_size)], - (*new_auth_tok)->session_key.encrypted_key_size); - (*packet_size) += - (*new_auth_tok)->session_key.encrypted_key_size; - (*new_auth_tok)->session_key.flags &= - ~ECRYPTFS_CONTAINS_DECRYPTED_KEY; - (*new_auth_tok)->session_key.flags |= - ECRYPTFS_CONTAINS_ENCRYPTED_KEY; - (*new_auth_tok)->token.password.hash_algo = 0x01; /* MD5 */ - break; - default: - ecryptfs_printk(KERN_ERR, "Unsupported hash algorithm: " - "[%d]\n", data[(*packet_size) - 1]); - rc = -ENOSYS; - goto out_free; - } - (*new_auth_tok)->token_type = ECRYPTFS_PASSWORD; - /* TODO: Parametarize; we might actually want userspace to - * decrypt the session key. */ - (*new_auth_tok)->session_key.flags &= - ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT); - (*new_auth_tok)->session_key.flags &= - ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT); - list_add(&auth_tok_list_item->list, auth_tok_list); - goto out; -out_free: - (*new_auth_tok) = NULL; - memset(auth_tok_list_item, 0, - sizeof(struct ecryptfs_auth_tok_list_item)); - kmem_cache_free(ecryptfs_auth_tok_list_item_cache, - auth_tok_list_item); -out: - if (rc) - (*packet_size) = 0; - return rc; -} - -/** - * parse_tag_11_packet - * @data: The raw bytes of the packet - * @contents: This function writes the data contents of the literal - * packet into this memory location - * @max_contents_bytes: The maximum number of bytes that this function - * is allowed to write into contents - * @tag_11_contents_size: This function writes the size of the parsed - * contents into this memory location; zero on - * error - * @packet_size: This function writes the size of the parsed packet - * into this memory location; zero on error - * @max_packet_size: maximum number of bytes to parse - * - * Returns zero on success; non-zero on error. - */ -static int -parse_tag_11_packet(unsigned char *data, unsigned char *contents, - size_t max_contents_bytes, size_t *tag_11_contents_size, - size_t *packet_size, size_t max_packet_size) -{ - size_t body_size; - size_t length_size; - int rc = 0; - - (*packet_size) = 0; - (*tag_11_contents_size) = 0; - /* This format is inspired by OpenPGP; see RFC 2440 - * packet tag 11 - * - * Tag 11 identifier (1 byte) - * Max Tag 11 packet size (max 3 bytes) - * Binary format specifier (1 byte) - * Filename length (1 byte) - * Filename ("_CONSOLE") (8 bytes) - * Modification date (4 bytes) - * Literal data (arbitrary) - * - * We need at least 16 bytes of data for the packet to even be - * valid. - */ - if (max_packet_size < 16) { - printk(KERN_ERR "Maximum packet size too small\n"); - rc = -EINVAL; - goto out; - } - if (data[(*packet_size)++] != ECRYPTFS_TAG_11_PACKET_TYPE) { - printk(KERN_WARNING "Invalid tag 11 packet format\n"); - rc = -EINVAL; - goto out; - } - rc = ecryptfs_parse_packet_length(&data[(*packet_size)], &body_size, - &length_size); - if (rc) { - printk(KERN_WARNING "Invalid tag 11 packet format\n"); - goto out; - } - if (body_size < 14) { - printk(KERN_WARNING "Invalid body size ([%td])\n", body_size); - rc = -EINVAL; - goto out; - } - (*packet_size) += length_size; - (*tag_11_contents_size) = (body_size - 14); - if (unlikely((*packet_size) + body_size + 1 > max_packet_size)) { - printk(KERN_ERR "Packet size exceeds max\n"); - rc = -EINVAL; - goto out; - } - if (unlikely((*tag_11_contents_size) > max_contents_bytes)) { - printk(KERN_ERR "Literal data section in tag 11 packet exceeds " - "expected size\n"); - rc = -EINVAL; - goto out; - } - if (data[(*packet_size)++] != 0x62) { - printk(KERN_WARNING "Unrecognizable packet\n"); - rc = -EINVAL; - goto out; - } - if (data[(*packet_size)++] != 0x08) { - printk(KERN_WARNING "Unrecognizable packet\n"); - rc = -EINVAL; - goto out; - } - (*packet_size) += 12; /* Ignore filename and modification date */ - memcpy(contents, &data[(*packet_size)], (*tag_11_contents_size)); - (*packet_size) += (*tag_11_contents_size); -out: - if (rc) { - (*packet_size) = 0; - (*tag_11_contents_size) = 0; - } - return rc; -} - -int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key, - struct ecryptfs_auth_tok **auth_tok, - char *sig) -{ - int rc = 0; - - (*auth_tok_key) = request_key(&key_type_user, sig, NULL); - if (!(*auth_tok_key) || IS_ERR(*auth_tok_key)) { - (*auth_tok_key) = ecryptfs_get_encrypted_key(sig); - if (!(*auth_tok_key) || IS_ERR(*auth_tok_key)) { - printk(KERN_ERR "Could not find key with description: [%s]\n", - sig); - rc = process_request_key_err(PTR_ERR(*auth_tok_key)); - (*auth_tok_key) = NULL; - goto out; - } - } - down_write(&(*auth_tok_key)->sem); - rc = ecryptfs_verify_auth_tok_from_key(*auth_tok_key, auth_tok); - if (rc) { - up_write(&(*auth_tok_key)->sem); - key_put(*auth_tok_key); - (*auth_tok_key) = NULL; - goto out; - } -out: - return rc; -} - -/** - * decrypt_passphrase_encrypted_session_key - Decrypt the session key with the given auth_tok. - * @auth_tok: The passphrase authentication token to use to encrypt the FEK - * @crypt_stat: The cryptographic context - * - * Returns zero on success; non-zero error otherwise - */ -static int -decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, - struct ecryptfs_crypt_stat *crypt_stat) -{ - struct scatterlist dst_sg[2]; - struct scatterlist src_sg[2]; - struct mutex *tfm_mutex; - struct blkcipher_desc desc = { - .flags = CRYPTO_TFM_REQ_MAY_SLEEP - }; - int rc = 0; - - if (unlikely(ecryptfs_verbosity > 0)) { - ecryptfs_printk( - KERN_DEBUG, "Session key encryption key (size [%d]):\n", - auth_tok->token.password.session_key_encryption_key_bytes); - ecryptfs_dump_hex( - auth_tok->token.password.session_key_encryption_key, - auth_tok->token.password.session_key_encryption_key_bytes); - } - rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&desc.tfm, &tfm_mutex, - crypt_stat->cipher); - if (unlikely(rc)) { - printk(KERN_ERR "Internal error whilst attempting to get " - "tfm and mutex for cipher name [%s]; rc = [%d]\n", - crypt_stat->cipher, rc); - goto out; - } - rc = virt_to_scatterlist(auth_tok->session_key.encrypted_key, - auth_tok->session_key.encrypted_key_size, - src_sg, 2); - if (rc < 1 || rc > 2) { - printk(KERN_ERR "Internal error whilst attempting to convert " - "auth_tok->session_key.encrypted_key to scatterlist; " - "expected rc = 1; got rc = [%d]. " - "auth_tok->session_key.encrypted_key_size = [%d]\n", rc, - auth_tok->session_key.encrypted_key_size); - goto out; - } - auth_tok->session_key.decrypted_key_size = - auth_tok->session_key.encrypted_key_size; - rc = virt_to_scatterlist(auth_tok->session_key.decrypted_key, - auth_tok->session_key.decrypted_key_size, - dst_sg, 2); - if (rc < 1 || rc > 2) { - printk(KERN_ERR "Internal error whilst attempting to convert " - "auth_tok->session_key.decrypted_key to scatterlist; " - "expected rc = 1; got rc = [%d]\n", rc); - goto out; - } - mutex_lock(tfm_mutex); - rc = crypto_blkcipher_setkey( - desc.tfm, auth_tok->token.password.session_key_encryption_key, - crypt_stat->key_size); - if (unlikely(rc < 0)) { - mutex_unlock(tfm_mutex); - printk(KERN_ERR "Error setting key for crypto context\n"); - rc = -EINVAL; - goto out; - } - rc = crypto_blkcipher_decrypt(&desc, dst_sg, src_sg, - auth_tok->session_key.encrypted_key_size); - mutex_unlock(tfm_mutex); - if (unlikely(rc)) { - printk(KERN_ERR "Error decrypting; rc = [%d]\n", rc); - goto out; - } - auth_tok->session_key.flags |= ECRYPTFS_CONTAINS_DECRYPTED_KEY; - memcpy(crypt_stat->key, auth_tok->session_key.decrypted_key, - auth_tok->session_key.decrypted_key_size); - crypt_stat->flags |= ECRYPTFS_KEY_VALID; - if (unlikely(ecryptfs_verbosity > 0)) { - ecryptfs_printk(KERN_DEBUG, "FEK of size [%zd]:\n", - crypt_stat->key_size); - ecryptfs_dump_hex(crypt_stat->key, - crypt_stat->key_size); - } -out: - return rc; -} - -/** - * ecryptfs_parse_packet_set - * @crypt_stat: The cryptographic context - * @src: Virtual address of region of memory containing the packets - * @ecryptfs_dentry: The eCryptfs dentry associated with the packet set - * - * Get crypt_stat to have the file's session key if the requisite key - * is available to decrypt the session key. - * - * Returns Zero if a valid authentication token was retrieved and - * processed; negative value for file not encrypted or for error - * conditions. - */ -int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat, - unsigned char *src, - struct dentry *ecryptfs_dentry) -{ - size_t i = 0; - 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; - char *candidate_auth_tok_sig; - size_t packet_size; - struct ecryptfs_auth_tok *new_auth_tok; - unsigned char sig_tmp_space[ECRYPTFS_SIG_SIZE]; - struct ecryptfs_auth_tok_list_item *auth_tok_list_item; - size_t tag_11_contents_size; - size_t tag_11_packet_size; - struct key *auth_tok_key = NULL; - int rc = 0; - - INIT_LIST_HEAD(&auth_tok_list); - /* Parse the header to find as many packets as we can; these will be - * added the our &auth_tok_list */ - next_packet_is_auth_tok_packet = 1; - while (next_packet_is_auth_tok_packet) { - size_t max_packet_size = ((PAGE_CACHE_SIZE - 8) - i); - - switch (src[i]) { - case ECRYPTFS_TAG_3_PACKET_TYPE: - rc = parse_tag_3_packet(crypt_stat, - (unsigned char *)&src[i], - &auth_tok_list, &new_auth_tok, - &packet_size, max_packet_size); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error parsing " - "tag 3 packet\n"); - rc = -EIO; - goto out_wipe_list; - } - i += packet_size; - rc = parse_tag_11_packet((unsigned char *)&src[i], - sig_tmp_space, - ECRYPTFS_SIG_SIZE, - &tag_11_contents_size, - &tag_11_packet_size, - max_packet_size); - if (rc) { - ecryptfs_printk(KERN_ERR, "No valid " - "(ecryptfs-specific) literal " - "packet containing " - "authentication token " - "signature found after " - "tag 3 packet\n"); - rc = -EIO; - goto out_wipe_list; - } - i += tag_11_packet_size; - if (ECRYPTFS_SIG_SIZE != tag_11_contents_size) { - ecryptfs_printk(KERN_ERR, "Expected " - "signature of size [%d]; " - "read size [%zd]\n", - ECRYPTFS_SIG_SIZE, - tag_11_contents_size); - rc = -EIO; - goto out_wipe_list; - } - ecryptfs_to_hex(new_auth_tok->token.password.signature, - sig_tmp_space, tag_11_contents_size); - new_auth_tok->token.password.signature[ - ECRYPTFS_PASSWORD_SIG_SIZE] = '\0'; - crypt_stat->flags |= ECRYPTFS_ENCRYPTED; - break; - case ECRYPTFS_TAG_1_PACKET_TYPE: - rc = parse_tag_1_packet(crypt_stat, - (unsigned char *)&src[i], - &auth_tok_list, &new_auth_tok, - &packet_size, max_packet_size); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error parsing " - "tag 1 packet\n"); - rc = -EIO; - goto out_wipe_list; - } - i += packet_size; - crypt_stat->flags |= ECRYPTFS_ENCRYPTED; - break; - case ECRYPTFS_TAG_11_PACKET_TYPE: - ecryptfs_printk(KERN_WARNING, "Invalid packet set " - "(Tag 11 not allowed by itself)\n"); - rc = -EIO; - goto out_wipe_list; - break; - default: - ecryptfs_printk(KERN_DEBUG, "No packet at offset [%zd] " - "of the file header; hex value of " - "character is [0x%.2x]\n", i, src[i]); - next_packet_is_auth_tok_packet = 0; - } - } - if (list_empty(&auth_tok_list)) { - printk(KERN_ERR "The lower file appears to be a non-encrypted " - "eCryptfs file; this is not supported in this version " - "of the eCryptfs kernel module\n"); - rc = -EINVAL; - goto out; - } - /* auth_tok_list contains the set of authentication tokens - * parsed from the metadata. We need to find a matching - * authentication token that has the secret component(s) - * necessary to decrypt the EFEK in the auth_tok parsed from - * the metadata. There may be several potential matches, but - * just one will be sufficient to decrypt to get the FEK. */ -find_next_matching_auth_tok: - found_auth_tok = 0; - list_for_each_entry(auth_tok_list_item, &auth_tok_list, list) { - candidate_auth_tok = &auth_tok_list_item->auth_tok; - if (unlikely(ecryptfs_verbosity > 0)) { - ecryptfs_printk(KERN_DEBUG, - "Considering cadidate auth tok:\n"); - ecryptfs_dump_auth_tok(candidate_auth_tok); - } - rc = ecryptfs_get_auth_tok_sig(&candidate_auth_tok_sig, - candidate_auth_tok); - if (rc) { - printk(KERN_ERR - "Unrecognized candidate auth tok type: [%d]\n", - candidate_auth_tok->token_type); - rc = -EINVAL; - goto out_wipe_list; - } - rc = ecryptfs_find_auth_tok_for_sig(&auth_tok_key, - &matching_auth_tok, - crypt_stat->mount_crypt_stat, - candidate_auth_tok_sig); - if (!rc) { - found_auth_tok = 1; - goto found_matching_auth_tok; - } - } - if (!found_auth_tok) { - ecryptfs_printk(KERN_ERR, "Could not find a usable " - "authentication token\n"); - rc = -EIO; - goto out_wipe_list; - } -found_matching_auth_tok: - if (candidate_auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) { - memcpy(&(candidate_auth_tok->token.private_key), - &(matching_auth_tok->token.private_key), - sizeof(struct ecryptfs_private_key)); - up_write(&(auth_tok_key->sem)); - key_put(auth_tok_key); - rc = decrypt_pki_encrypted_session_key(candidate_auth_tok, - crypt_stat); - } else if (candidate_auth_tok->token_type == ECRYPTFS_PASSWORD) { - memcpy(&(candidate_auth_tok->token.password), - &(matching_auth_tok->token.password), - sizeof(struct ecryptfs_password)); - up_write(&(auth_tok_key->sem)); - key_put(auth_tok_key); - rc = decrypt_passphrase_encrypted_session_key( - candidate_auth_tok, crypt_stat); - } else { - up_write(&(auth_tok_key->sem)); - key_put(auth_tok_key); - rc = -EINVAL; - } - if (rc) { - struct ecryptfs_auth_tok_list_item *auth_tok_list_item_tmp; - - ecryptfs_printk(KERN_WARNING, "Error decrypting the " - "session key for authentication token with sig " - "[%.*s]; rc = [%d]. Removing auth tok " - "candidate from the list and searching for " - "the next match.\n", ECRYPTFS_SIG_SIZE_HEX, - candidate_auth_tok_sig, rc); - list_for_each_entry_safe(auth_tok_list_item, - auth_tok_list_item_tmp, - &auth_tok_list, list) { - if (candidate_auth_tok - == &auth_tok_list_item->auth_tok) { - list_del(&auth_tok_list_item->list); - kmem_cache_free( - ecryptfs_auth_tok_list_item_cache, - auth_tok_list_item); - goto find_next_matching_auth_tok; - } - } - BUG(); - } - rc = ecryptfs_compute_root_iv(crypt_stat); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error computing " - "the root IV\n"); - goto out_wipe_list; - } - rc = ecryptfs_init_crypt_ctx(crypt_stat); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error initializing crypto " - "context for cipher [%s]; rc = [%d]\n", - crypt_stat->cipher, rc); - } -out_wipe_list: - wipe_auth_tok_list(&auth_tok_list); -out: - return rc; -} - -static int -pki_encrypt_session_key(struct key *auth_tok_key, - struct ecryptfs_auth_tok *auth_tok, - struct ecryptfs_crypt_stat *crypt_stat, - struct ecryptfs_key_record *key_rec) -{ - struct ecryptfs_msg_ctx *msg_ctx = NULL; - char *payload = NULL; - size_t payload_len = 0; - struct ecryptfs_message *msg; - int rc; - - rc = write_tag_66_packet(auth_tok->token.private_key.signature, - ecryptfs_code_for_cipher_string( - crypt_stat->cipher, - crypt_stat->key_size), - crypt_stat, &payload, &payload_len); - up_write(&(auth_tok_key->sem)); - key_put(auth_tok_key); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet\n"); - goto out; - } - rc = ecryptfs_send_message(payload, payload_len, &msg_ctx); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error sending message to " - "ecryptfsd\n"); - goto out; - } - rc = ecryptfs_wait_for_response(msg_ctx, &msg); - if (rc) { - ecryptfs_printk(KERN_ERR, "Failed to receive tag 67 packet " - "from the user space daemon\n"); - rc = -EIO; - goto out; - } - rc = parse_tag_67_packet(key_rec, msg); - if (rc) - ecryptfs_printk(KERN_ERR, "Error parsing tag 67 packet\n"); - kfree(msg); -out: - kfree(payload); - return rc; -} -/** - * write_tag_1_packet - Write an RFC2440-compatible tag 1 (public key) packet - * @dest: Buffer into which to write the packet - * @remaining_bytes: Maximum number of bytes that can be writtn - * @auth_tok_key: The authentication token key to unlock and put when done with - * @auth_tok - * @auth_tok: The authentication token used for generating the tag 1 packet - * @crypt_stat: The cryptographic context - * @key_rec: The key record struct for the tag 1 packet - * @packet_size: This function will write the number of bytes that end - * up constituting the packet; set to zero on error - * - * Returns zero on success; non-zero on error. - */ -static int -write_tag_1_packet(char *dest, size_t *remaining_bytes, - struct key *auth_tok_key, struct ecryptfs_auth_tok *auth_tok, - struct ecryptfs_crypt_stat *crypt_stat, - struct ecryptfs_key_record *key_rec, size_t *packet_size) -{ - size_t i; - size_t encrypted_session_key_valid = 0; - size_t packet_size_length; - size_t max_packet_size; - int rc = 0; - - (*packet_size) = 0; - ecryptfs_from_hex(key_rec->sig, auth_tok->token.private_key.signature, - ECRYPTFS_SIG_SIZE); - encrypted_session_key_valid = 0; - for (i = 0; i < crypt_stat->key_size; i++) - encrypted_session_key_valid |= - auth_tok->session_key.encrypted_key[i]; - if (encrypted_session_key_valid) { - memcpy(key_rec->enc_key, - auth_tok->session_key.encrypted_key, - auth_tok->session_key.encrypted_key_size); - up_write(&(auth_tok_key->sem)); - key_put(auth_tok_key); - goto encrypted_session_key_set; - } - if (auth_tok->session_key.encrypted_key_size == 0) - auth_tok->session_key.encrypted_key_size = - auth_tok->token.private_key.key_size; - rc = pki_encrypt_session_key(auth_tok_key, auth_tok, crypt_stat, - key_rec); - if (rc) { - printk(KERN_ERR "Failed to encrypt session key via a key " - "module; rc = [%d]\n", rc); - goto out; - } - if (ecryptfs_verbosity > 0) { - ecryptfs_printk(KERN_DEBUG, "Encrypted key:\n"); - ecryptfs_dump_hex(key_rec->enc_key, key_rec->enc_key_size); - } -encrypted_session_key_set: - /* This format is inspired by OpenPGP; see RFC 2440 - * packet tag 1 */ - max_packet_size = (1 /* Tag 1 identifier */ - + 3 /* Max Tag 1 packet size */ - + 1 /* Version */ - + ECRYPTFS_SIG_SIZE /* Key identifier */ - + 1 /* Cipher identifier */ - + key_rec->enc_key_size); /* Encrypted key size */ - if (max_packet_size > (*remaining_bytes)) { - printk(KERN_ERR "Packet length larger than maximum allowable; " - "need up to [%td] bytes, but there are only [%td] " - "available\n", max_packet_size, (*remaining_bytes)); - rc = -EINVAL; - goto out; - } - dest[(*packet_size)++] = ECRYPTFS_TAG_1_PACKET_TYPE; - rc = ecryptfs_write_packet_length(&dest[(*packet_size)], - (max_packet_size - 4), - &packet_size_length); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error generating tag 1 packet " - "header; cannot generate packet length\n"); - goto out; - } - (*packet_size) += packet_size_length; - dest[(*packet_size)++] = 0x03; /* version 3 */ - memcpy(&dest[(*packet_size)], key_rec->sig, ECRYPTFS_SIG_SIZE); - (*packet_size) += ECRYPTFS_SIG_SIZE; - dest[(*packet_size)++] = RFC2440_CIPHER_RSA; - memcpy(&dest[(*packet_size)], key_rec->enc_key, - key_rec->enc_key_size); - (*packet_size) += key_rec->enc_key_size; -out: - if (rc) - (*packet_size) = 0; - else - (*remaining_bytes) -= (*packet_size); - return rc; -} - -/** - * write_tag_11_packet - * @dest: Target into which Tag 11 packet is to be written - * @remaining_bytes: Maximum packet length - * @contents: Byte array of contents to copy in - * @contents_length: Number of bytes in contents - * @packet_length: Length of the Tag 11 packet written; zero on error - * - * Returns zero on success; non-zero on error. - */ -static int -write_tag_11_packet(char *dest, size_t *remaining_bytes, char *contents, - size_t contents_length, size_t *packet_length) -{ - size_t packet_size_length; - size_t max_packet_size; - int rc = 0; - - (*packet_length) = 0; - /* This format is inspired by OpenPGP; see RFC 2440 - * packet tag 11 */ - max_packet_size = (1 /* Tag 11 identifier */ - + 3 /* Max Tag 11 packet size */ - + 1 /* Binary format specifier */ - + 1 /* Filename length */ - + 8 /* Filename ("_CONSOLE") */ - + 4 /* Modification date */ - + contents_length); /* Literal data */ - if (max_packet_size > (*remaining_bytes)) { - printk(KERN_ERR "Packet length larger than maximum allowable; " - "need up to [%td] bytes, but there are only [%td] " - "available\n", max_packet_size, (*remaining_bytes)); - rc = -EINVAL; - goto out; - } - dest[(*packet_length)++] = ECRYPTFS_TAG_11_PACKET_TYPE; - rc = ecryptfs_write_packet_length(&dest[(*packet_length)], - (max_packet_size - 4), - &packet_size_length); - if (rc) { - printk(KERN_ERR "Error generating tag 11 packet header; cannot " - "generate packet length. rc = [%d]\n", rc); - goto out; - } - (*packet_length) += packet_size_length; - dest[(*packet_length)++] = 0x62; /* binary data format specifier */ - dest[(*packet_length)++] = 8; - memcpy(&dest[(*packet_length)], "_CONSOLE", 8); - (*packet_length) += 8; - memset(&dest[(*packet_length)], 0x00, 4); - (*packet_length) += 4; - memcpy(&dest[(*packet_length)], contents, contents_length); - (*packet_length) += contents_length; - out: - if (rc) - (*packet_length) = 0; - else - (*remaining_bytes) -= (*packet_length); - return rc; -} - -/** - * write_tag_3_packet - * @dest: Buffer into which to write the packet - * @remaining_bytes: Maximum number of bytes that can be written - * @auth_tok: Authentication token - * @crypt_stat: The cryptographic context - * @key_rec: encrypted key - * @packet_size: This function will write the number of bytes that end - * up constituting the packet; set to zero on error - * - * Returns zero on success; non-zero on error. - */ -static int -write_tag_3_packet(char *dest, size_t *remaining_bytes, - struct ecryptfs_auth_tok *auth_tok, - struct ecryptfs_crypt_stat *crypt_stat, - struct ecryptfs_key_record *key_rec, size_t *packet_size) -{ - size_t i; - size_t encrypted_session_key_valid = 0; - char session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES]; - struct scatterlist dst_sg[2]; - struct scatterlist src_sg[2]; - struct mutex *tfm_mutex = NULL; - u8 cipher_code; - size_t packet_size_length; - size_t max_packet_size; - struct ecryptfs_mount_crypt_stat *mount_crypt_stat = - crypt_stat->mount_crypt_stat; - struct blkcipher_desc desc = { - .tfm = NULL, - .flags = CRYPTO_TFM_REQ_MAY_SLEEP - }; - int rc = 0; - - (*packet_size) = 0; - ecryptfs_from_hex(key_rec->sig, auth_tok->token.password.signature, - ECRYPTFS_SIG_SIZE); - rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&desc.tfm, &tfm_mutex, - crypt_stat->cipher); - if (unlikely(rc)) { - printk(KERN_ERR "Internal error whilst attempting to get " - "tfm and mutex for cipher name [%s]; rc = [%d]\n", - crypt_stat->cipher, rc); - goto out; - } - if (mount_crypt_stat->global_default_cipher_key_size == 0) { - struct blkcipher_alg *alg = crypto_blkcipher_alg(desc.tfm); - - printk(KERN_WARNING "No key size specified at mount; " - "defaulting to [%d]\n", alg->max_keysize); - mount_crypt_stat->global_default_cipher_key_size = - alg->max_keysize; - } - if (crypt_stat->key_size == 0) - crypt_stat->key_size = - mount_crypt_stat->global_default_cipher_key_size; - if (auth_tok->session_key.encrypted_key_size == 0) - auth_tok->session_key.encrypted_key_size = - crypt_stat->key_size; - if (crypt_stat->key_size == 24 - && strcmp("aes", crypt_stat->cipher) == 0) { - memset((crypt_stat->key + 24), 0, 8); - auth_tok->session_key.encrypted_key_size = 32; - } else - auth_tok->session_key.encrypted_key_size = crypt_stat->key_size; - key_rec->enc_key_size = - auth_tok->session_key.encrypted_key_size; - encrypted_session_key_valid = 0; - for (i = 0; i < auth_tok->session_key.encrypted_key_size; i++) - encrypted_session_key_valid |= - auth_tok->session_key.encrypted_key[i]; - if (encrypted_session_key_valid) { - ecryptfs_printk(KERN_DEBUG, "encrypted_session_key_valid != 0; " - "using auth_tok->session_key.encrypted_key, " - "where key_rec->enc_key_size = [%zd]\n", - key_rec->enc_key_size); - memcpy(key_rec->enc_key, - auth_tok->session_key.encrypted_key, - key_rec->enc_key_size); - goto encrypted_session_key_set; - } - if (auth_tok->token.password.flags & - ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET) { - ecryptfs_printk(KERN_DEBUG, "Using previously generated " - "session key encryption key of size [%d]\n", - auth_tok->token.password. - session_key_encryption_key_bytes); - memcpy(session_key_encryption_key, - auth_tok->token.password.session_key_encryption_key, - crypt_stat->key_size); - ecryptfs_printk(KERN_DEBUG, - "Cached session key encryption key:\n"); - if (ecryptfs_verbosity > 0) - ecryptfs_dump_hex(session_key_encryption_key, 16); - } - if (unlikely(ecryptfs_verbosity > 0)) { - ecryptfs_printk(KERN_DEBUG, "Session key encryption key:\n"); - ecryptfs_dump_hex(session_key_encryption_key, 16); - } - rc = virt_to_scatterlist(crypt_stat->key, key_rec->enc_key_size, - src_sg, 2); - if (rc < 1 || rc > 2) { - ecryptfs_printk(KERN_ERR, "Error generating scatterlist " - "for crypt_stat session key; expected rc = 1; " - "got rc = [%d]. key_rec->enc_key_size = [%zd]\n", - rc, key_rec->enc_key_size); - rc = -ENOMEM; - goto out; - } - rc = virt_to_scatterlist(key_rec->enc_key, key_rec->enc_key_size, - dst_sg, 2); - if (rc < 1 || rc > 2) { - ecryptfs_printk(KERN_ERR, "Error generating scatterlist " - "for crypt_stat encrypted session key; " - "expected rc = 1; got rc = [%d]. " - "key_rec->enc_key_size = [%zd]\n", rc, - key_rec->enc_key_size); - rc = -ENOMEM; - goto out; - } - mutex_lock(tfm_mutex); - rc = crypto_blkcipher_setkey(desc.tfm, session_key_encryption_key, - crypt_stat->key_size); - if (rc < 0) { - mutex_unlock(tfm_mutex); - ecryptfs_printk(KERN_ERR, "Error setting key for crypto " - "context; rc = [%d]\n", rc); - goto out; - } - rc = 0; - ecryptfs_printk(KERN_DEBUG, "Encrypting [%zd] bytes of the key\n", - crypt_stat->key_size); - rc = crypto_blkcipher_encrypt(&desc, dst_sg, src_sg, - (*key_rec).enc_key_size); - mutex_unlock(tfm_mutex); - if (rc) { - printk(KERN_ERR "Error encrypting; rc = [%d]\n", rc); - goto out; - } - ecryptfs_printk(KERN_DEBUG, "This should be the encrypted key:\n"); - if (ecryptfs_verbosity > 0) { - ecryptfs_printk(KERN_DEBUG, "EFEK of size [%zd]:\n", - key_rec->enc_key_size); - ecryptfs_dump_hex(key_rec->enc_key, - key_rec->enc_key_size); - } -encrypted_session_key_set: - /* This format is inspired by OpenPGP; see RFC 2440 - * packet tag 3 */ - max_packet_size = (1 /* Tag 3 identifier */ - + 3 /* Max Tag 3 packet size */ - + 1 /* Version */ - + 1 /* Cipher code */ - + 1 /* S2K specifier */ - + 1 /* Hash identifier */ - + ECRYPTFS_SALT_SIZE /* Salt */ - + 1 /* Hash iterations */ - + key_rec->enc_key_size); /* Encrypted key size */ - if (max_packet_size > (*remaining_bytes)) { - printk(KERN_ERR "Packet too large; need up to [%td] bytes, but " - "there are only [%td] available\n", max_packet_size, - (*remaining_bytes)); - rc = -EINVAL; - goto out; - } - dest[(*packet_size)++] = ECRYPTFS_TAG_3_PACKET_TYPE; - /* Chop off the Tag 3 identifier(1) and Tag 3 packet size(3) - * to get the number of octets in the actual Tag 3 packet */ - rc = ecryptfs_write_packet_length(&dest[(*packet_size)], - (max_packet_size - 4), - &packet_size_length); - if (rc) { - printk(KERN_ERR "Error generating tag 3 packet header; cannot " - "generate packet length. rc = [%d]\n", rc); - goto out; - } - (*packet_size) += packet_size_length; - dest[(*packet_size)++] = 0x04; /* version 4 */ - /* TODO: Break from RFC2440 so that arbitrary ciphers can be - * specified with strings */ - cipher_code = ecryptfs_code_for_cipher_string(crypt_stat->cipher, - crypt_stat->key_size); - if (cipher_code == 0) { - ecryptfs_printk(KERN_WARNING, "Unable to generate code for " - "cipher [%s]\n", crypt_stat->cipher); - rc = -EINVAL; - goto out; - } - dest[(*packet_size)++] = cipher_code; - dest[(*packet_size)++] = 0x03; /* S2K */ - dest[(*packet_size)++] = 0x01; /* MD5 (TODO: parameterize) */ - memcpy(&dest[(*packet_size)], auth_tok->token.password.salt, - ECRYPTFS_SALT_SIZE); - (*packet_size) += ECRYPTFS_SALT_SIZE; /* salt */ - dest[(*packet_size)++] = 0x60; /* hash iterations (65536) */ - memcpy(&dest[(*packet_size)], key_rec->enc_key, - key_rec->enc_key_size); - (*packet_size) += key_rec->enc_key_size; -out: - if (rc) - (*packet_size) = 0; - else - (*remaining_bytes) -= (*packet_size); - return rc; -} - -struct kmem_cache *ecryptfs_key_record_cache; - -/** - * ecryptfs_generate_key_packet_set - * @dest_base: Virtual address from which to write the key record set - * @crypt_stat: The cryptographic context from which the - * authentication tokens will be retrieved - * @ecryptfs_dentry: The dentry, used to retrieve the mount crypt stat - * for the global parameters - * @len: The amount written - * @max: The maximum amount of data allowed to be written - * - * Generates a key packet set and writes it to the virtual address - * passed in. - * - * Returns zero on success; non-zero on error. - */ -int -ecryptfs_generate_key_packet_set(char *dest_base, - struct ecryptfs_crypt_stat *crypt_stat, - struct dentry *ecryptfs_dentry, size_t *len, - size_t max) -{ - struct ecryptfs_auth_tok *auth_tok; - struct key *auth_tok_key = NULL; - struct ecryptfs_mount_crypt_stat *mount_crypt_stat = - &ecryptfs_superblock_to_private( - ecryptfs_dentry->d_sb)->mount_crypt_stat; - size_t written; - struct ecryptfs_key_record *key_rec; - struct ecryptfs_key_sig *key_sig; - int rc = 0; - - (*len) = 0; - mutex_lock(&crypt_stat->keysig_list_mutex); - key_rec = kmem_cache_alloc(ecryptfs_key_record_cache, GFP_KERNEL); - if (!key_rec) { - rc = -ENOMEM; - goto out; - } - list_for_each_entry(key_sig, &crypt_stat->keysig_list, - crypt_stat_list) { - memset(key_rec, 0, sizeof(*key_rec)); - rc = ecryptfs_find_global_auth_tok_for_sig(&auth_tok_key, - &auth_tok, - mount_crypt_stat, - key_sig->keysig); - if (rc) { - printk(KERN_WARNING "Unable to retrieve auth tok with " - "sig = [%s]\n", key_sig->keysig); - rc = process_find_global_auth_tok_for_sig_err(rc); - goto out_free; - } - if (auth_tok->token_type == ECRYPTFS_PASSWORD) { - rc = write_tag_3_packet((dest_base + (*len)), - &max, auth_tok, - crypt_stat, key_rec, - &written); - up_write(&(auth_tok_key->sem)); - key_put(auth_tok_key); - if (rc) { - ecryptfs_printk(KERN_WARNING, "Error " - "writing tag 3 packet\n"); - goto out_free; - } - (*len) += written; - /* Write auth tok signature packet */ - rc = write_tag_11_packet((dest_base + (*len)), &max, - key_rec->sig, - ECRYPTFS_SIG_SIZE, &written); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error writing " - "auth tok signature packet\n"); - goto out_free; - } - (*len) += written; - } else if (auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) { - rc = write_tag_1_packet(dest_base + (*len), &max, - auth_tok_key, auth_tok, - crypt_stat, key_rec, &written); - if (rc) { - ecryptfs_printk(KERN_WARNING, "Error " - "writing tag 1 packet\n"); - goto out_free; - } - (*len) += written; - } else { - up_write(&(auth_tok_key->sem)); - key_put(auth_tok_key); - ecryptfs_printk(KERN_WARNING, "Unsupported " - "authentication token type\n"); - rc = -EINVAL; - goto out_free; - } - } - if (likely(max > 0)) { - dest_base[(*len)] = 0x00; - } else { - ecryptfs_printk(KERN_ERR, "Error writing boundary byte\n"); - rc = -EIO; - } -out_free: - kmem_cache_free(ecryptfs_key_record_cache, key_rec); -out: - if (rc) - (*len) = 0; - mutex_unlock(&crypt_stat->keysig_list_mutex); - return rc; -} - -struct kmem_cache *ecryptfs_key_sig_cache; - -int ecryptfs_add_keysig(struct ecryptfs_crypt_stat *crypt_stat, char *sig) -{ - struct ecryptfs_key_sig *new_key_sig; - - new_key_sig = kmem_cache_alloc(ecryptfs_key_sig_cache, GFP_KERNEL); - if (!new_key_sig) { - printk(KERN_ERR - "Error allocating from ecryptfs_key_sig_cache\n"); - return -ENOMEM; - } - memcpy(new_key_sig->keysig, sig, ECRYPTFS_SIG_SIZE_HEX); - new_key_sig->keysig[ECRYPTFS_SIG_SIZE_HEX] = '\0'; - /* Caller must hold keysig_list_mutex */ - list_add(&new_key_sig->crypt_stat_list, &crypt_stat->keysig_list); - - return 0; -} - -struct kmem_cache *ecryptfs_global_auth_tok_cache; - -int -ecryptfs_add_global_auth_tok(struct ecryptfs_mount_crypt_stat *mount_crypt_stat, - char *sig, u32 global_auth_tok_flags) -{ - struct ecryptfs_global_auth_tok *new_auth_tok; - int rc = 0; - - new_auth_tok = kmem_cache_zalloc(ecryptfs_global_auth_tok_cache, - GFP_KERNEL); - if (!new_auth_tok) { - rc = -ENOMEM; - printk(KERN_ERR "Error allocating from " - "ecryptfs_global_auth_tok_cache\n"); - goto out; - } - memcpy(new_auth_tok->sig, sig, ECRYPTFS_SIG_SIZE_HEX); - new_auth_tok->flags = global_auth_tok_flags; - new_auth_tok->sig[ECRYPTFS_SIG_SIZE_HEX] = '\0'; - mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex); - list_add(&new_auth_tok->mount_crypt_stat_list, - &mount_crypt_stat->global_auth_tok_list); - mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex); -out: - return rc; -} - diff --git a/ANDROID_3.4.5/fs/ecryptfs/kthread.c b/ANDROID_3.4.5/fs/ecryptfs/kthread.c deleted file mode 100644 index 0dbe58a8..00000000 --- a/ANDROID_3.4.5/fs/ecryptfs/kthread.c +++ /dev/null @@ -1,197 +0,0 @@ -/** - * eCryptfs: Linux filesystem encryption layer - * - * Copyright (C) 2008 International Business Machines Corp. - * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <linux/kthread.h> -#include <linux/freezer.h> -#include <linux/slab.h> -#include <linux/wait.h> -#include <linux/mount.h> -#include "ecryptfs_kernel.h" - -struct kmem_cache *ecryptfs_open_req_cache; - -static struct ecryptfs_kthread_ctl { -#define ECRYPTFS_KTHREAD_ZOMBIE 0x00000001 - u32 flags; - struct mutex mux; - struct list_head req_list; - wait_queue_head_t wait; -} ecryptfs_kthread_ctl; - -static struct task_struct *ecryptfs_kthread; - -/** - * ecryptfs_threadfn - * @ignored: ignored - * - * The eCryptfs kernel thread that has the responsibility of getting - * the lower file with RW permissions. - * - * Returns zero on success; non-zero otherwise - */ -static int ecryptfs_threadfn(void *ignored) -{ - set_freezable(); - while (1) { - struct ecryptfs_open_req *req; - - wait_event_freezable( - ecryptfs_kthread_ctl.wait, - (!list_empty(&ecryptfs_kthread_ctl.req_list) - || kthread_should_stop())); - mutex_lock(&ecryptfs_kthread_ctl.mux); - if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) { - mutex_unlock(&ecryptfs_kthread_ctl.mux); - goto out; - } - while (!list_empty(&ecryptfs_kthread_ctl.req_list)) { - req = list_first_entry(&ecryptfs_kthread_ctl.req_list, - struct ecryptfs_open_req, - kthread_ctl_list); - mutex_lock(&req->mux); - list_del(&req->kthread_ctl_list); - if (!(req->flags & ECRYPTFS_REQ_ZOMBIE)) { - dget(req->lower_dentry); - mntget(req->lower_mnt); - (*req->lower_file) = dentry_open( - req->lower_dentry, req->lower_mnt, - (O_RDWR | O_LARGEFILE), current_cred()); - req->flags |= ECRYPTFS_REQ_PROCESSED; - } - wake_up(&req->wait); - mutex_unlock(&req->mux); - } - mutex_unlock(&ecryptfs_kthread_ctl.mux); - } -out: - return 0; -} - -int __init ecryptfs_init_kthread(void) -{ - int rc = 0; - - mutex_init(&ecryptfs_kthread_ctl.mux); - init_waitqueue_head(&ecryptfs_kthread_ctl.wait); - INIT_LIST_HEAD(&ecryptfs_kthread_ctl.req_list); - ecryptfs_kthread = kthread_run(&ecryptfs_threadfn, NULL, - "ecryptfs-kthread"); - if (IS_ERR(ecryptfs_kthread)) { - rc = PTR_ERR(ecryptfs_kthread); - printk(KERN_ERR "%s: Failed to create kernel thread; rc = [%d]" - "\n", __func__, rc); - } - return rc; -} - -void ecryptfs_destroy_kthread(void) -{ - struct ecryptfs_open_req *req; - - mutex_lock(&ecryptfs_kthread_ctl.mux); - ecryptfs_kthread_ctl.flags |= ECRYPTFS_KTHREAD_ZOMBIE; - list_for_each_entry(req, &ecryptfs_kthread_ctl.req_list, - kthread_ctl_list) { - mutex_lock(&req->mux); - req->flags |= ECRYPTFS_REQ_ZOMBIE; - wake_up(&req->wait); - mutex_unlock(&req->mux); - } - mutex_unlock(&ecryptfs_kthread_ctl.mux); - kthread_stop(ecryptfs_kthread); - wake_up(&ecryptfs_kthread_ctl.wait); -} - -/** - * ecryptfs_privileged_open - * @lower_file: Result of dentry_open by root on lower dentry - * @lower_dentry: Lower dentry for file to open - * @lower_mnt: Lower vfsmount for file to open - * - * This function gets a r/w file opened againt the lower dentry. - * - * Returns zero on success; non-zero otherwise - */ -int ecryptfs_privileged_open(struct file **lower_file, - struct dentry *lower_dentry, - struct vfsmount *lower_mnt, - const struct cred *cred) -{ - struct ecryptfs_open_req *req; - int flags = O_LARGEFILE; - int rc = 0; - - /* Corresponding dput() and mntput() are done when the - * lower file is fput() when all eCryptfs files for the inode are - * released. */ - dget(lower_dentry); - mntget(lower_mnt); - flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR; - (*lower_file) = dentry_open(lower_dentry, lower_mnt, flags, cred); - if (!IS_ERR(*lower_file)) - goto out; - if ((flags & O_ACCMODE) == O_RDONLY) { - rc = PTR_ERR((*lower_file)); - goto out; - } - req = kmem_cache_alloc(ecryptfs_open_req_cache, GFP_KERNEL); - if (!req) { - rc = -ENOMEM; - goto out; - } - mutex_init(&req->mux); - req->lower_file = lower_file; - req->lower_dentry = lower_dentry; - req->lower_mnt = lower_mnt; - init_waitqueue_head(&req->wait); - req->flags = 0; - mutex_lock(&ecryptfs_kthread_ctl.mux); - if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) { - rc = -EIO; - mutex_unlock(&ecryptfs_kthread_ctl.mux); - printk(KERN_ERR "%s: We are in the middle of shutting down; " - "aborting privileged request to open lower file\n", - __func__); - goto out_free; - } - list_add_tail(&req->kthread_ctl_list, &ecryptfs_kthread_ctl.req_list); - mutex_unlock(&ecryptfs_kthread_ctl.mux); - wake_up(&ecryptfs_kthread_ctl.wait); - wait_event(req->wait, (req->flags != 0)); - mutex_lock(&req->mux); - BUG_ON(req->flags == 0); - if (req->flags & ECRYPTFS_REQ_DROPPED - || req->flags & ECRYPTFS_REQ_ZOMBIE) { - rc = -EIO; - printk(KERN_WARNING "%s: Privileged open request dropped\n", - __func__); - goto out_unlock; - } - if (IS_ERR(*req->lower_file)) - rc = PTR_ERR(*req->lower_file); -out_unlock: - mutex_unlock(&req->mux); -out_free: - kmem_cache_free(ecryptfs_open_req_cache, req); -out: - return rc; -} diff --git a/ANDROID_3.4.5/fs/ecryptfs/main.c b/ANDROID_3.4.5/fs/ecryptfs/main.c deleted file mode 100644 index 68954937..00000000 --- a/ANDROID_3.4.5/fs/ecryptfs/main.c +++ /dev/null @@ -1,866 +0,0 @@ -/** - * eCryptfs: Linux filesystem encryption layer - * - * Copyright (C) 1997-2003 Erez Zadok - * Copyright (C) 2001-2003 Stony Brook University - * Copyright (C) 2004-2007 International Business Machines Corp. - * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> - * Michael C. Thompson <mcthomps@us.ibm.com> - * Tyler Hicks <tyhicks@ou.edu> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <linux/dcache.h> -#include <linux/file.h> -#include <linux/module.h> -#include <linux/namei.h> -#include <linux/skbuff.h> -#include <linux/crypto.h> -#include <linux/mount.h> -#include <linux/pagemap.h> -#include <linux/key.h> -#include <linux/parser.h> -#include <linux/fs_stack.h> -#include <linux/slab.h> -#include <linux/magic.h> -#include "ecryptfs_kernel.h" - -/** - * Module parameter that defines the ecryptfs_verbosity level. - */ -int ecryptfs_verbosity = 0; - -module_param(ecryptfs_verbosity, int, 0); -MODULE_PARM_DESC(ecryptfs_verbosity, - "Initial verbosity level (0 or 1; defaults to " - "0, which is Quiet)"); - -/** - * Module parameter that defines the number of message buffer elements - */ -unsigned int ecryptfs_message_buf_len = ECRYPTFS_DEFAULT_MSG_CTX_ELEMS; - -module_param(ecryptfs_message_buf_len, uint, 0); -MODULE_PARM_DESC(ecryptfs_message_buf_len, - "Number of message buffer elements"); - -/** - * Module parameter that defines the maximum guaranteed amount of time to wait - * for a response from ecryptfsd. The actual sleep time will be, more than - * likely, a small amount greater than this specified value, but only less if - * the message successfully arrives. - */ -signed long ecryptfs_message_wait_timeout = ECRYPTFS_MAX_MSG_CTX_TTL / HZ; - -module_param(ecryptfs_message_wait_timeout, long, 0); -MODULE_PARM_DESC(ecryptfs_message_wait_timeout, - "Maximum number of seconds that an operation will " - "sleep while waiting for a message response from " - "userspace"); - -/** - * Module parameter that is an estimate of the maximum number of users - * that will be concurrently using eCryptfs. Set this to the right - * value to balance performance and memory use. - */ -unsigned int ecryptfs_number_of_users = ECRYPTFS_DEFAULT_NUM_USERS; - -module_param(ecryptfs_number_of_users, uint, 0); -MODULE_PARM_DESC(ecryptfs_number_of_users, "An estimate of the number of " - "concurrent users of eCryptfs"); - -void __ecryptfs_printk(const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - if (fmt[1] == '7') { /* KERN_DEBUG */ - if (ecryptfs_verbosity >= 1) - vprintk(fmt, args); - } else - vprintk(fmt, args); - va_end(args); -} - -/** - * ecryptfs_init_lower_file - * @ecryptfs_dentry: Fully initialized eCryptfs dentry object, with - * the lower dentry and the lower mount set - * - * eCryptfs only ever keeps a single open file for every lower - * inode. All I/O operations to the lower inode occur through that - * file. When the first eCryptfs dentry that interposes with the first - * lower dentry for that inode is created, this function creates the - * lower file struct and associates it with the eCryptfs - * inode. When all eCryptfs files associated with the inode are released, the - * file is closed. - * - * The lower file will be opened with read/write permissions, if - * possible. Otherwise, it is opened read-only. - * - * This function does nothing if a lower file is already - * associated with the eCryptfs inode. - * - * Returns zero on success; non-zero otherwise - */ -static int ecryptfs_init_lower_file(struct dentry *dentry, - struct file **lower_file) -{ - const struct cred *cred = current_cred(); - struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); - struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); - int rc; - - rc = ecryptfs_privileged_open(lower_file, lower_dentry, lower_mnt, - cred); - if (rc) { - printk(KERN_ERR "Error opening lower file " - "for lower_dentry [0x%p] and lower_mnt [0x%p]; " - "rc = [%d]\n", lower_dentry, lower_mnt, rc); - (*lower_file) = NULL; - } - return rc; -} - -int ecryptfs_get_lower_file(struct dentry *dentry, struct inode *inode) -{ - struct ecryptfs_inode_info *inode_info; - int count, rc = 0; - - inode_info = ecryptfs_inode_to_private(inode); - mutex_lock(&inode_info->lower_file_mutex); - count = atomic_inc_return(&inode_info->lower_file_count); - if (WARN_ON_ONCE(count < 1)) - rc = -EINVAL; - else if (count == 1) { - rc = ecryptfs_init_lower_file(dentry, - &inode_info->lower_file); - if (rc) - atomic_set(&inode_info->lower_file_count, 0); - } - mutex_unlock(&inode_info->lower_file_mutex); - return rc; -} - -void ecryptfs_put_lower_file(struct inode *inode) -{ - struct ecryptfs_inode_info *inode_info; - - inode_info = ecryptfs_inode_to_private(inode); - if (atomic_dec_and_mutex_lock(&inode_info->lower_file_count, - &inode_info->lower_file_mutex)) { - fput(inode_info->lower_file); - inode_info->lower_file = NULL; - mutex_unlock(&inode_info->lower_file_mutex); - } -} - -enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig, - ecryptfs_opt_cipher, ecryptfs_opt_ecryptfs_cipher, - ecryptfs_opt_ecryptfs_key_bytes, - ecryptfs_opt_passthrough, ecryptfs_opt_xattr_metadata, - ecryptfs_opt_encrypted_view, ecryptfs_opt_fnek_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, - ecryptfs_opt_err }; - -static const match_table_t tokens = { - {ecryptfs_opt_sig, "sig=%s"}, - {ecryptfs_opt_ecryptfs_sig, "ecryptfs_sig=%s"}, - {ecryptfs_opt_cipher, "cipher=%s"}, - {ecryptfs_opt_ecryptfs_cipher, "ecryptfs_cipher=%s"}, - {ecryptfs_opt_ecryptfs_key_bytes, "ecryptfs_key_bytes=%u"}, - {ecryptfs_opt_passthrough, "ecryptfs_passthrough"}, - {ecryptfs_opt_xattr_metadata, "ecryptfs_xattr_metadata"}, - {ecryptfs_opt_encrypted_view, "ecryptfs_encrypted_view"}, - {ecryptfs_opt_fnek_sig, "ecryptfs_fnek_sig=%s"}, - {ecryptfs_opt_fn_cipher, "ecryptfs_fn_cipher=%s"}, - {ecryptfs_opt_fn_cipher_key_bytes, "ecryptfs_fn_key_bytes=%u"}, - {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"}, - {ecryptfs_opt_err, NULL} -}; - -static int ecryptfs_init_global_auth_toks( - struct ecryptfs_mount_crypt_stat *mount_crypt_stat) -{ - struct ecryptfs_global_auth_tok *global_auth_tok; - struct ecryptfs_auth_tok *auth_tok; - int rc = 0; - - list_for_each_entry(global_auth_tok, - &mount_crypt_stat->global_auth_tok_list, - mount_crypt_stat_list) { - rc = ecryptfs_keyring_auth_tok_for_sig( - &global_auth_tok->global_auth_tok_key, &auth_tok, - global_auth_tok->sig); - if (rc) { - printk(KERN_ERR "Could not find valid key in user " - "session keyring for sig specified in mount " - "option: [%s]\n", global_auth_tok->sig); - global_auth_tok->flags |= ECRYPTFS_AUTH_TOK_INVALID; - goto out; - } else { - global_auth_tok->flags &= ~ECRYPTFS_AUTH_TOK_INVALID; - up_write(&(global_auth_tok->global_auth_tok_key)->sem); - } - } -out: - return rc; -} - -static void ecryptfs_init_mount_crypt_stat( - struct ecryptfs_mount_crypt_stat *mount_crypt_stat) -{ - memset((void *)mount_crypt_stat, 0, - sizeof(struct ecryptfs_mount_crypt_stat)); - INIT_LIST_HEAD(&mount_crypt_stat->global_auth_tok_list); - mutex_init(&mount_crypt_stat->global_auth_tok_list_mutex); - mount_crypt_stat->flags |= ECRYPTFS_MOUNT_CRYPT_STAT_INITIALIZED; -} - -/** - * ecryptfs_parse_options - * @sb: The ecryptfs super block - * @options: The options passed to the kernel - * @check_ruid: set to 1 if device uid should be checked against the ruid - * - * Parse mount options: - * debug=N - ecryptfs_verbosity level for debug output - * sig=XXX - description(signature) of the key to use - * - * Returns the dentry object of the lower-level (lower/interposed) - * directory; We want to mount our stackable file system on top of - * that lower directory. - * - * The signature of the key to use must be the description of a key - * already in the keyring. Mounting will fail if the key can not be - * found. - * - * Returns zero on success; non-zero on error - */ -static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options, - uid_t *check_ruid) -{ - char *p; - int rc = 0; - int sig_set = 0; - int cipher_name_set = 0; - int fn_cipher_name_set = 0; - int cipher_key_bytes; - int cipher_key_bytes_set = 0; - int fn_cipher_key_bytes; - int fn_cipher_key_bytes_set = 0; - struct ecryptfs_mount_crypt_stat *mount_crypt_stat = - &sbi->mount_crypt_stat; - substring_t args[MAX_OPT_ARGS]; - int token; - char *sig_src; - char *cipher_name_dst; - char *cipher_name_src; - char *fn_cipher_name_dst; - char *fn_cipher_name_src; - char *fnek_dst; - char *fnek_src; - char *cipher_key_bytes_src; - char *fn_cipher_key_bytes_src; - - *check_ruid = 0; - - if (!options) { - rc = -EINVAL; - goto out; - } - ecryptfs_init_mount_crypt_stat(mount_crypt_stat); - while ((p = strsep(&options, ",")) != NULL) { - if (!*p) - continue; - token = match_token(p, tokens, args); - switch (token) { - case ecryptfs_opt_sig: - case ecryptfs_opt_ecryptfs_sig: - sig_src = args[0].from; - rc = ecryptfs_add_global_auth_tok(mount_crypt_stat, - sig_src, 0); - if (rc) { - printk(KERN_ERR "Error attempting to register " - "global sig; rc = [%d]\n", rc); - goto out; - } - sig_set = 1; - break; - case ecryptfs_opt_cipher: - case ecryptfs_opt_ecryptfs_cipher: - cipher_name_src = args[0].from; - cipher_name_dst = - mount_crypt_stat-> - global_default_cipher_name; - strncpy(cipher_name_dst, cipher_name_src, - ECRYPTFS_MAX_CIPHER_NAME_SIZE); - cipher_name_dst[ECRYPTFS_MAX_CIPHER_NAME_SIZE] = '\0'; - cipher_name_set = 1; - break; - case ecryptfs_opt_ecryptfs_key_bytes: - cipher_key_bytes_src = args[0].from; - cipher_key_bytes = - (int)simple_strtol(cipher_key_bytes_src, - &cipher_key_bytes_src, 0); - mount_crypt_stat->global_default_cipher_key_size = - cipher_key_bytes; - cipher_key_bytes_set = 1; - break; - case ecryptfs_opt_passthrough: - mount_crypt_stat->flags |= - ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED; - break; - case ecryptfs_opt_xattr_metadata: - mount_crypt_stat->flags |= - ECRYPTFS_XATTR_METADATA_ENABLED; - break; - case ecryptfs_opt_encrypted_view: - mount_crypt_stat->flags |= - ECRYPTFS_XATTR_METADATA_ENABLED; - mount_crypt_stat->flags |= - ECRYPTFS_ENCRYPTED_VIEW_ENABLED; - break; - case ecryptfs_opt_fnek_sig: - fnek_src = args[0].from; - fnek_dst = - mount_crypt_stat->global_default_fnek_sig; - strncpy(fnek_dst, fnek_src, ECRYPTFS_SIG_SIZE_HEX); - mount_crypt_stat->global_default_fnek_sig[ - ECRYPTFS_SIG_SIZE_HEX] = '\0'; - rc = ecryptfs_add_global_auth_tok( - mount_crypt_stat, - mount_crypt_stat->global_default_fnek_sig, - ECRYPTFS_AUTH_TOK_FNEK); - if (rc) { - printk(KERN_ERR "Error attempting to register " - "global fnek sig [%s]; rc = [%d]\n", - mount_crypt_stat->global_default_fnek_sig, - rc); - goto out; - } - mount_crypt_stat->flags |= - (ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES - | ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK); - break; - case ecryptfs_opt_fn_cipher: - fn_cipher_name_src = args[0].from; - fn_cipher_name_dst = - mount_crypt_stat->global_default_fn_cipher_name; - strncpy(fn_cipher_name_dst, fn_cipher_name_src, - ECRYPTFS_MAX_CIPHER_NAME_SIZE); - mount_crypt_stat->global_default_fn_cipher_name[ - ECRYPTFS_MAX_CIPHER_NAME_SIZE] = '\0'; - fn_cipher_name_set = 1; - break; - case ecryptfs_opt_fn_cipher_key_bytes: - fn_cipher_key_bytes_src = args[0].from; - fn_cipher_key_bytes = - (int)simple_strtol(fn_cipher_key_bytes_src, - &fn_cipher_key_bytes_src, 0); - mount_crypt_stat->global_default_fn_cipher_key_bytes = - fn_cipher_key_bytes; - fn_cipher_key_bytes_set = 1; - break; - case ecryptfs_opt_unlink_sigs: - mount_crypt_stat->flags |= ECRYPTFS_UNLINK_SIGS; - break; - case ecryptfs_opt_mount_auth_tok_only: - mount_crypt_stat->flags |= - ECRYPTFS_GLOBAL_MOUNT_AUTH_TOK_ONLY; - break; - case ecryptfs_opt_check_dev_ruid: - *check_ruid = 1; - break; - case ecryptfs_opt_err: - default: - printk(KERN_WARNING - "%s: eCryptfs: unrecognized option [%s]\n", - __func__, p); - } - } - if (!sig_set) { - rc = -EINVAL; - ecryptfs_printk(KERN_ERR, "You must supply at least one valid " - "auth tok signature as a mount " - "parameter; see the eCryptfs README\n"); - goto out; - } - if (!cipher_name_set) { - int cipher_name_len = strlen(ECRYPTFS_DEFAULT_CIPHER); - - BUG_ON(cipher_name_len >= ECRYPTFS_MAX_CIPHER_NAME_SIZE); - strcpy(mount_crypt_stat->global_default_cipher_name, - ECRYPTFS_DEFAULT_CIPHER); - } - if ((mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) - && !fn_cipher_name_set) - strcpy(mount_crypt_stat->global_default_fn_cipher_name, - mount_crypt_stat->global_default_cipher_name); - if (!cipher_key_bytes_set) - mount_crypt_stat->global_default_cipher_key_size = 0; - if ((mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) - && !fn_cipher_key_bytes_set) - mount_crypt_stat->global_default_fn_cipher_key_bytes = - mount_crypt_stat->global_default_cipher_key_size; - mutex_lock(&key_tfm_list_mutex); - if (!ecryptfs_tfm_exists(mount_crypt_stat->global_default_cipher_name, - NULL)) { - rc = ecryptfs_add_new_key_tfm( - NULL, mount_crypt_stat->global_default_cipher_name, - mount_crypt_stat->global_default_cipher_key_size); - if (rc) { - printk(KERN_ERR "Error attempting to initialize " - "cipher with name = [%s] and key size = [%td]; " - "rc = [%d]\n", - mount_crypt_stat->global_default_cipher_name, - mount_crypt_stat->global_default_cipher_key_size, - rc); - rc = -EINVAL; - mutex_unlock(&key_tfm_list_mutex); - goto out; - } - } - if ((mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) - && !ecryptfs_tfm_exists( - mount_crypt_stat->global_default_fn_cipher_name, NULL)) { - rc = ecryptfs_add_new_key_tfm( - NULL, mount_crypt_stat->global_default_fn_cipher_name, - mount_crypt_stat->global_default_fn_cipher_key_bytes); - if (rc) { - printk(KERN_ERR "Error attempting to initialize " - "cipher with name = [%s] and key size = [%td]; " - "rc = [%d]\n", - mount_crypt_stat->global_default_fn_cipher_name, - mount_crypt_stat->global_default_fn_cipher_key_bytes, - rc); - rc = -EINVAL; - mutex_unlock(&key_tfm_list_mutex); - goto out; - } - } - mutex_unlock(&key_tfm_list_mutex); - rc = ecryptfs_init_global_auth_toks(mount_crypt_stat); - if (rc) - printk(KERN_WARNING "One or more global auth toks could not " - "properly register; rc = [%d]\n", rc); -out: - return rc; -} - -struct kmem_cache *ecryptfs_sb_info_cache; -static struct file_system_type ecryptfs_fs_type; - -/** - * ecryptfs_get_sb - * @fs_type - * @flags - * @dev_name: The path to mount over - * @raw_data: The options passed into the kernel - */ -static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags, - const char *dev_name, void *raw_data) -{ - struct super_block *s; - struct ecryptfs_sb_info *sbi; - struct ecryptfs_dentry_info *root_info; - const char *err = "Getting sb failed"; - struct inode *inode; - struct path path; - uid_t check_ruid; - int rc; - - sbi = kmem_cache_zalloc(ecryptfs_sb_info_cache, GFP_KERNEL); - if (!sbi) { - rc = -ENOMEM; - goto out; - } - - rc = ecryptfs_parse_options(sbi, raw_data, &check_ruid); - if (rc) { - err = "Error parsing options"; - goto out; - } - - s = sget(fs_type, NULL, set_anon_super, NULL); - if (IS_ERR(s)) { - rc = PTR_ERR(s); - goto out; - } - - s->s_flags = flags; - rc = bdi_setup_and_register(&sbi->bdi, "ecryptfs", BDI_CAP_MAP_COPY); - if (rc) - goto out1; - - ecryptfs_set_superblock_private(s, sbi); - s->s_bdi = &sbi->bdi; - - /* ->kill_sb() will take care of sbi after that point */ - sbi = NULL; - s->s_op = &ecryptfs_sops; - s->s_d_op = &ecryptfs_dops; - - err = "Reading sb failed"; - rc = kern_path(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path); - if (rc) { - ecryptfs_printk(KERN_WARNING, "kern_path() failed\n"); - goto out1; - } - if (path.dentry->d_sb->s_type == &ecryptfs_fs_type) { - rc = -EINVAL; - printk(KERN_ERR "Mount on filesystem of type " - "eCryptfs explicitly disallowed due to " - "known incompatibilities\n"); - goto out_free; - } - - if (check_ruid && path.dentry->d_inode->i_uid != current_uid()) { - rc = -EPERM; - printk(KERN_ERR "Mount of device (uid: %d) not owned by " - "requested user (uid: %d)\n", - path.dentry->d_inode->i_uid, current_uid()); - goto out_free; - } - - ecryptfs_set_superblock_lower(s, path.dentry->d_sb); - s->s_maxbytes = path.dentry->d_sb->s_maxbytes; - s->s_blocksize = path.dentry->d_sb->s_blocksize; - s->s_magic = ECRYPTFS_SUPER_MAGIC; - - inode = ecryptfs_get_inode(path.dentry->d_inode, s); - rc = PTR_ERR(inode); - if (IS_ERR(inode)) - goto out_free; - - s->s_root = d_make_root(inode); - if (!s->s_root) { - rc = -ENOMEM; - goto out_free; - } - - rc = -ENOMEM; - root_info = kmem_cache_zalloc(ecryptfs_dentry_info_cache, GFP_KERNEL); - if (!root_info) - goto out_free; - - /* ->kill_sb() will take care of root_info */ - ecryptfs_set_dentry_private(s->s_root, root_info); - ecryptfs_set_dentry_lower(s->s_root, path.dentry); - ecryptfs_set_dentry_lower_mnt(s->s_root, path.mnt); - - s->s_flags |= MS_ACTIVE; - return dget(s->s_root); - -out_free: - path_put(&path); -out1: - deactivate_locked_super(s); -out: - if (sbi) { - ecryptfs_destroy_mount_crypt_stat(&sbi->mount_crypt_stat); - kmem_cache_free(ecryptfs_sb_info_cache, sbi); - } - printk(KERN_ERR "%s; rc = [%d]\n", err, rc); - return ERR_PTR(rc); -} - -/** - * ecryptfs_kill_block_super - * @sb: The ecryptfs super block - * - * Used to bring the superblock down and free the private data. - */ -static void ecryptfs_kill_block_super(struct super_block *sb) -{ - struct ecryptfs_sb_info *sb_info = ecryptfs_superblock_to_private(sb); - kill_anon_super(sb); - if (!sb_info) - return; - ecryptfs_destroy_mount_crypt_stat(&sb_info->mount_crypt_stat); - bdi_destroy(&sb_info->bdi); - kmem_cache_free(ecryptfs_sb_info_cache, sb_info); -} - -static struct file_system_type ecryptfs_fs_type = { - .owner = THIS_MODULE, - .name = "ecryptfs", - .mount = ecryptfs_mount, - .kill_sb = ecryptfs_kill_block_super, - .fs_flags = 0 -}; - -/** - * inode_info_init_once - * - * Initializes the ecryptfs_inode_info_cache when it is created - */ -static void -inode_info_init_once(void *vptr) -{ - struct ecryptfs_inode_info *ei = (struct ecryptfs_inode_info *)vptr; - - inode_init_once(&ei->vfs_inode); -} - -static struct ecryptfs_cache_info { - struct kmem_cache **cache; - const char *name; - size_t size; - void (*ctor)(void *obj); -} ecryptfs_cache_infos[] = { - { - .cache = &ecryptfs_auth_tok_list_item_cache, - .name = "ecryptfs_auth_tok_list_item", - .size = sizeof(struct ecryptfs_auth_tok_list_item), - }, - { - .cache = &ecryptfs_file_info_cache, - .name = "ecryptfs_file_cache", - .size = sizeof(struct ecryptfs_file_info), - }, - { - .cache = &ecryptfs_dentry_info_cache, - .name = "ecryptfs_dentry_info_cache", - .size = sizeof(struct ecryptfs_dentry_info), - }, - { - .cache = &ecryptfs_inode_info_cache, - .name = "ecryptfs_inode_cache", - .size = sizeof(struct ecryptfs_inode_info), - .ctor = inode_info_init_once, - }, - { - .cache = &ecryptfs_sb_info_cache, - .name = "ecryptfs_sb_cache", - .size = sizeof(struct ecryptfs_sb_info), - }, - { - .cache = &ecryptfs_header_cache, - .name = "ecryptfs_headers", - .size = PAGE_CACHE_SIZE, - }, - { - .cache = &ecryptfs_xattr_cache, - .name = "ecryptfs_xattr_cache", - .size = PAGE_CACHE_SIZE, - }, - { - .cache = &ecryptfs_key_record_cache, - .name = "ecryptfs_key_record_cache", - .size = sizeof(struct ecryptfs_key_record), - }, - { - .cache = &ecryptfs_key_sig_cache, - .name = "ecryptfs_key_sig_cache", - .size = sizeof(struct ecryptfs_key_sig), - }, - { - .cache = &ecryptfs_global_auth_tok_cache, - .name = "ecryptfs_global_auth_tok_cache", - .size = sizeof(struct ecryptfs_global_auth_tok), - }, - { - .cache = &ecryptfs_key_tfm_cache, - .name = "ecryptfs_key_tfm_cache", - .size = sizeof(struct ecryptfs_key_tfm), - }, - { - .cache = &ecryptfs_open_req_cache, - .name = "ecryptfs_open_req_cache", - .size = sizeof(struct ecryptfs_open_req), - }, -}; - -static void ecryptfs_free_kmem_caches(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ecryptfs_cache_infos); i++) { - struct ecryptfs_cache_info *info; - - info = &ecryptfs_cache_infos[i]; - if (*(info->cache)) - kmem_cache_destroy(*(info->cache)); - } -} - -/** - * ecryptfs_init_kmem_caches - * - * Returns zero on success; non-zero otherwise - */ -static int ecryptfs_init_kmem_caches(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ecryptfs_cache_infos); i++) { - struct ecryptfs_cache_info *info; - - info = &ecryptfs_cache_infos[i]; - *(info->cache) = kmem_cache_create(info->name, info->size, - 0, SLAB_HWCACHE_ALIGN, info->ctor); - if (!*(info->cache)) { - ecryptfs_free_kmem_caches(); - ecryptfs_printk(KERN_WARNING, "%s: " - "kmem_cache_create failed\n", - info->name); - return -ENOMEM; - } - } - return 0; -} - -static struct kobject *ecryptfs_kobj; - -static ssize_t version_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buff) -{ - return snprintf(buff, PAGE_SIZE, "%d\n", ECRYPTFS_VERSIONING_MASK); -} - -static struct kobj_attribute version_attr = __ATTR_RO(version); - -static struct attribute *attributes[] = { - &version_attr.attr, - NULL, -}; - -static struct attribute_group attr_group = { - .attrs = attributes, -}; - -static int do_sysfs_registration(void) -{ - int rc; - - 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_group(ecryptfs_kobj, &attr_group); - if (rc) { - printk(KERN_ERR - "Unable to create ecryptfs version attributes\n"); - kobject_put(ecryptfs_kobj); - } -out: - return rc; -} - -static void do_sysfs_unregistration(void) -{ - sysfs_remove_group(ecryptfs_kobj, &attr_group); - kobject_put(ecryptfs_kobj); -} - -static int __init ecryptfs_init(void) -{ - int rc; - - if (ECRYPTFS_DEFAULT_EXTENT_SIZE > PAGE_CACHE_SIZE) { - rc = -EINVAL; - ecryptfs_printk(KERN_ERR, "The eCryptfs extent size is " - "larger than the host's page size, and so " - "eCryptfs cannot run on this system. The " - "default eCryptfs extent size is [%u] bytes; " - "the page size is [%lu] bytes.\n", - ECRYPTFS_DEFAULT_EXTENT_SIZE, - (unsigned long)PAGE_CACHE_SIZE); - goto out; - } - rc = ecryptfs_init_kmem_caches(); - if (rc) { - printk(KERN_ERR - "Failed to allocate one or more kmem_cache objects\n"); - goto out; - } - rc = do_sysfs_registration(); - if (rc) { - printk(KERN_ERR "sysfs registration failed\n"); - goto out_free_kmem_caches; - } - rc = ecryptfs_init_kthread(); - if (rc) { - printk(KERN_ERR "%s: kthread initialization failed; " - "rc = [%d]\n", __func__, rc); - goto out_do_sysfs_unregistration; - } - rc = ecryptfs_init_messaging(); - if (rc) { - printk(KERN_ERR "Failure occurred while attempting to " - "initialize the communications channel to " - "ecryptfsd\n"); - goto out_destroy_kthread; - } - rc = ecryptfs_init_crypto(); - if (rc) { - printk(KERN_ERR "Failure whilst attempting to init crypto; " - "rc = [%d]\n", rc); - goto out_release_messaging; - } - rc = register_filesystem(&ecryptfs_fs_type); - if (rc) { - printk(KERN_ERR "Failed to register filesystem\n"); - goto out_destroy_crypto; - } - if (ecryptfs_verbosity > 0) - printk(KERN_CRIT "eCryptfs verbosity set to %d. Secret values " - "will be written to the syslog!\n", ecryptfs_verbosity); - - goto out; -out_destroy_crypto: - ecryptfs_destroy_crypto(); -out_release_messaging: - ecryptfs_release_messaging(); -out_destroy_kthread: - ecryptfs_destroy_kthread(); -out_do_sysfs_unregistration: - do_sysfs_unregistration(); -out_free_kmem_caches: - ecryptfs_free_kmem_caches(); -out: - return rc; -} - -static void __exit ecryptfs_exit(void) -{ - int rc; - - rc = ecryptfs_destroy_crypto(); - if (rc) - printk(KERN_ERR "Failure whilst attempting to destroy crypto; " - "rc = [%d]\n", rc); - ecryptfs_release_messaging(); - ecryptfs_destroy_kthread(); - do_sysfs_unregistration(); - unregister_filesystem(&ecryptfs_fs_type); - ecryptfs_free_kmem_caches(); -} - -MODULE_AUTHOR("Michael A. Halcrow <mhalcrow@us.ibm.com>"); -MODULE_DESCRIPTION("eCryptfs"); - -MODULE_LICENSE("GPL"); - -module_init(ecryptfs_init) -module_exit(ecryptfs_exit) diff --git a/ANDROID_3.4.5/fs/ecryptfs/messaging.c b/ANDROID_3.4.5/fs/ecryptfs/messaging.c deleted file mode 100644 index ab224809..00000000 --- a/ANDROID_3.4.5/fs/ecryptfs/messaging.c +++ /dev/null @@ -1,578 +0,0 @@ -/** - * eCryptfs: Linux filesystem encryption layer - * - * Copyright (C) 2004-2008 International Business Machines Corp. - * Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com> - * Tyler Hicks <tyhicks@ou.edu> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/user_namespace.h> -#include <linux/nsproxy.h> -#include "ecryptfs_kernel.h" - -static LIST_HEAD(ecryptfs_msg_ctx_free_list); -static LIST_HEAD(ecryptfs_msg_ctx_alloc_list); -static struct mutex ecryptfs_msg_ctx_lists_mux; - -static struct hlist_head *ecryptfs_daemon_hash; -struct mutex ecryptfs_daemon_hash_mux; -static int ecryptfs_hash_bits; -#define ecryptfs_uid_hash(uid) \ - hash_long((unsigned long)uid, ecryptfs_hash_bits) - -static u32 ecryptfs_msg_counter; -static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr; - -/** - * ecryptfs_acquire_free_msg_ctx - * @msg_ctx: The context that was acquired from the free list - * - * Acquires a context element from the free list and locks the mutex - * on the context. Sets the msg_ctx task to current. Returns zero on - * success; non-zero on error or upon failure to acquire a free - * context element. Must be called with ecryptfs_msg_ctx_lists_mux - * held. - */ -static int ecryptfs_acquire_free_msg_ctx(struct ecryptfs_msg_ctx **msg_ctx) -{ - struct list_head *p; - int rc; - - if (list_empty(&ecryptfs_msg_ctx_free_list)) { - printk(KERN_WARNING "%s: The eCryptfs free " - "context list is empty. It may be helpful to " - "specify the ecryptfs_message_buf_len " - "parameter to be greater than the current " - "value of [%d]\n", __func__, ecryptfs_message_buf_len); - rc = -ENOMEM; - goto out; - } - list_for_each(p, &ecryptfs_msg_ctx_free_list) { - *msg_ctx = list_entry(p, struct ecryptfs_msg_ctx, node); - if (mutex_trylock(&(*msg_ctx)->mux)) { - (*msg_ctx)->task = current; - rc = 0; - goto out; - } - } - rc = -ENOMEM; -out: - return rc; -} - -/** - * ecryptfs_msg_ctx_free_to_alloc - * @msg_ctx: The context to move from the free list to the alloc list - * - * Must be called with ecryptfs_msg_ctx_lists_mux held. - */ -static void ecryptfs_msg_ctx_free_to_alloc(struct ecryptfs_msg_ctx *msg_ctx) -{ - list_move(&msg_ctx->node, &ecryptfs_msg_ctx_alloc_list); - msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_PENDING; - msg_ctx->counter = ++ecryptfs_msg_counter; -} - -/** - * ecryptfs_msg_ctx_alloc_to_free - * @msg_ctx: The context to move from the alloc list to the free list - * - * Must be called with ecryptfs_msg_ctx_lists_mux held. - */ -void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx) -{ - list_move(&(msg_ctx->node), &ecryptfs_msg_ctx_free_list); - if (msg_ctx->msg) - kfree(msg_ctx->msg); - msg_ctx->msg = NULL; - msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_FREE; -} - -/** - * ecryptfs_find_daemon_by_euid - * @euid: The effective user id which maps to the desired daemon id - * @user_ns: The namespace in which @euid applies - * @daemon: If return value is zero, points to the desired daemon pointer - * - * Must be called with ecryptfs_daemon_hash_mux held. - * - * Search the hash list for the given user id. - * - * Returns zero if the user id exists in the list; non-zero otherwise. - */ -int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon, uid_t euid, - struct user_namespace *user_ns) -{ - struct hlist_node *elem; - int rc; - - hlist_for_each_entry(*daemon, elem, - &ecryptfs_daemon_hash[ecryptfs_uid_hash(euid)], - euid_chain) { - if ((*daemon)->euid == euid && (*daemon)->user_ns == user_ns) { - rc = 0; - goto out; - } - } - rc = -EINVAL; -out: - return rc; -} - -/** - * ecryptfs_spawn_daemon - Create and initialize a new daemon struct - * @daemon: Pointer to set to newly allocated daemon struct - * @euid: Effective user id for the daemon - * @user_ns: The namespace in which @euid applies - * @pid: Process id for the daemon - * - * Must be called ceremoniously while in possession of - * ecryptfs_sacred_daemon_hash_mux - * - * Returns zero on success; non-zero otherwise - */ -int -ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid, - struct user_namespace *user_ns, struct pid *pid) -{ - int rc = 0; - - (*daemon) = kzalloc(sizeof(**daemon), GFP_KERNEL); - if (!(*daemon)) { - rc = -ENOMEM; - printk(KERN_ERR "%s: Failed to allocate [%zd] bytes of " - "GFP_KERNEL memory\n", __func__, sizeof(**daemon)); - goto out; - } - (*daemon)->euid = euid; - (*daemon)->user_ns = get_user_ns(user_ns); - (*daemon)->pid = get_pid(pid); - (*daemon)->task = current; - mutex_init(&(*daemon)->mux); - INIT_LIST_HEAD(&(*daemon)->msg_ctx_out_queue); - init_waitqueue_head(&(*daemon)->wait); - (*daemon)->num_queued_msg_ctx = 0; - hlist_add_head(&(*daemon)->euid_chain, - &ecryptfs_daemon_hash[ecryptfs_uid_hash(euid)]); -out: - return rc; -} - -/** - * ecryptfs_exorcise_daemon - Destroy the daemon struct - * - * Must be called ceremoniously while in possession of - * ecryptfs_daemon_hash_mux and the daemon's own mux. - */ -int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon) -{ - struct ecryptfs_msg_ctx *msg_ctx, *msg_ctx_tmp; - int rc = 0; - - mutex_lock(&daemon->mux); - if ((daemon->flags & ECRYPTFS_DAEMON_IN_READ) - || (daemon->flags & ECRYPTFS_DAEMON_IN_POLL)) { - rc = -EBUSY; - printk(KERN_WARNING "%s: Attempt to destroy daemon with pid " - "[0x%p], but it is in the midst of a read or a poll\n", - __func__, daemon->pid); - mutex_unlock(&daemon->mux); - goto out; - } - list_for_each_entry_safe(msg_ctx, msg_ctx_tmp, - &daemon->msg_ctx_out_queue, daemon_out_list) { - list_del(&msg_ctx->daemon_out_list); - daemon->num_queued_msg_ctx--; - printk(KERN_WARNING "%s: Warning: dropping message that is in " - "the out queue of a dying daemon\n", __func__); - ecryptfs_msg_ctx_alloc_to_free(msg_ctx); - } - hlist_del(&daemon->euid_chain); - if (daemon->task) - wake_up_process(daemon->task); - if (daemon->pid) - put_pid(daemon->pid); - if (daemon->user_ns) - put_user_ns(daemon->user_ns); - mutex_unlock(&daemon->mux); - kzfree(daemon); -out: - return rc; -} - -/** - * ecryptfs_process_quit - * @euid: The user ID owner of the message - * @user_ns: The namespace in which @euid applies - * @pid: The process ID for the userspace program that sent the - * message - * - * Deletes the corresponding daemon for the given euid and pid, if - * it is the registered that is requesting the deletion. Returns zero - * after deleting the desired daemon; non-zero otherwise. - */ -int ecryptfs_process_quit(uid_t euid, struct user_namespace *user_ns, - struct pid *pid) -{ - struct ecryptfs_daemon *daemon; - int rc; - - mutex_lock(&ecryptfs_daemon_hash_mux); - rc = ecryptfs_find_daemon_by_euid(&daemon, euid, user_ns); - if (rc || !daemon) { - rc = -EINVAL; - printk(KERN_ERR "Received request from user [%d] to " - "unregister unrecognized daemon [0x%p]\n", euid, pid); - goto out_unlock; - } - rc = ecryptfs_exorcise_daemon(daemon); -out_unlock: - mutex_unlock(&ecryptfs_daemon_hash_mux); - return rc; -} - -/** - * ecryptfs_process_reponse - * @msg: The ecryptfs message received; the caller should sanity check - * msg->data_len and free the memory - * @pid: The process ID of the userspace application that sent the - * message - * @seq: The sequence number of the message; must match the sequence - * number for the existing message context waiting for this - * response - * - * Processes a response message after sending an operation request to - * userspace. Some other process is awaiting this response. Before - * sending out its first communications, the other process allocated a - * msg_ctx from the ecryptfs_msg_ctx_arr at a particular index. The - * response message contains this index so that we can copy over the - * response message into the msg_ctx that the process holds a - * reference to. The other process is going to wake up, check to see - * that msg_ctx->state == ECRYPTFS_MSG_CTX_STATE_DONE, and then - * proceed to read off and process the response message. Returns zero - * upon delivery to desired context element; non-zero upon delivery - * failure or error. - * - * Returns zero on success; non-zero otherwise - */ -int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, - struct user_namespace *user_ns, struct pid *pid, - u32 seq) -{ - struct ecryptfs_daemon *uninitialized_var(daemon); - struct ecryptfs_msg_ctx *msg_ctx; - size_t msg_size; - struct nsproxy *nsproxy; - struct user_namespace *tsk_user_ns; - uid_t ctx_euid; - int rc; - - if (msg->index >= ecryptfs_message_buf_len) { - rc = -EINVAL; - printk(KERN_ERR "%s: Attempt to reference " - "context buffer at index [%d]; maximum " - "allowable is [%d]\n", __func__, msg->index, - (ecryptfs_message_buf_len - 1)); - goto out; - } - msg_ctx = &ecryptfs_msg_ctx_arr[msg->index]; - mutex_lock(&msg_ctx->mux); - mutex_lock(&ecryptfs_daemon_hash_mux); - rcu_read_lock(); - nsproxy = task_nsproxy(msg_ctx->task); - if (nsproxy == NULL) { - rc = -EBADMSG; - printk(KERN_ERR "%s: Receiving process is a zombie. Dropping " - "message.\n", __func__); - rcu_read_unlock(); - mutex_unlock(&ecryptfs_daemon_hash_mux); - goto wake_up; - } - tsk_user_ns = __task_cred(msg_ctx->task)->user->user_ns; - ctx_euid = task_euid(msg_ctx->task); - rc = ecryptfs_find_daemon_by_euid(&daemon, ctx_euid, tsk_user_ns); - rcu_read_unlock(); - mutex_unlock(&ecryptfs_daemon_hash_mux); - if (rc) { - rc = -EBADMSG; - printk(KERN_WARNING "%s: User [%d] received a " - "message response from process [0x%p] but does " - "not have a registered daemon\n", __func__, - ctx_euid, pid); - goto wake_up; - } - if (ctx_euid != euid) { - rc = -EBADMSG; - printk(KERN_WARNING "%s: Received message from user " - "[%d]; expected message from user [%d]\n", __func__, - euid, ctx_euid); - goto unlock; - } - if (tsk_user_ns != user_ns) { - rc = -EBADMSG; - printk(KERN_WARNING "%s: Received message from user_ns " - "[0x%p]; expected message from user_ns [0x%p]\n", - __func__, user_ns, tsk_user_ns); - goto unlock; - } - if (daemon->pid != pid) { - rc = -EBADMSG; - printk(KERN_ERR "%s: User [%d] sent a message response " - "from an unrecognized process [0x%p]\n", - __func__, ctx_euid, pid); - goto unlock; - } - if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) { - rc = -EINVAL; - printk(KERN_WARNING "%s: Desired context element is not " - "pending a response\n", __func__); - goto unlock; - } else if (msg_ctx->counter != seq) { - rc = -EINVAL; - printk(KERN_WARNING "%s: Invalid message sequence; " - "expected [%d]; received [%d]\n", __func__, - msg_ctx->counter, seq); - goto unlock; - } - msg_size = (sizeof(*msg) + msg->data_len); - msg_ctx->msg = kmalloc(msg_size, GFP_KERNEL); - if (!msg_ctx->msg) { - rc = -ENOMEM; - printk(KERN_ERR "%s: Failed to allocate [%zd] bytes of " - "GFP_KERNEL memory\n", __func__, msg_size); - goto unlock; - } - memcpy(msg_ctx->msg, msg, msg_size); - msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_DONE; - rc = 0; -wake_up: - wake_up_process(msg_ctx->task); -unlock: - mutex_unlock(&msg_ctx->mux); -out: - return rc; -} - -/** - * ecryptfs_send_message_locked - * @data: The data to send - * @data_len: The length of data - * @msg_ctx: The message context allocated for the send - * - * Must be called with ecryptfs_daemon_hash_mux held. - * - * Returns zero on success; non-zero otherwise - */ -static int -ecryptfs_send_message_locked(char *data, int data_len, u8 msg_type, - struct ecryptfs_msg_ctx **msg_ctx) -{ - struct ecryptfs_daemon *daemon; - uid_t euid = current_euid(); - int rc; - - rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); - if (rc || !daemon) { - rc = -ENOTCONN; - printk(KERN_ERR "%s: User [%d] does not have a daemon " - "registered\n", __func__, euid); - goto out; - } - mutex_lock(&ecryptfs_msg_ctx_lists_mux); - rc = ecryptfs_acquire_free_msg_ctx(msg_ctx); - if (rc) { - mutex_unlock(&ecryptfs_msg_ctx_lists_mux); - printk(KERN_WARNING "%s: Could not claim a free " - "context element\n", __func__); - goto out; - } - ecryptfs_msg_ctx_free_to_alloc(*msg_ctx); - mutex_unlock(&(*msg_ctx)->mux); - mutex_unlock(&ecryptfs_msg_ctx_lists_mux); - rc = ecryptfs_send_miscdev(data, data_len, *msg_ctx, msg_type, 0, - daemon); - if (rc) - printk(KERN_ERR "%s: Error attempting to send message to " - "userspace daemon; rc = [%d]\n", __func__, rc); -out: - return rc; -} - -/** - * ecryptfs_send_message - * @data: The data to send - * @data_len: The length of data - * @msg_ctx: The message context allocated for the send - * - * Grabs ecryptfs_daemon_hash_mux. - * - * Returns zero on success; non-zero otherwise - */ -int ecryptfs_send_message(char *data, int data_len, - struct ecryptfs_msg_ctx **msg_ctx) -{ - int rc; - - mutex_lock(&ecryptfs_daemon_hash_mux); - rc = ecryptfs_send_message_locked(data, data_len, ECRYPTFS_MSG_REQUEST, - msg_ctx); - mutex_unlock(&ecryptfs_daemon_hash_mux); - return rc; -} - -/** - * ecryptfs_wait_for_response - * @msg_ctx: The context that was assigned when sending a message - * @msg: The incoming message from userspace; not set if rc != 0 - * - * Sleeps until awaken by ecryptfs_receive_message or until the amount - * of time exceeds ecryptfs_message_wait_timeout. If zero is - * returned, msg will point to a valid message from userspace; a - * non-zero value is returned upon failure to receive a message or an - * error occurs. Callee must free @msg on success. - */ -int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx, - struct ecryptfs_message **msg) -{ - signed long timeout = ecryptfs_message_wait_timeout * HZ; - int rc = 0; - -sleep: - timeout = schedule_timeout_interruptible(timeout); - mutex_lock(&ecryptfs_msg_ctx_lists_mux); - mutex_lock(&msg_ctx->mux); - if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_DONE) { - if (timeout) { - mutex_unlock(&msg_ctx->mux); - mutex_unlock(&ecryptfs_msg_ctx_lists_mux); - goto sleep; - } - rc = -ENOMSG; - } else { - *msg = msg_ctx->msg; - msg_ctx->msg = NULL; - } - ecryptfs_msg_ctx_alloc_to_free(msg_ctx); - mutex_unlock(&msg_ctx->mux); - mutex_unlock(&ecryptfs_msg_ctx_lists_mux); - return rc; -} - -int __init ecryptfs_init_messaging(void) -{ - int i; - int rc = 0; - - if (ecryptfs_number_of_users > ECRYPTFS_MAX_NUM_USERS) { - ecryptfs_number_of_users = ECRYPTFS_MAX_NUM_USERS; - printk(KERN_WARNING "%s: Specified number of users is " - "too large, defaulting to [%d] users\n", __func__, - ecryptfs_number_of_users); - } - mutex_init(&ecryptfs_daemon_hash_mux); - mutex_lock(&ecryptfs_daemon_hash_mux); - ecryptfs_hash_bits = 1; - while (ecryptfs_number_of_users >> ecryptfs_hash_bits) - ecryptfs_hash_bits++; - ecryptfs_daemon_hash = kmalloc((sizeof(struct hlist_head) - * (1 << ecryptfs_hash_bits)), - GFP_KERNEL); - if (!ecryptfs_daemon_hash) { - rc = -ENOMEM; - printk(KERN_ERR "%s: Failed to allocate memory\n", __func__); - mutex_unlock(&ecryptfs_daemon_hash_mux); - goto out; - } - for (i = 0; i < (1 << ecryptfs_hash_bits); i++) - INIT_HLIST_HEAD(&ecryptfs_daemon_hash[i]); - mutex_unlock(&ecryptfs_daemon_hash_mux); - ecryptfs_msg_ctx_arr = kmalloc((sizeof(struct ecryptfs_msg_ctx) - * ecryptfs_message_buf_len), - GFP_KERNEL); - if (!ecryptfs_msg_ctx_arr) { - rc = -ENOMEM; - printk(KERN_ERR "%s: Failed to allocate memory\n", __func__); - goto out; - } - mutex_init(&ecryptfs_msg_ctx_lists_mux); - mutex_lock(&ecryptfs_msg_ctx_lists_mux); - ecryptfs_msg_counter = 0; - for (i = 0; i < ecryptfs_message_buf_len; i++) { - INIT_LIST_HEAD(&ecryptfs_msg_ctx_arr[i].node); - INIT_LIST_HEAD(&ecryptfs_msg_ctx_arr[i].daemon_out_list); - mutex_init(&ecryptfs_msg_ctx_arr[i].mux); - mutex_lock(&ecryptfs_msg_ctx_arr[i].mux); - ecryptfs_msg_ctx_arr[i].index = i; - ecryptfs_msg_ctx_arr[i].state = ECRYPTFS_MSG_CTX_STATE_FREE; - ecryptfs_msg_ctx_arr[i].counter = 0; - ecryptfs_msg_ctx_arr[i].task = NULL; - ecryptfs_msg_ctx_arr[i].msg = NULL; - list_add_tail(&ecryptfs_msg_ctx_arr[i].node, - &ecryptfs_msg_ctx_free_list); - mutex_unlock(&ecryptfs_msg_ctx_arr[i].mux); - } - mutex_unlock(&ecryptfs_msg_ctx_lists_mux); - rc = ecryptfs_init_ecryptfs_miscdev(); - if (rc) - ecryptfs_release_messaging(); -out: - return rc; -} - -void ecryptfs_release_messaging(void) -{ - if (ecryptfs_msg_ctx_arr) { - int i; - - mutex_lock(&ecryptfs_msg_ctx_lists_mux); - for (i = 0; i < ecryptfs_message_buf_len; i++) { - mutex_lock(&ecryptfs_msg_ctx_arr[i].mux); - if (ecryptfs_msg_ctx_arr[i].msg) - kfree(ecryptfs_msg_ctx_arr[i].msg); - mutex_unlock(&ecryptfs_msg_ctx_arr[i].mux); - } - kfree(ecryptfs_msg_ctx_arr); - mutex_unlock(&ecryptfs_msg_ctx_lists_mux); - } - if (ecryptfs_daemon_hash) { - struct hlist_node *elem; - struct ecryptfs_daemon *daemon; - int i; - - mutex_lock(&ecryptfs_daemon_hash_mux); - for (i = 0; i < (1 << ecryptfs_hash_bits); i++) { - int rc; - - hlist_for_each_entry(daemon, elem, - &ecryptfs_daemon_hash[i], - euid_chain) { - rc = ecryptfs_exorcise_daemon(daemon); - if (rc) - printk(KERN_ERR "%s: Error whilst " - "attempting to destroy daemon; " - "rc = [%d]. Dazed and confused, " - "but trying to continue.\n", - __func__, rc); - } - } - kfree(ecryptfs_daemon_hash); - mutex_unlock(&ecryptfs_daemon_hash_mux); - } - ecryptfs_destroy_ecryptfs_miscdev(); - return; -} diff --git a/ANDROID_3.4.5/fs/ecryptfs/miscdev.c b/ANDROID_3.4.5/fs/ecryptfs/miscdev.c deleted file mode 100644 index c0038f65..00000000 --- a/ANDROID_3.4.5/fs/ecryptfs/miscdev.c +++ /dev/null @@ -1,567 +0,0 @@ -/** - * eCryptfs: Linux filesystem encryption layer - * - * Copyright (C) 2008 International Business Machines Corp. - * Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <linux/fs.h> -#include <linux/hash.h> -#include <linux/random.h> -#include <linux/miscdevice.h> -#include <linux/poll.h> -#include <linux/slab.h> -#include <linux/wait.h> -#include <linux/module.h> -#include "ecryptfs_kernel.h" - -static atomic_t ecryptfs_num_miscdev_opens; - -/** - * ecryptfs_miscdev_poll - * @file: dev file (ignored) - * @pt: dev poll table (ignored) - * - * Returns the poll mask - */ -static unsigned int -ecryptfs_miscdev_poll(struct file *file, poll_table *pt) -{ - struct ecryptfs_daemon *daemon; - unsigned int mask = 0; - uid_t euid = current_euid(); - int rc; - - mutex_lock(&ecryptfs_daemon_hash_mux); - /* TODO: Just use file->private_data? */ - rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); - if (rc || !daemon) { - mutex_unlock(&ecryptfs_daemon_hash_mux); - return -EINVAL; - } - mutex_lock(&daemon->mux); - mutex_unlock(&ecryptfs_daemon_hash_mux); - if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { - printk(KERN_WARNING "%s: Attempt to poll on zombified " - "daemon\n", __func__); - goto out_unlock_daemon; - } - if (daemon->flags & ECRYPTFS_DAEMON_IN_READ) - goto out_unlock_daemon; - if (daemon->flags & ECRYPTFS_DAEMON_IN_POLL) - goto out_unlock_daemon; - daemon->flags |= ECRYPTFS_DAEMON_IN_POLL; - mutex_unlock(&daemon->mux); - poll_wait(file, &daemon->wait, pt); - mutex_lock(&daemon->mux); - if (!list_empty(&daemon->msg_ctx_out_queue)) - mask |= POLLIN | POLLRDNORM; -out_unlock_daemon: - daemon->flags &= ~ECRYPTFS_DAEMON_IN_POLL; - mutex_unlock(&daemon->mux); - return mask; -} - -/** - * ecryptfs_miscdev_open - * @inode: inode of miscdev handle (ignored) - * @file: file for miscdev handle (ignored) - * - * Returns zero on success; non-zero otherwise - */ -static int -ecryptfs_miscdev_open(struct inode *inode, struct file *file) -{ - struct ecryptfs_daemon *daemon = NULL; - uid_t euid = current_euid(); - int rc; - - mutex_lock(&ecryptfs_daemon_hash_mux); - rc = try_module_get(THIS_MODULE); - if (rc == 0) { - rc = -EIO; - printk(KERN_ERR "%s: Error attempting to increment module use " - "count; rc = [%d]\n", __func__, rc); - goto out_unlock_daemon_list; - } - rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); - if (rc || !daemon) { - rc = ecryptfs_spawn_daemon(&daemon, euid, current_user_ns(), - task_pid(current)); - if (rc) { - printk(KERN_ERR "%s: Error attempting to spawn daemon; " - "rc = [%d]\n", __func__, rc); - goto out_module_put_unlock_daemon_list; - } - } - mutex_lock(&daemon->mux); - if (daemon->pid != task_pid(current)) { - rc = -EINVAL; - printk(KERN_ERR "%s: pid [0x%p] has registered with euid [%d], " - "but pid [0x%p] has attempted to open the handle " - "instead\n", __func__, daemon->pid, daemon->euid, - task_pid(current)); - goto out_unlock_daemon; - } - if (daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN) { - rc = -EBUSY; - printk(KERN_ERR "%s: Miscellaneous device handle may only be " - "opened once per daemon; pid [0x%p] already has this " - "handle open\n", __func__, daemon->pid); - goto out_unlock_daemon; - } - daemon->flags |= ECRYPTFS_DAEMON_MISCDEV_OPEN; - file->private_data = daemon; - atomic_inc(&ecryptfs_num_miscdev_opens); -out_unlock_daemon: - mutex_unlock(&daemon->mux); -out_module_put_unlock_daemon_list: - if (rc) - module_put(THIS_MODULE); -out_unlock_daemon_list: - mutex_unlock(&ecryptfs_daemon_hash_mux); - return rc; -} - -/** - * ecryptfs_miscdev_release - * @inode: inode of fs/ecryptfs/euid handle (ignored) - * @file: file for fs/ecryptfs/euid handle (ignored) - * - * This keeps the daemon registered until the daemon sends another - * ioctl to fs/ecryptfs/ctl or until the kernel module unregisters. - * - * Returns zero on success; non-zero otherwise - */ -static int -ecryptfs_miscdev_release(struct inode *inode, struct file *file) -{ - struct ecryptfs_daemon *daemon = NULL; - uid_t euid = current_euid(); - int rc; - - mutex_lock(&ecryptfs_daemon_hash_mux); - rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); - if (rc || !daemon) - daemon = file->private_data; - mutex_lock(&daemon->mux); - BUG_ON(!(daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN)); - daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN; - atomic_dec(&ecryptfs_num_miscdev_opens); - mutex_unlock(&daemon->mux); - rc = ecryptfs_exorcise_daemon(daemon); - if (rc) { - printk(KERN_CRIT "%s: Fatal error whilst attempting to " - "shut down daemon; rc = [%d]. Please report this " - "bug.\n", __func__, rc); - BUG(); - } - module_put(THIS_MODULE); - mutex_unlock(&ecryptfs_daemon_hash_mux); - return rc; -} - -/** - * ecryptfs_send_miscdev - * @data: Data to send to daemon; may be NULL - * @data_size: Amount of data to send to daemon - * @msg_ctx: Message context, which is used to handle the reply. If - * this is NULL, then we do not expect a reply. - * @msg_type: Type of message - * @msg_flags: Flags for message - * @daemon: eCryptfs daemon object - * - * Add msg_ctx to queue and then, if it exists, notify the blocked - * miscdevess about the data being available. Must be called with - * ecryptfs_daemon_hash_mux held. - * - * Returns zero on success; non-zero otherwise - */ -int ecryptfs_send_miscdev(char *data, size_t data_size, - struct ecryptfs_msg_ctx *msg_ctx, u8 msg_type, - u16 msg_flags, struct ecryptfs_daemon *daemon) -{ - struct ecryptfs_message *msg; - - msg = kmalloc((sizeof(*msg) + data_size), GFP_KERNEL); - if (!msg) { - printk(KERN_ERR "%s: Out of memory whilst attempting " - "to kmalloc(%zd, GFP_KERNEL)\n", __func__, - (sizeof(*msg) + data_size)); - return -ENOMEM; - } - - mutex_lock(&msg_ctx->mux); - msg_ctx->msg = msg; - msg_ctx->msg->index = msg_ctx->index; - msg_ctx->msg->data_len = data_size; - msg_ctx->type = msg_type; - memcpy(msg_ctx->msg->data, data, data_size); - msg_ctx->msg_size = (sizeof(*msg_ctx->msg) + data_size); - list_add_tail(&msg_ctx->daemon_out_list, &daemon->msg_ctx_out_queue); - mutex_unlock(&msg_ctx->mux); - - mutex_lock(&daemon->mux); - daemon->num_queued_msg_ctx++; - wake_up_interruptible(&daemon->wait); - mutex_unlock(&daemon->mux); - - return 0; -} - -/* - * miscdevfs packet format: - * Octet 0: Type - * Octets 1-4: network byte order msg_ctx->counter - * Octets 5-N0: Size of struct ecryptfs_message to follow - * Octets N0-N1: struct ecryptfs_message (including data) - * - * Octets 5-N1 not written if the packet type does not include a message - */ -#define PKT_TYPE_SIZE 1 -#define PKT_CTR_SIZE 4 -#define MIN_NON_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE) -#define MIN_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE \ - + ECRYPTFS_MIN_PKT_LEN_SIZE) -/* 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES comes from tag 65 packet format */ -#define MAX_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE \ - + ECRYPTFS_MAX_PKT_LEN_SIZE \ - + sizeof(struct ecryptfs_message) \ - + 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) -#define PKT_TYPE_OFFSET 0 -#define PKT_CTR_OFFSET PKT_TYPE_SIZE -#define PKT_LEN_OFFSET (PKT_TYPE_SIZE + PKT_CTR_SIZE) - -/** - * ecryptfs_miscdev_read - format and send message from queue - * @file: fs/ecryptfs/euid miscdevfs handle (ignored) - * @buf: User buffer into which to copy the next message on the daemon queue - * @count: Amount of space available in @buf - * @ppos: Offset in file (ignored) - * - * Pulls the most recent message from the daemon queue, formats it for - * being sent via a miscdevfs handle, and copies it into @buf - * - * Returns the number of bytes copied into the user buffer - */ -static ssize_t -ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) -{ - struct ecryptfs_daemon *daemon; - struct ecryptfs_msg_ctx *msg_ctx; - size_t packet_length_size; - char packet_length[ECRYPTFS_MAX_PKT_LEN_SIZE]; - size_t i; - size_t total_length; - uid_t euid = current_euid(); - int rc; - - mutex_lock(&ecryptfs_daemon_hash_mux); - /* TODO: Just use file->private_data? */ - rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); - if (rc || !daemon) { - mutex_unlock(&ecryptfs_daemon_hash_mux); - return -EINVAL; - } - mutex_lock(&daemon->mux); - if (task_pid(current) != daemon->pid) { - mutex_unlock(&daemon->mux); - mutex_unlock(&ecryptfs_daemon_hash_mux); - return -EPERM; - } - if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { - rc = 0; - mutex_unlock(&ecryptfs_daemon_hash_mux); - printk(KERN_WARNING "%s: Attempt to read from zombified " - "daemon\n", __func__); - goto out_unlock_daemon; - } - if (daemon->flags & ECRYPTFS_DAEMON_IN_READ) { - rc = 0; - mutex_unlock(&ecryptfs_daemon_hash_mux); - goto out_unlock_daemon; - } - /* This daemon will not go away so long as this flag is set */ - daemon->flags |= ECRYPTFS_DAEMON_IN_READ; - mutex_unlock(&ecryptfs_daemon_hash_mux); -check_list: - if (list_empty(&daemon->msg_ctx_out_queue)) { - mutex_unlock(&daemon->mux); - rc = wait_event_interruptible( - daemon->wait, !list_empty(&daemon->msg_ctx_out_queue)); - mutex_lock(&daemon->mux); - if (rc < 0) { - rc = 0; - goto out_unlock_daemon; - } - } - if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { - rc = 0; - goto out_unlock_daemon; - } - if (list_empty(&daemon->msg_ctx_out_queue)) { - /* Something else jumped in since the - * wait_event_interruptable() and removed the - * message from the queue; try again */ - goto check_list; - } - msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue, - struct ecryptfs_msg_ctx, daemon_out_list); - BUG_ON(!msg_ctx); - mutex_lock(&msg_ctx->mux); - if (msg_ctx->msg) { - rc = ecryptfs_write_packet_length(packet_length, - msg_ctx->msg_size, - &packet_length_size); - if (rc) { - rc = 0; - printk(KERN_WARNING "%s: Error writing packet length; " - "rc = [%d]\n", __func__, rc); - goto out_unlock_msg_ctx; - } - } else { - packet_length_size = 0; - msg_ctx->msg_size = 0; - } - total_length = (PKT_TYPE_SIZE + PKT_CTR_SIZE + packet_length_size - + msg_ctx->msg_size); - if (count < total_length) { - rc = 0; - printk(KERN_WARNING "%s: Only given user buffer of " - "size [%zd], but we need [%zd] to read the " - "pending message\n", __func__, count, total_length); - goto out_unlock_msg_ctx; - } - rc = -EFAULT; - if (put_user(msg_ctx->type, buf)) - goto out_unlock_msg_ctx; - if (put_user(cpu_to_be32(msg_ctx->counter), - (__be32 __user *)(&buf[PKT_CTR_OFFSET]))) - goto out_unlock_msg_ctx; - i = PKT_TYPE_SIZE + PKT_CTR_SIZE; - if (msg_ctx->msg) { - if (copy_to_user(&buf[i], packet_length, packet_length_size)) - goto out_unlock_msg_ctx; - i += packet_length_size; - if (copy_to_user(&buf[i], msg_ctx->msg, msg_ctx->msg_size)) - goto out_unlock_msg_ctx; - i += msg_ctx->msg_size; - } - rc = i; - list_del(&msg_ctx->daemon_out_list); - kfree(msg_ctx->msg); - msg_ctx->msg = NULL; - /* We do not expect a reply from the userspace daemon for any - * message type other than ECRYPTFS_MSG_REQUEST */ - if (msg_ctx->type != ECRYPTFS_MSG_REQUEST) - ecryptfs_msg_ctx_alloc_to_free(msg_ctx); -out_unlock_msg_ctx: - mutex_unlock(&msg_ctx->mux); -out_unlock_daemon: - daemon->flags &= ~ECRYPTFS_DAEMON_IN_READ; - mutex_unlock(&daemon->mux); - return rc; -} - -/** - * ecryptfs_miscdev_response - miscdevess response to message previously sent to daemon - * @data: Bytes comprising struct ecryptfs_message - * @data_size: sizeof(struct ecryptfs_message) + data len - * @euid: Effective user id of miscdevess sending the miscdev response - * @user_ns: The namespace in which @euid applies - * @pid: Miscdevess id of miscdevess sending the miscdev response - * @seq: Sequence number for miscdev response packet - * - * Returns zero on success; non-zero otherwise - */ -static int ecryptfs_miscdev_response(char *data, size_t data_size, - uid_t euid, struct user_namespace *user_ns, - struct pid *pid, u32 seq) -{ - struct ecryptfs_message *msg = (struct ecryptfs_message *)data; - int rc; - - if ((sizeof(*msg) + msg->data_len) != data_size) { - printk(KERN_WARNING "%s: (sizeof(*msg) + msg->data_len) = " - "[%zd]; data_size = [%zd]. Invalid packet.\n", __func__, - (sizeof(*msg) + msg->data_len), data_size); - rc = -EINVAL; - goto out; - } - rc = ecryptfs_process_response(msg, euid, user_ns, pid, seq); - if (rc) - printk(KERN_ERR - "Error processing response message; rc = [%d]\n", rc); -out: - return rc; -} - -/** - * ecryptfs_miscdev_write - handle write to daemon miscdev handle - * @file: File for misc dev handle (ignored) - * @buf: Buffer containing user data - * @count: Amount of data in @buf - * @ppos: Pointer to offset in file (ignored) - * - * Returns the number of bytes read from @buf - */ -static ssize_t -ecryptfs_miscdev_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - __be32 counter_nbo; - u32 seq; - size_t packet_size, packet_size_length; - char *data; - uid_t euid = current_euid(); - unsigned char packet_size_peek[ECRYPTFS_MAX_PKT_LEN_SIZE]; - ssize_t rc; - - if (count == 0) { - return 0; - } else if (count == MIN_NON_MSG_PKT_SIZE) { - /* Likely a harmless MSG_HELO or MSG_QUIT - no packet length */ - goto memdup; - } else if (count < MIN_MSG_PKT_SIZE || count > MAX_MSG_PKT_SIZE) { - printk(KERN_WARNING "%s: Acceptable packet size range is " - "[%d-%zu], but amount of data written is [%zu].", - __func__, MIN_MSG_PKT_SIZE, MAX_MSG_PKT_SIZE, count); - return -EINVAL; - } - - if (copy_from_user(packet_size_peek, &buf[PKT_LEN_OFFSET], - sizeof(packet_size_peek))) { - printk(KERN_WARNING "%s: Error while inspecting packet size\n", - __func__); - return -EFAULT; - } - - rc = ecryptfs_parse_packet_length(packet_size_peek, &packet_size, - &packet_size_length); - if (rc) { - printk(KERN_WARNING "%s: Error parsing packet length; " - "rc = [%zd]\n", __func__, rc); - return rc; - } - - if ((PKT_TYPE_SIZE + PKT_CTR_SIZE + packet_size_length + packet_size) - != count) { - printk(KERN_WARNING "%s: Invalid packet size [%zu]\n", __func__, - packet_size); - return -EINVAL; - } - -memdup: - data = memdup_user(buf, count); - if (IS_ERR(data)) { - printk(KERN_ERR "%s: memdup_user returned error [%ld]\n", - __func__, PTR_ERR(data)); - return PTR_ERR(data); - } - switch (data[PKT_TYPE_OFFSET]) { - case ECRYPTFS_MSG_RESPONSE: - if (count < (MIN_MSG_PKT_SIZE - + sizeof(struct ecryptfs_message))) { - printk(KERN_WARNING "%s: Minimum acceptable packet " - "size is [%zd], but amount of data written is " - "only [%zd]. Discarding response packet.\n", - __func__, - (MIN_MSG_PKT_SIZE - + sizeof(struct ecryptfs_message)), count); - rc = -EINVAL; - goto out_free; - } - memcpy(&counter_nbo, &data[PKT_CTR_OFFSET], PKT_CTR_SIZE); - seq = be32_to_cpu(counter_nbo); - rc = ecryptfs_miscdev_response( - &data[PKT_LEN_OFFSET + packet_size_length], - packet_size, euid, current_user_ns(), - task_pid(current), seq); - if (rc) { - printk(KERN_WARNING "%s: Failed to deliver miscdev " - "response to requesting operation; rc = [%zd]\n", - __func__, rc); - goto out_free; - } - break; - case ECRYPTFS_MSG_HELO: - case ECRYPTFS_MSG_QUIT: - break; - default: - ecryptfs_printk(KERN_WARNING, "Dropping miscdev " - "message of unrecognized type [%d]\n", - data[0]); - rc = -EINVAL; - goto out_free; - } - rc = count; -out_free: - kfree(data); - return rc; -} - - -static const struct file_operations ecryptfs_miscdev_fops = { - .open = ecryptfs_miscdev_open, - .poll = ecryptfs_miscdev_poll, - .read = ecryptfs_miscdev_read, - .write = ecryptfs_miscdev_write, - .release = ecryptfs_miscdev_release, - .llseek = noop_llseek, -}; - -static struct miscdevice ecryptfs_miscdev = { - .minor = MISC_DYNAMIC_MINOR, - .name = "ecryptfs", - .fops = &ecryptfs_miscdev_fops -}; - -/** - * ecryptfs_init_ecryptfs_miscdev - * - * Messages sent to the userspace daemon from the kernel are placed on - * a queue associated with the daemon. The next read against the - * miscdev handle by that daemon will return the oldest message placed - * on the message queue for the daemon. - * - * Returns zero on success; non-zero otherwise - */ -int __init ecryptfs_init_ecryptfs_miscdev(void) -{ - int rc; - - atomic_set(&ecryptfs_num_miscdev_opens, 0); - rc = misc_register(&ecryptfs_miscdev); - if (rc) - printk(KERN_ERR "%s: Failed to register miscellaneous device " - "for communications with userspace daemons; rc = [%d]\n", - __func__, rc); - return rc; -} - -/** - * ecryptfs_destroy_ecryptfs_miscdev - * - * All of the daemons must be exorcised prior to calling this - * function. - */ -void ecryptfs_destroy_ecryptfs_miscdev(void) -{ - BUG_ON(atomic_read(&ecryptfs_num_miscdev_opens) != 0); - misc_deregister(&ecryptfs_miscdev); -} diff --git a/ANDROID_3.4.5/fs/ecryptfs/mmap.c b/ANDROID_3.4.5/fs/ecryptfs/mmap.c deleted file mode 100644 index a46b3a8f..00000000 --- a/ANDROID_3.4.5/fs/ecryptfs/mmap.c +++ /dev/null @@ -1,566 +0,0 @@ -/** - * eCryptfs: Linux filesystem encryption layer - * This is where eCryptfs coordinates the symmetric encryption and - * decryption of the file data as it passes between the lower - * encrypted file and the upper decrypted file. - * - * Copyright (C) 1997-2003 Erez Zadok - * Copyright (C) 2001-2003 Stony Brook University - * Copyright (C) 2004-2007 International Business Machines Corp. - * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <linux/pagemap.h> -#include <linux/writeback.h> -#include <linux/page-flags.h> -#include <linux/mount.h> -#include <linux/file.h> -#include <linux/crypto.h> -#include <linux/scatterlist.h> -#include <linux/slab.h> -#include <asm/unaligned.h> -#include "ecryptfs_kernel.h" - -/** - * ecryptfs_get_locked_page - * - * Get one page from cache or lower f/s, return error otherwise. - * - * Returns locked and up-to-date page (if ok), with increased - * refcnt. - */ -struct page *ecryptfs_get_locked_page(struct inode *inode, loff_t index) -{ - struct page *page = read_mapping_page(inode->i_mapping, index, NULL); - if (!IS_ERR(page)) - lock_page(page); - return page; -} - -/** - * ecryptfs_writepage - * @page: Page that is locked before this call is made - * - * Returns zero on success; non-zero otherwise - * - * This is where we encrypt the data and pass the encrypted data to - * the lower filesystem. In OpenPGP-compatible mode, we operate on - * entire underlying packets. - */ -static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc) -{ - int rc; - - /* - * Refuse to write the page out if we are called from reclaim context - * since our writepage() path may potentially allocate memory when - * calling into the lower fs vfs_write() which may in turn invoke - * us again. - */ - if (current->flags & PF_MEMALLOC) { - redirty_page_for_writepage(wbc, page); - rc = 0; - goto out; - } - - rc = ecryptfs_encrypt_page(page); - if (rc) { - ecryptfs_printk(KERN_WARNING, "Error encrypting " - "page (upper index [0x%.16lx])\n", page->index); - ClearPageUptodate(page); - goto out; - } - SetPageUptodate(page); -out: - unlock_page(page); - return rc; -} - -static void strip_xattr_flag(char *page_virt, - struct ecryptfs_crypt_stat *crypt_stat) -{ - if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) { - size_t written; - - crypt_stat->flags &= ~ECRYPTFS_METADATA_IN_XATTR; - ecryptfs_write_crypt_stat_flags(page_virt, crypt_stat, - &written); - crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; - } -} - -/** - * Header Extent: - * Octets 0-7: Unencrypted file size (big-endian) - * Octets 8-15: eCryptfs special marker - * Octets 16-19: Flags - * Octet 16: File format version number (between 0 and 255) - * Octets 17-18: Reserved - * Octet 19: Bit 1 (lsb): Reserved - * Bit 2: Encrypted? - * Bits 3-8: Reserved - * Octets 20-23: Header extent size (big-endian) - * Octets 24-25: Number of header extents at front of file - * (big-endian) - * Octet 26: Begin RFC 2440 authentication token packet set - */ - -/** - * ecryptfs_copy_up_encrypted_with_header - * @page: Sort of a ``virtual'' representation of the encrypted lower - * file. The actual lower file does not have the metadata in - * the header. This is locked. - * @crypt_stat: The eCryptfs inode's cryptographic context - * - * The ``view'' is the version of the file that userspace winds up - * seeing, with the header information inserted. - */ -static int -ecryptfs_copy_up_encrypted_with_header(struct page *page, - struct ecryptfs_crypt_stat *crypt_stat) -{ - loff_t extent_num_in_page = 0; - loff_t num_extents_per_page = (PAGE_CACHE_SIZE - / crypt_stat->extent_size); - int rc = 0; - - while (extent_num_in_page < num_extents_per_page) { - loff_t view_extent_num = ((((loff_t)page->index) - * num_extents_per_page) - + extent_num_in_page); - size_t num_header_extents_at_front = - (crypt_stat->metadata_size / crypt_stat->extent_size); - - if (view_extent_num < num_header_extents_at_front) { - /* This is a header extent */ - char *page_virt; - - page_virt = kmap_atomic(page); - memset(page_virt, 0, PAGE_CACHE_SIZE); - /* TODO: Support more than one header extent */ - if (view_extent_num == 0) { - size_t written; - - rc = ecryptfs_read_xattr_region( - page_virt, page->mapping->host); - strip_xattr_flag(page_virt + 16, crypt_stat); - ecryptfs_write_header_metadata(page_virt + 20, - crypt_stat, - &written); - } - kunmap_atomic(page_virt); - flush_dcache_page(page); - if (rc) { - printk(KERN_ERR "%s: Error reading xattr " - "region; rc = [%d]\n", __func__, rc); - goto out; - } - } else { - /* This is an encrypted data extent */ - loff_t lower_offset = - ((view_extent_num * crypt_stat->extent_size) - - crypt_stat->metadata_size); - - rc = ecryptfs_read_lower_page_segment( - page, (lower_offset >> PAGE_CACHE_SHIFT), - (lower_offset & ~PAGE_CACHE_MASK), - crypt_stat->extent_size, page->mapping->host); - if (rc) { - printk(KERN_ERR "%s: Error attempting to read " - "extent at offset [%lld] in the lower " - "file; rc = [%d]\n", __func__, - lower_offset, rc); - goto out; - } - } - extent_num_in_page++; - } -out: - return rc; -} - -/** - * ecryptfs_readpage - * @file: An eCryptfs file - * @page: Page from eCryptfs inode mapping into which to stick the read data - * - * Read in a page, decrypting if necessary. - * - * Returns zero on success; non-zero on error. - */ -static int ecryptfs_readpage(struct file *file, struct page *page) -{ - struct ecryptfs_crypt_stat *crypt_stat = - &ecryptfs_inode_to_private(page->mapping->host)->crypt_stat; - int rc = 0; - - if (!crypt_stat || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { - rc = ecryptfs_read_lower_page_segment(page, page->index, 0, - PAGE_CACHE_SIZE, - page->mapping->host); - } else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) { - if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) { - rc = ecryptfs_copy_up_encrypted_with_header(page, - crypt_stat); - if (rc) { - printk(KERN_ERR "%s: Error attempting to copy " - "the encrypted content from the lower " - "file whilst inserting the metadata " - "from the xattr into the header; rc = " - "[%d]\n", __func__, rc); - goto out; - } - - } else { - rc = ecryptfs_read_lower_page_segment( - page, page->index, 0, PAGE_CACHE_SIZE, - page->mapping->host); - if (rc) { - printk(KERN_ERR "Error reading page; rc = " - "[%d]\n", rc); - goto out; - } - } - } else { - rc = ecryptfs_decrypt_page(page); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error decrypting page; " - "rc = [%d]\n", rc); - goto out; - } - } -out: - if (rc) - ClearPageUptodate(page); - else - SetPageUptodate(page); - ecryptfs_printk(KERN_DEBUG, "Unlocking page with index = [0x%.16lx]\n", - page->index); - unlock_page(page); - return rc; -} - -/** - * Called with lower inode mutex held. - */ -static int fill_zeros_to_end_of_page(struct page *page, unsigned int to) -{ - struct inode *inode = page->mapping->host; - int end_byte_in_page; - - if ((i_size_read(inode) / PAGE_CACHE_SIZE) != page->index) - goto out; - end_byte_in_page = i_size_read(inode) % PAGE_CACHE_SIZE; - if (to > end_byte_in_page) - end_byte_in_page = to; - zero_user_segment(page, end_byte_in_page, PAGE_CACHE_SIZE); -out: - return 0; -} - -/** - * ecryptfs_write_begin - * @file: The eCryptfs file - * @mapping: The eCryptfs object - * @pos: The file offset at which to start writing - * @len: Length of the write - * @flags: Various flags - * @pagep: Pointer to return the page - * @fsdata: Pointer to return fs data (unused) - * - * This function must zero any hole we create - * - * Returns zero on success; non-zero otherwise - */ -static int ecryptfs_write_begin(struct file *file, - struct address_space *mapping, - loff_t pos, unsigned len, unsigned flags, - struct page **pagep, void **fsdata) -{ - pgoff_t index = pos >> PAGE_CACHE_SHIFT; - struct page *page; - loff_t prev_page_end_size; - int rc = 0; - - page = grab_cache_page_write_begin(mapping, index, flags); - if (!page) - return -ENOMEM; - *pagep = page; - - prev_page_end_size = ((loff_t)index << PAGE_CACHE_SHIFT); - if (!PageUptodate(page)) { - struct ecryptfs_crypt_stat *crypt_stat = - &ecryptfs_inode_to_private(mapping->host)->crypt_stat; - - if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { - rc = ecryptfs_read_lower_page_segment( - page, index, 0, PAGE_CACHE_SIZE, mapping->host); - if (rc) { - printk(KERN_ERR "%s: Error attemping to read " - "lower page segment; rc = [%d]\n", - __func__, rc); - ClearPageUptodate(page); - goto out; - } else - SetPageUptodate(page); - } else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) { - if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) { - rc = ecryptfs_copy_up_encrypted_with_header( - page, crypt_stat); - if (rc) { - printk(KERN_ERR "%s: Error attempting " - "to copy the encrypted content " - "from the lower file whilst " - "inserting the metadata from " - "the xattr into the header; rc " - "= [%d]\n", __func__, rc); - ClearPageUptodate(page); - goto out; - } - SetPageUptodate(page); - } else { - rc = ecryptfs_read_lower_page_segment( - page, index, 0, PAGE_CACHE_SIZE, - mapping->host); - if (rc) { - printk(KERN_ERR "%s: Error reading " - "page; rc = [%d]\n", - __func__, rc); - ClearPageUptodate(page); - goto out; - } - SetPageUptodate(page); - } - } else { - if (prev_page_end_size - >= i_size_read(page->mapping->host)) { - zero_user(page, 0, PAGE_CACHE_SIZE); - } else { - rc = ecryptfs_decrypt_page(page); - if (rc) { - printk(KERN_ERR "%s: Error decrypting " - "page at index [%ld]; " - "rc = [%d]\n", - __func__, page->index, rc); - ClearPageUptodate(page); - goto out; - } - } - SetPageUptodate(page); - } - } - /* If creating a page or more of holes, zero them out via truncate. - * Note, this will increase i_size. */ - if (index != 0) { - if (prev_page_end_size > i_size_read(page->mapping->host)) { - rc = ecryptfs_truncate(file->f_path.dentry, - prev_page_end_size); - if (rc) { - printk(KERN_ERR "%s: Error on attempt to " - "truncate to (higher) offset [%lld];" - " rc = [%d]\n", __func__, - prev_page_end_size, rc); - goto out; - } - } - } - /* Writing to a new page, and creating a small hole from start - * of page? Zero it out. */ - if ((i_size_read(mapping->host) == prev_page_end_size) - && (pos != 0)) - zero_user(page, 0, PAGE_CACHE_SIZE); -out: - if (unlikely(rc)) { - unlock_page(page); - page_cache_release(page); - *pagep = NULL; - } - return rc; -} - -/** - * ecryptfs_write_inode_size_to_header - * - * Writes the lower file size to the first 8 bytes of the header. - * - * Returns zero on success; non-zero on error. - */ -static int ecryptfs_write_inode_size_to_header(struct inode *ecryptfs_inode) -{ - char *file_size_virt; - int rc; - - file_size_virt = kmalloc(sizeof(u64), GFP_KERNEL); - if (!file_size_virt) { - rc = -ENOMEM; - goto out; - } - put_unaligned_be64(i_size_read(ecryptfs_inode), file_size_virt); - rc = ecryptfs_write_lower(ecryptfs_inode, file_size_virt, 0, - sizeof(u64)); - kfree(file_size_virt); - if (rc < 0) - printk(KERN_ERR "%s: Error writing file size to header; " - "rc = [%d]\n", __func__, rc); - else - rc = 0; -out: - return rc; -} - -struct kmem_cache *ecryptfs_xattr_cache; - -static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode) -{ - ssize_t size; - void *xattr_virt; - struct dentry *lower_dentry = - ecryptfs_inode_to_private(ecryptfs_inode)->lower_file->f_dentry; - struct inode *lower_inode = lower_dentry->d_inode; - int rc; - - if (!lower_inode->i_op->getxattr || !lower_inode->i_op->setxattr) { - printk(KERN_WARNING - "No support for setting xattr in lower filesystem\n"); - rc = -ENOSYS; - goto out; - } - xattr_virt = kmem_cache_alloc(ecryptfs_xattr_cache, GFP_KERNEL); - if (!xattr_virt) { - printk(KERN_ERR "Out of memory whilst attempting to write " - "inode size to xattr\n"); - rc = -ENOMEM; - goto out; - } - mutex_lock(&lower_inode->i_mutex); - size = lower_inode->i_op->getxattr(lower_dentry, ECRYPTFS_XATTR_NAME, - xattr_virt, PAGE_CACHE_SIZE); - if (size < 0) - size = 8; - put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt); - rc = lower_inode->i_op->setxattr(lower_dentry, ECRYPTFS_XATTR_NAME, - xattr_virt, size, 0); - mutex_unlock(&lower_inode->i_mutex); - if (rc) - printk(KERN_ERR "Error whilst attempting to write inode size " - "to lower file xattr; rc = [%d]\n", rc); - kmem_cache_free(ecryptfs_xattr_cache, xattr_virt); -out: - return rc; -} - -int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode) -{ - struct ecryptfs_crypt_stat *crypt_stat; - - crypt_stat = &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; - BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)); - if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) - return ecryptfs_write_inode_size_to_xattr(ecryptfs_inode); - else - return ecryptfs_write_inode_size_to_header(ecryptfs_inode); -} - -/** - * ecryptfs_write_end - * @file: The eCryptfs file object - * @mapping: The eCryptfs object - * @pos: The file position - * @len: The length of the data (unused) - * @copied: The amount of data copied - * @page: The eCryptfs page - * @fsdata: The fsdata (unused) - */ -static int ecryptfs_write_end(struct file *file, - struct address_space *mapping, - loff_t pos, unsigned len, unsigned copied, - struct page *page, void *fsdata) -{ - pgoff_t index = pos >> PAGE_CACHE_SHIFT; - unsigned from = pos & (PAGE_CACHE_SIZE - 1); - unsigned to = from + copied; - struct inode *ecryptfs_inode = mapping->host; - struct ecryptfs_crypt_stat *crypt_stat = - &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; - int rc; - int need_unlock_page = 1; - - ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page" - "(page w/ index = [0x%.16lx], to = [%d])\n", index, to); - if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { - rc = ecryptfs_write_lower_page_segment(ecryptfs_inode, page, 0, - to); - if (!rc) { - rc = copied; - fsstack_copy_inode_size(ecryptfs_inode, - ecryptfs_inode_to_lower(ecryptfs_inode)); - } - goto out; - } - /* Fills in zeros if 'to' goes beyond inode size */ - rc = fill_zeros_to_end_of_page(page, to); - if (rc) { - ecryptfs_printk(KERN_WARNING, "Error attempting to fill " - "zeros in page with index = [0x%.16lx]\n", index); - goto out; - } - set_page_dirty(page); - unlock_page(page); - need_unlock_page = 0; - if (pos + copied > i_size_read(ecryptfs_inode)) { - i_size_write(ecryptfs_inode, pos + copied); - ecryptfs_printk(KERN_DEBUG, "Expanded file size to " - "[0x%.16llx]\n", - (unsigned long long)i_size_read(ecryptfs_inode)); - balance_dirty_pages_ratelimited(mapping); - rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode); - if (rc) { - printk(KERN_ERR "Error writing inode size to metadata; " - "rc = [%d]\n", rc); - goto out; - } - } - rc = copied; -out: - if (need_unlock_page) - unlock_page(page); - page_cache_release(page); - return rc; -} - -static sector_t ecryptfs_bmap(struct address_space *mapping, sector_t block) -{ - int rc = 0; - struct inode *inode; - struct inode *lower_inode; - - inode = (struct inode *)mapping->host; - lower_inode = ecryptfs_inode_to_lower(inode); - if (lower_inode->i_mapping->a_ops->bmap) - rc = lower_inode->i_mapping->a_ops->bmap(lower_inode->i_mapping, - block); - return rc; -} - -const struct address_space_operations ecryptfs_aops = { - .writepage = ecryptfs_writepage, - .readpage = ecryptfs_readpage, - .write_begin = ecryptfs_write_begin, - .write_end = ecryptfs_write_end, - .bmap = ecryptfs_bmap, -}; diff --git a/ANDROID_3.4.5/fs/ecryptfs/read_write.c b/ANDROID_3.4.5/fs/ecryptfs/read_write.c deleted file mode 100644 index b2a34a19..00000000 --- a/ANDROID_3.4.5/fs/ecryptfs/read_write.c +++ /dev/null @@ -1,284 +0,0 @@ -/** - * eCryptfs: Linux filesystem encryption layer - * - * Copyright (C) 2007 International Business Machines Corp. - * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <linux/fs.h> -#include <linux/pagemap.h> -#include "ecryptfs_kernel.h" - -/** - * ecryptfs_write_lower - * @ecryptfs_inode: The eCryptfs inode - * @data: Data to write - * @offset: Byte offset in the lower file to which to write the data - * @size: Number of bytes from @data to write at @offset in the lower - * file - * - * Write data to the lower file. - * - * Returns bytes written on success; less than zero on error - */ -int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data, - loff_t offset, size_t size) -{ - struct file *lower_file; - mm_segment_t fs_save; - ssize_t rc; - - lower_file = ecryptfs_inode_to_private(ecryptfs_inode)->lower_file; - if (!lower_file) - return -EIO; - fs_save = get_fs(); - set_fs(get_ds()); - rc = vfs_write(lower_file, data, size, &offset); - set_fs(fs_save); - mark_inode_dirty_sync(ecryptfs_inode); - return rc; -} - -/** - * ecryptfs_write_lower_page_segment - * @ecryptfs_inode: The eCryptfs inode - * @page_for_lower: The page containing the data to be written to the - * lower file - * @offset_in_page: The offset in the @page_for_lower from which to - * start writing the data - * @size: The amount of data from @page_for_lower to write to the - * lower file - * - * Determines the byte offset in the file for the given page and - * offset within the page, maps the page, and makes the call to write - * the contents of @page_for_lower to the lower inode. - * - * Returns zero on success; non-zero otherwise - */ -int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode, - struct page *page_for_lower, - size_t offset_in_page, size_t size) -{ - char *virt; - loff_t offset; - int rc; - - 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); - if (rc > 0) - rc = 0; - kunmap(page_for_lower); - return rc; -} - -/** - * ecryptfs_write - * @ecryptfs_inode: The eCryptfs file into which to write - * @data: Virtual address where data to write is located - * @offset: Offset in the eCryptfs file at which to begin writing the - * data from @data - * @size: The number of bytes to write from @data - * - * Write an arbitrary amount of data to an arbitrary location in the - * eCryptfs inode page cache. This is done on a page-by-page, and then - * by an extent-by-extent, basis; individual extents are encrypted and - * written to the lower page cache (via VFS writes). This function - * takes care of all the address translation to locations in the lower - * filesystem; it also handles truncate events, writing out zeros - * where necessary. - * - * Returns zero on success; non-zero otherwise - */ -int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset, - size_t size) -{ - struct page *ecryptfs_page; - struct ecryptfs_crypt_stat *crypt_stat; - char *ecryptfs_page_virt; - loff_t ecryptfs_file_size = i_size_read(ecryptfs_inode); - loff_t data_offset = 0; - loff_t pos; - int rc = 0; - - crypt_stat = &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; - /* - * 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 - pos = offset; - while (pos < (offset + size)) { - pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT); - size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK); - size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page); - loff_t total_remaining_bytes = ((offset + size) - pos); - - if (fatal_signal_pending(current)) { - rc = -EINTR; - break; - } - - if (num_bytes > total_remaining_bytes) - num_bytes = total_remaining_bytes; - if (pos < offset) { - /* remaining zeros to write, up to destination offset */ - loff_t total_remaining_zeros = (offset - pos); - - if (num_bytes > total_remaining_zeros) - num_bytes = total_remaining_zeros; - } - ecryptfs_page = ecryptfs_get_locked_page(ecryptfs_inode, - ecryptfs_page_idx); - if (IS_ERR(ecryptfs_page)) { - rc = PTR_ERR(ecryptfs_page); - printk(KERN_ERR "%s: Error getting page at " - "index [%ld] from eCryptfs inode " - "mapping; rc = [%d]\n", __func__, - ecryptfs_page_idx, rc); - goto out; - } - ecryptfs_page_virt = kmap_atomic(ecryptfs_page); - - /* - * 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; - } - kunmap_atomic(ecryptfs_page_virt); - flush_dcache_page(ecryptfs_page); - SetPageUptodate(ecryptfs_page); - unlock_page(ecryptfs_page); - if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) - rc = ecryptfs_encrypt_page(ecryptfs_page); - else - rc = ecryptfs_write_lower_page_segment(ecryptfs_inode, - ecryptfs_page, - start_offset_in_page, - data_offset); - page_cache_release(ecryptfs_page); - if (rc) { - printk(KERN_ERR "%s: Error encrypting " - "page; rc = [%d]\n", __func__, rc); - goto out; - } - pos += num_bytes; - } - if (pos > ecryptfs_file_size) { - i_size_write(ecryptfs_inode, pos); - if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) { - int rc2; - - rc2 = ecryptfs_write_inode_size_to_metadata( - ecryptfs_inode); - if (rc2) { - printk(KERN_ERR "Problem with " - "ecryptfs_write_inode_size_to_metadata; " - "rc = [%d]\n", rc2); - if (!rc) - rc = rc2; - goto out; - } - } - } -out: - return rc; -} - -/** - * ecryptfs_read_lower - * @data: The read data is stored here by this function - * @offset: Byte offset in the lower file from which to read the data - * @size: Number of bytes to read from @offset of the lower file and - * store into @data - * @ecryptfs_inode: The eCryptfs inode - * - * Read @size bytes of data at byte offset @offset from the lower - * inode into memory location @data. - * - * Returns bytes read on success; 0 on EOF; less than zero on error - */ -int ecryptfs_read_lower(char *data, loff_t offset, size_t size, - struct inode *ecryptfs_inode) -{ - struct file *lower_file; - mm_segment_t fs_save; - ssize_t rc; - - lower_file = ecryptfs_inode_to_private(ecryptfs_inode)->lower_file; - if (!lower_file) - return -EIO; - fs_save = get_fs(); - set_fs(get_ds()); - rc = vfs_read(lower_file, data, size, &offset); - set_fs(fs_save); - return rc; -} - -/** - * ecryptfs_read_lower_page_segment - * @page_for_ecryptfs: The page into which data for eCryptfs will be - * written - * @offset_in_page: Offset in @page_for_ecryptfs from which to start - * writing - * @size: The number of bytes to write into @page_for_ecryptfs - * @ecryptfs_inode: The eCryptfs inode - * - * Determines the byte offset in the file for the given page and - * offset within the page, maps the page, and makes the call to read - * the contents of @page_for_ecryptfs from the lower inode. - * - * Returns zero on success; non-zero otherwise - */ -int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs, - pgoff_t page_index, - size_t offset_in_page, size_t size, - struct inode *ecryptfs_inode) -{ - char *virt; - loff_t offset; - int rc; - - offset = ((((loff_t)page_index) << PAGE_CACHE_SHIFT) + offset_in_page); - virt = kmap(page_for_ecryptfs); - rc = ecryptfs_read_lower(virt, offset, size, ecryptfs_inode); - if (rc > 0) - rc = 0; - kunmap(page_for_ecryptfs); - flush_dcache_page(page_for_ecryptfs); - return rc; -} diff --git a/ANDROID_3.4.5/fs/ecryptfs/super.c b/ANDROID_3.4.5/fs/ecryptfs/super.c deleted file mode 100644 index 2dd946b6..00000000 --- a/ANDROID_3.4.5/fs/ecryptfs/super.c +++ /dev/null @@ -1,191 +0,0 @@ -/** - * eCryptfs: Linux filesystem encryption layer - * - * Copyright (C) 1997-2003 Erez Zadok - * Copyright (C) 2001-2003 Stony Brook University - * Copyright (C) 2004-2006 International Business Machines Corp. - * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> - * Michael C. Thompson <mcthomps@us.ibm.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <linux/fs.h> -#include <linux/mount.h> -#include <linux/key.h> -#include <linux/slab.h> -#include <linux/seq_file.h> -#include <linux/file.h> -#include <linux/crypto.h> -#include <linux/statfs.h> -#include <linux/magic.h> -#include "ecryptfs_kernel.h" - -struct kmem_cache *ecryptfs_inode_info_cache; - -/** - * ecryptfs_alloc_inode - allocate an ecryptfs inode - * @sb: Pointer to the ecryptfs super block - * - * Called to bring an inode into existence. - * - * Only handle allocation, setting up structures should be done in - * ecryptfs_read_inode. This is because the kernel, between now and - * then, will 0 out the private data pointer. - * - * Returns a pointer to a newly allocated inode, NULL otherwise - */ -static struct inode *ecryptfs_alloc_inode(struct super_block *sb) -{ - struct ecryptfs_inode_info *inode_info; - struct inode *inode = NULL; - - inode_info = kmem_cache_alloc(ecryptfs_inode_info_cache, GFP_KERNEL); - if (unlikely(!inode_info)) - goto out; - ecryptfs_init_crypt_stat(&inode_info->crypt_stat); - mutex_init(&inode_info->lower_file_mutex); - atomic_set(&inode_info->lower_file_count, 0); - inode_info->lower_file = NULL; - inode = &inode_info->vfs_inode; -out: - return inode; -} - -static void ecryptfs_i_callback(struct rcu_head *head) -{ - struct inode *inode = container_of(head, struct inode, i_rcu); - struct ecryptfs_inode_info *inode_info; - inode_info = ecryptfs_inode_to_private(inode); - - kmem_cache_free(ecryptfs_inode_info_cache, inode_info); -} - -/** - * ecryptfs_destroy_inode - * @inode: The ecryptfs inode - * - * This is used during the final destruction of the inode. All - * allocation of memory related to the inode, including allocated - * memory in the crypt_stat struct, will be released here. - * There should be no chance that this deallocation will be missed. - */ -static void ecryptfs_destroy_inode(struct inode *inode) -{ - struct ecryptfs_inode_info *inode_info; - - inode_info = ecryptfs_inode_to_private(inode); - BUG_ON(inode_info->lower_file); - ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat); - call_rcu(&inode->i_rcu, ecryptfs_i_callback); -} - -/** - * ecryptfs_statfs - * @sb: The ecryptfs super block - * @buf: The struct kstatfs to fill in with stats - * - * Get the filesystem statistics. Currently, we let this pass right through - * to the lower filesystem and take no action ourselves. - */ -static int ecryptfs_statfs(struct dentry *dentry, struct kstatfs *buf) -{ - struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); - int rc; - - if (!lower_dentry->d_sb->s_op->statfs) - return -ENOSYS; - - rc = lower_dentry->d_sb->s_op->statfs(lower_dentry, buf); - if (rc) - return rc; - - buf->f_type = ECRYPTFS_SUPER_MAGIC; - rc = ecryptfs_set_f_namelen(&buf->f_namelen, buf->f_namelen, - &ecryptfs_superblock_to_private(dentry->d_sb)->mount_crypt_stat); - - return rc; -} - -/** - * ecryptfs_evict_inode - * @inode - The ecryptfs inode - * - * Called by iput() when the inode reference count reached zero - * and the inode is not hashed anywhere. Used to clear anything - * that needs to be, before the inode is completely destroyed and put - * on the inode free list. We use this to drop out reference to the - * lower inode. - */ -static void ecryptfs_evict_inode(struct inode *inode) -{ - truncate_inode_pages(&inode->i_data, 0); - end_writeback(inode); - iput(ecryptfs_inode_to_lower(inode)); -} - -/** - * ecryptfs_show_options - * - * Prints the mount options for a given superblock. - * Returns zero; does not fail. - */ -static int ecryptfs_show_options(struct seq_file *m, struct dentry *root) -{ - struct super_block *sb = root->d_sb; - struct ecryptfs_mount_crypt_stat *mount_crypt_stat = - &ecryptfs_superblock_to_private(sb)->mount_crypt_stat; - struct ecryptfs_global_auth_tok *walker; - - mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex); - list_for_each_entry(walker, - &mount_crypt_stat->global_auth_tok_list, - mount_crypt_stat_list) { - if (walker->flags & ECRYPTFS_AUTH_TOK_FNEK) - seq_printf(m, ",ecryptfs_fnek_sig=%s", walker->sig); - else - seq_printf(m, ",ecryptfs_sig=%s", walker->sig); - } - mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex); - - seq_printf(m, ",ecryptfs_cipher=%s", - mount_crypt_stat->global_default_cipher_name); - - if (mount_crypt_stat->global_default_cipher_key_size) - seq_printf(m, ",ecryptfs_key_bytes=%zd", - mount_crypt_stat->global_default_cipher_key_size); - if (mount_crypt_stat->flags & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED) - seq_printf(m, ",ecryptfs_passthrough"); - if (mount_crypt_stat->flags & ECRYPTFS_XATTR_METADATA_ENABLED) - seq_printf(m, ",ecryptfs_xattr_metadata"); - if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) - seq_printf(m, ",ecryptfs_encrypted_view"); - if (mount_crypt_stat->flags & ECRYPTFS_UNLINK_SIGS) - seq_printf(m, ",ecryptfs_unlink_sigs"); - if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_MOUNT_AUTH_TOK_ONLY) - seq_printf(m, ",ecryptfs_mount_auth_tok_only"); - - return 0; -} - -const struct super_operations ecryptfs_sops = { - .alloc_inode = ecryptfs_alloc_inode, - .destroy_inode = ecryptfs_destroy_inode, - .statfs = ecryptfs_statfs, - .remount_fs = NULL, - .evict_inode = ecryptfs_evict_inode, - .show_options = ecryptfs_show_options -}; |