diff options
Diffstat (limited to 'fs/ecryptfs')
| -rw-r--r-- | fs/ecryptfs/Kconfig | 12 | ||||
| -rw-r--r-- | fs/ecryptfs/Makefile | 7 | ||||
| -rw-r--r-- | fs/ecryptfs/crypto.c | 671 | ||||
| -rw-r--r-- | fs/ecryptfs/dentry.c | 44 | ||||
| -rw-r--r-- | fs/ecryptfs/ecryptfs_kernel.h | 330 | ||||
| -rw-r--r-- | fs/ecryptfs/file.c | 211 | ||||
| -rw-r--r-- | fs/ecryptfs/inode.c | 763 | ||||
| -rw-r--r-- | fs/ecryptfs/keystore.c | 408 | ||||
| -rw-r--r-- | fs/ecryptfs/kthread.c | 87 | ||||
| -rw-r--r-- | fs/ecryptfs/main.c | 340 | ||||
| -rw-r--r-- | fs/ecryptfs/messaging.c | 149 | ||||
| -rw-r--r-- | fs/ecryptfs/miscdev.c | 258 | ||||
| -rw-r--r-- | fs/ecryptfs/mmap.c | 79 | ||||
| -rw-r--r-- | fs/ecryptfs/read_write.c | 137 | ||||
| -rw-r--r-- | fs/ecryptfs/super.c | 66 | 
15 files changed, 1580 insertions, 1982 deletions
diff --git a/fs/ecryptfs/Kconfig b/fs/ecryptfs/Kconfig index 1cd6d9d3e29..434aa313f07 100644 --- a/fs/ecryptfs/Kconfig +++ b/fs/ecryptfs/Kconfig @@ -1,6 +1,6 @@  config ECRYPT_FS -	tristate "eCrypt filesystem layer support (EXPERIMENTAL)" -	depends on EXPERIMENTAL && KEYS && CRYPTO +	tristate "eCrypt filesystem layer support" +	depends on KEYS && CRYPTO && (ENCRYPTED_KEYS || ENCRYPTED_KEYS=n)  	select CRYPTO_ECB  	select CRYPTO_CBC  	select CRYPTO_MD5 @@ -12,3 +12,11 @@ config ECRYPT_FS  	  To compile this file system support as a module, choose M here: the  	  module will be called ecryptfs. + +config ECRYPT_FS_MESSAGING +	bool "Enable notifications for userspace key wrap/unwrap" +	depends on ECRYPT_FS +	help +	  Enables the /dev/ecryptfs entry for use by ecryptfsd. This allows +	  for userspace to wrap/unwrap file encryption keys by other +	  backends, like OpenSSL. diff --git a/fs/ecryptfs/Makefile b/fs/ecryptfs/Makefile index 2cc9ee4ad2e..49678a69947 100644 --- a/fs/ecryptfs/Makefile +++ b/fs/ecryptfs/Makefile @@ -1,7 +1,10 @@  # -# Makefile for the Linux 2.6 eCryptfs +# Makefile for the Linux 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 +ecryptfs-y := dentry.o file.o inode.o main.o super.o mmap.o read_write.o \ +	      crypto.o keystore.o kthread.o debug.o + +ecryptfs-$(CONFIG_ECRYPT_FS_MESSAGING) += messaging.o miscdev.o diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index cbadc1bee6e..2f6735dbf1a 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -37,16 +37,8 @@  #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); +#define DECRYPT		0 +#define ENCRYPT		1  /**   * ecryptfs_to_hex @@ -243,7 +235,7 @@ 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); +		crypto_free_ablkcipher(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, @@ -266,7 +258,6 @@ void ecryptfs_destroy_mount_crypt_stat(  				 &mount_crypt_stat->global_auth_tok_list,  				 mount_crypt_stat_list) {  		list_del(&auth_tok->mount_crypt_stat_list); -		mount_crypt_stat->num_global_auth_toks--;  		if (auth_tok->global_auth_tok_key  		    && !(auth_tok->flags & ECRYPTFS_AUTH_TOK_INVALID))  			key_put(auth_tok->global_auth_tok_key); @@ -302,17 +293,14 @@ int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg,  	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); +		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; +			sg[i].length = remainder_of_page;  			addr += remainder_of_page;  			size -= remainder_of_page;  		} else { -			if (sg) -				sg[i].length = size; +			sg[i].length = size;  			addr += size;  			size = 0;  		} @@ -323,133 +311,158 @@ int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg,  	return i;  } +struct extent_crypt_result { +	struct completion completion; +	int rc; +}; + +static void extent_crypt_complete(struct crypto_async_request *req, int rc) +{ +	struct extent_crypt_result *ecr = req->data; + +	if (rc == -EINPROGRESS) +		return; + +	ecr->rc = rc; +	complete(&ecr->completion); +} +  /** - * encrypt_scatterlist + * crypt_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 + * @dst_sg: Destination of the data after performing the crypto operation + * @src_sg: Data to be encrypted or decrypted + * @size: Length of data + * @iv: IV to use + * @op: ENCRYPT or DECRYPT to indicate the desired operation   * - * Returns the number of bytes encrypted; negative value on error + * Returns the number of bytes encrypted or decrypted; 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) +static int crypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, +			     struct scatterlist *dst_sg, +			     struct scatterlist *src_sg, int size, +			     unsigned char *iv, int op)  { -	struct blkcipher_desc desc = { -		.tfm = crypt_stat->tfm, -		.info = iv, -		.flags = CRYPTO_TFM_REQ_MAY_SLEEP -	}; +	struct ablkcipher_request *req = NULL; +	struct extent_crypt_result ecr;  	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 [%d]; key:\n", +		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 */ + +	init_completion(&ecr.completion); +  	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); +	req = ablkcipher_request_alloc(crypt_stat->tfm, GFP_NOFS); +	if (!req) {  		mutex_unlock(&crypt_stat->cs_tfm_mutex); -		rc = -EINVAL; +		rc = -ENOMEM;  		goto out;  	} -	ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes.\n", size); -	crypto_blkcipher_encrypt_iv(&desc, dest_sg, src_sg, size); + +	ablkcipher_request_set_callback(req, +			CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, +			extent_crypt_complete, &ecr); +	/* Consider doing this once, when the file is opened */ +	if (!(crypt_stat->flags & ECRYPTFS_KEY_SET)) { +		rc = crypto_ablkcipher_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; +		} +		crypt_stat->flags |= ECRYPTFS_KEY_SET; +	}  	mutex_unlock(&crypt_stat->cs_tfm_mutex); +	ablkcipher_request_set_crypt(req, src_sg, dst_sg, size, iv); +	rc = op == ENCRYPT ? crypto_ablkcipher_encrypt(req) : +			     crypto_ablkcipher_decrypt(req); +	if (rc == -EINPROGRESS || rc == -EBUSY) { +		struct extent_crypt_result *ecr = req->base.data; + +		wait_for_completion(&ecr->completion); +		rc = ecr->rc; +		reinit_completion(&ecr->completion); +	}  out: +	ablkcipher_request_free(req);  	return rc;  }  /** - * ecryptfs_lower_offset_for_extent + * lower_offset_for_page   *   * 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) +static loff_t lower_offset_for_page(struct ecryptfs_crypt_stat *crypt_stat, +				    struct page *page)  { -	(*offset) = ecryptfs_lower_header_size(crypt_stat) -		    + (crypt_stat->extent_size * extent_num); +	return ecryptfs_lower_header_size(crypt_stat) + +	       ((loff_t)page->index << PAGE_CACHE_SHIFT);  }  /** - * ecryptfs_encrypt_extent - * @enc_extent_page: Allocated page into which to encrypt the data in - *                   @page + * crypt_extent   * @crypt_stat: crypt_stat containing cryptographic context for the   *              encryption operation - * @page: Page containing plaintext data extent to encrypt + * @dst_page: The page to write the result into + * @src_page: The page to read from   * @extent_offset: Page extent offset for use in generating IV + * @op: ENCRYPT or DECRYPT to indicate the desired operation   * - * Encrypts one extent of data. + * Encrypts or decrypts 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) +static int crypt_extent(struct ecryptfs_crypt_stat *crypt_stat, +			struct page *dst_page, +			struct page *src_page, +			unsigned long extent_offset, int op)  { +	pgoff_t page_index = op == ENCRYPT ? src_page->index : dst_page->index;  	loff_t extent_base;  	char extent_iv[ECRYPTFS_MAX_IV_BYTES]; +	struct scatterlist src_sg, dst_sg; +	size_t extent_size = crypt_stat->extent_size;  	int rc; -	extent_base = (((loff_t)page->index) -		       * (PAGE_CACHE_SIZE / crypt_stat->extent_size)); +	extent_base = (((loff_t)page_index) * (PAGE_CACHE_SIZE / 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%.16x]; " -				"rc = [%d]\n", (extent_base + extent_offset), -				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;  	} -	if (unlikely(ecryptfs_verbosity > 0)) { -		ecryptfs_printk(KERN_DEBUG, "Encrypting extent " -				"with iv:\n"); -		ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes); -		ecryptfs_printk(KERN_DEBUG, "First 8 bytes before " -				"encryption:\n"); -		ecryptfs_dump_hex((char *) -				  (page_address(page) -				   + (extent_offset * crypt_stat->extent_size)), -				  8); -	} -	rc = ecryptfs_encrypt_page_offset(crypt_stat, enc_extent_page, 0, -					  page, (extent_offset -						 * crypt_stat->extent_size), -					  crypt_stat->extent_size, extent_iv); + +	sg_init_table(&src_sg, 1); +	sg_init_table(&dst_sg, 1); + +	sg_set_page(&src_sg, src_page, extent_size, +		    extent_offset * extent_size); +	sg_set_page(&dst_sg, dst_page, extent_size, +		    extent_offset * extent_size); + +	rc = crypt_scatterlist(crypt_stat, &dst_sg, &src_sg, extent_size, +			       extent_iv, op);  	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); +		printk(KERN_ERR "%s: Error attempting to crypt page with " +		       "page_index = [%ld], extent_offset = [%ld]; " +		       "rc = [%d]\n", __func__, page_index, extent_offset, rc);  		goto out;  	}  	rc = 0; -	if (unlikely(ecryptfs_verbosity > 0)) { -		ecryptfs_printk(KERN_DEBUG, "Encrypt extent [0x%.16x]; " -				"rc = [%d]\n", (extent_base + extent_offset), -				rc); -		ecryptfs_printk(KERN_DEBUG, "First 8 bytes after " -				"encryption:\n"); -		ecryptfs_dump_hex((char *)(page_address(enc_extent_page)), 8); -	}  out:  	return rc;  } @@ -477,6 +490,7 @@ int ecryptfs_encrypt_page(struct page *page)  	char *enc_extent_virt;  	struct page *enc_extent_page = NULL;  	loff_t extent_offset; +	loff_t lower_offset;  	int rc = 0;  	ecryptfs_inode = page->mapping->host; @@ -490,97 +504,35 @@ int ecryptfs_encrypt_page(struct page *page)  				"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); +		rc = crypt_extent(crypt_stat, enc_extent_page, page, +				  extent_offset, ENCRYPT);  		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%.16x]; " -				"rc = [%d]\n", (extent_base + extent_offset), -				rc); -		goto out; -	} -	if (unlikely(ecryptfs_verbosity > 0)) { -		ecryptfs_printk(KERN_DEBUG, "Decrypting extent " -				"with iv:\n"); -		ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes); -		ecryptfs_printk(KERN_DEBUG, "First 8 bytes before " -				"decryption:\n"); -		ecryptfs_dump_hex((char *) -				  (page_address(enc_extent_page) -				   + (extent_offset * crypt_stat->extent_size)), -				  8); -	} -	rc = ecryptfs_decrypt_page_offset(crypt_stat, page, -					  (extent_offset -					   * crypt_stat->extent_size), -					  enc_extent_page, 0, -					  crypt_stat->extent_size, extent_iv); +	lower_offset = lower_offset_for_page(crypt_stat, page); +	enc_extent_virt = kmap(enc_extent_page); +	rc = ecryptfs_write_lower(ecryptfs_inode, enc_extent_virt, lower_offset, +				  PAGE_CACHE_SIZE); +	kunmap(enc_extent_page);  	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); +		ecryptfs_printk(KERN_ERR, +			"Error attempting to write lower page; rc = [%d]\n", +			rc);  		goto out;  	}  	rc = 0; -	if (unlikely(ecryptfs_verbosity > 0)) { -		ecryptfs_printk(KERN_DEBUG, "Decrypt extent [0x%.16x]; " -				"rc = [%d]\n", (extent_base + extent_offset), -				rc); -		ecryptfs_printk(KERN_DEBUG, "First 8 bytes after " -				"decryption:\n"); -		ecryptfs_dump_hex((char *)(page_address(page) -					   + (extent_offset -					      * crypt_stat->extent_size)), 8); -	}  out: +	if (enc_extent_page) { +		__free_page(enc_extent_page); +	}  	return rc;  } @@ -604,43 +556,33 @@ 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; +	char *page_virt;  	unsigned long extent_offset; +	loff_t lower_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"); + +	lower_offset = lower_offset_for_page(crypt_stat, page); +	page_virt = kmap(page); +	rc = ecryptfs_read_lower(page_virt, lower_offset, PAGE_CACHE_SIZE, +				 ecryptfs_inode); +	kunmap(page); +	if (rc < 0) { +		ecryptfs_printk(KERN_ERR, +			"Error attempting to read lower page; rc = [%d]\n", +			rc);  		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); +		rc = crypt_extent(crypt_stat, page, page, +				  extent_offset, DECRYPT);  		if (rc) {  			printk(KERN_ERR "%s: Error encrypting extent; "  			       "rc = [%d]\n", __func__, rc); @@ -648,116 +590,9 @@ int ecryptfs_decrypt_page(struct page *page)  		}  	}  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  /** @@ -774,40 +609,35 @@ 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 = [%d]\n", +			"key_size_bits = [%zd]\n",  			crypt_stat->cipher, (int)strlen(crypt_stat->cipher),  			crypt_stat->key_size << 3); +	mutex_lock(&crypt_stat->cs_tfm_mutex);  	if (crypt_stat->tfm) {  		rc = 0; -		goto out; +		goto out_unlock;  	} -	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); +	crypt_stat->tfm = crypto_alloc_ablkcipher(full_alg_name, 0, 0);  	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; +				full_alg_name); +		goto out_free;  	} -	crypto_blkcipher_set_flags(crypt_stat->tfm, CRYPTO_TFM_REQ_WEAK_KEY); +	crypto_ablkcipher_set_flags(crypt_stat->tfm, CRYPTO_TFM_REQ_WEAK_KEY);  	rc = 0; +out_free: +	kfree(full_alg_name);  out_unlock:  	mutex_unlock(&crypt_stat->cs_tfm_mutex); -out:  	return rc;  } @@ -970,7 +800,7 @@ static void ecryptfs_set_default_crypt_stat_vals(  /**   * ecryptfs_new_file_context - * @ecryptfs_dentry: The eCryptfs dentry + * @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 @@ -987,13 +817,13 @@ static void ecryptfs_set_default_crypt_stat_vals(   *   * Returns zero on success; non-zero otherwise   */ -int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry) +int ecryptfs_new_file_context(struct inode *ecryptfs_inode)  {  	struct ecryptfs_crypt_stat *crypt_stat = -	    &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->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_inode->i_sb)->mount_crypt_stat;  	int cipher_name_len;  	int rc = 0; @@ -1027,25 +857,25 @@ out:  }  /** - * contains_ecryptfs_marker - check for the ecryptfs marker + * ecryptfs_validate_marker - check for the ecryptfs marker   * @data: The data block in which to check   * - * Returns one if marker found; zero if not found + * Returns zero if marker found; -EINVAL if not found   */ -static int contains_ecryptfs_marker(char *data) +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 1; +		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 0; +	return -EINVAL;  }  struct ecryptfs_flag_map_elem { @@ -1204,27 +1034,19 @@ int ecryptfs_cipher_code_to_string(char *str, u8 cipher_code)  	return rc;  } -int ecryptfs_read_and_validate_header_region(char *data, -					     struct inode *ecryptfs_inode) +int ecryptfs_read_and_validate_header_region(struct inode *inode)  { -	struct ecryptfs_crypt_stat *crypt_stat = -		&(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat); +	u8 file_size[ECRYPTFS_SIZE_AND_MARKER_BYTES]; +	u8 *marker = file_size + ECRYPTFS_FILE_SIZE_BYTES;  	int rc; -	if (crypt_stat->extent_size == 0) -		crypt_stat->extent_size = ECRYPTFS_DEFAULT_EXTENT_SIZE; -	rc = ecryptfs_read_lower(data, 0, crypt_stat->extent_size, -				 ecryptfs_inode); -	if (rc < 0) { -		printk(KERN_ERR "%s: Error reading header region; rc = [%d]\n", -		       __func__, rc); -		goto out; -	} -	if (!contains_ecryptfs_marker(data + ECRYPTFS_FILE_SIZE_BYTES)) { -		rc = -EINVAL; -	} else -		rc = 0; -out: +	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;  } @@ -1245,8 +1067,7 @@ ecryptfs_write_header_metadata(char *virt,  	(*written) = 6;  } -struct kmem_cache *ecryptfs_header_cache_1; -struct kmem_cache *ecryptfs_header_cache_2; +struct kmem_cache *ecryptfs_header_cache;  /**   * ecryptfs_write_headers_virt @@ -1311,12 +1132,12 @@ static int ecryptfs_write_headers_virt(char *page_virt, size_t max,  }  static int -ecryptfs_write_metadata_to_contents(struct dentry *ecryptfs_dentry, +ecryptfs_write_metadata_to_contents(struct inode *ecryptfs_inode,  				    char *virt, size_t virt_len)  {  	int rc; -	rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, virt, +	rc = ecryptfs_write_lower(ecryptfs_inode, virt,  				  0, virt_len);  	if (rc < 0)  		printk(KERN_ERR "%s: Error attempting to write header " @@ -1350,7 +1171,8 @@ static unsigned long ecryptfs_get_zeroed_pages(gfp_t gfp_mask,  /**   * ecryptfs_write_metadata - * @ecryptfs_dentry: The eCryptfs dentry + * @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 @@ -1360,10 +1182,11 @@ static unsigned long ecryptfs_get_zeroed_pages(gfp_t gfp_mask,   *   * Returns zero on success; non-zero on error   */ -int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry) +int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry, +			    struct inode *ecryptfs_inode)  {  	struct ecryptfs_crypt_stat *crypt_stat = -		&ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat; +		&ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;  	unsigned int order;  	char *virt;  	size_t virt_len; @@ -1391,6 +1214,7 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry)  		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)) { @@ -1402,7 +1226,7 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry)  		rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry, virt,  						      size);  	else -		rc = ecryptfs_write_metadata_to_contents(ecryptfs_dentry, virt, +		rc = ecryptfs_write_metadata_to_contents(ecryptfs_inode, virt,  							 virt_len);  	if (rc) {  		printk(KERN_ERR "%s: Error writing metadata out to lower file; " @@ -1454,6 +1278,25 @@ 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 @@ -1479,11 +1322,11 @@ static int ecryptfs_read_headers_virt(char *page_virt,  	crypt_stat->mount_crypt_stat = &ecryptfs_superblock_to_private(  		ecryptfs_dentry->d_sb)->mount_crypt_stat;  	offset = ECRYPTFS_FILE_SIZE_BYTES; -	rc = contains_ecryptfs_marker(page_virt + offset); -	if (rc == 0) { -		rc = -EINVAL; +	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); @@ -1548,20 +1391,21 @@ out:  	return rc;  } -int ecryptfs_read_and_validate_xattr_region(char *page_virt, -					    struct dentry *ecryptfs_dentry) +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_read_xattr_region(page_virt, ecryptfs_dentry->d_inode); -	if (rc) -		goto out; -	if (!contains_ecryptfs_marker(page_virt	+ ECRYPTFS_FILE_SIZE_BYTES)) { -		printk(KERN_WARNING "Valid data found in [%s] xattr, but " -			"the marker is invalid\n", ECRYPTFS_XATTR_NAME); -		rc = -EINVAL; -	} -out: +	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;  } @@ -1579,8 +1423,8 @@ out:   */  int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)  { -	int rc = 0; -	char *page_virt = NULL; +	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; @@ -1591,7 +1435,7 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)  	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_1, GFP_USER); +	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", @@ -1605,11 +1449,13 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)  						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\n"); +			       "file header region or xattr region, inode %lu\n", +				ecryptfs_inode->i_ino);  			rc = -EINVAL;  			goto out;  		} @@ -1618,7 +1464,8 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)  						ECRYPTFS_DONT_VALIDATE_HEADER_SIZE);  		if (rc) {  			printk(KERN_DEBUG "Valid eCryptfs headers not found in " -			       "file xattr region either\n"); +			       "file xattr region either, inode %lu\n", +				ecryptfs_inode->i_ino);  			rc = -EINVAL;  		}  		if (crypt_stat->mount_crypt_stat->flags @@ -1629,14 +1476,15 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)  			       "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.\n"); +			       "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_1, page_virt); +		kmem_cache_free(ecryptfs_header_cache, page_virt);  	}  	return rc;  } @@ -1934,7 +1782,7 @@ static unsigned char *portable_filename_chars = ("-.0123456789ABCD"  /* 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[] = { +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 */ @@ -1950,7 +1798,7 @@ static const unsigned char filename_rev_map[] = {  	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 +	0x3D, 0x3E, 0x3F /* 123 - 255 initialized to 0x00 */  };  /** @@ -1960,7 +1808,7 @@ static const unsigned char filename_rev_map[] = {   * @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, +static void ecryptfs_encode_for_filename(unsigned char *dst, size_t *dst_size,  				  unsigned char *src, size_t src_size)  {  	size_t num_blocks; @@ -2015,6 +1863,17 @@ 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 @@ -2033,13 +1892,7 @@ ecryptfs_decode_from_filename(unsigned char *dst, size_t *dst_size,  	size_t dst_byte_offset = 0;  	if (dst == NULL) { -		/* 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. */ -		(*dst_size) = (((src_size + 1) * 3) / 4); +		(*dst_size) = ecryptfs_max_decoded_size(src_size);  		goto out;  	}  	while (src_byte_offset < src_size) { @@ -2205,12 +2058,11 @@ out:   */  int ecryptfs_decode_and_decrypt_filename(char **plaintext_name,  					 size_t *plaintext_name_size, -					 struct dentry *ecryptfs_dir_dentry, +					 struct super_block *sb,  					 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; +		&ecryptfs_superblock_to_private(sb)->mount_crypt_stat;  	char *decoded_name;  	size_t decoded_name_size;  	size_t packet_size; @@ -2264,3 +2116,52 @@ out_free:  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/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c index 906e803f7f7..4000f6b3a75 100644 --- a/fs/ecryptfs/dentry.c +++ b/fs/ecryptfs/dentry.c @@ -32,7 +32,7 @@  /**   * ecryptfs_d_revalidate - revalidate an ecryptfs dentry   * @dentry: The ecryptfs dentry - * @nd: The associated nameidata + * @flags: lookup flags   *   * Called when the VFS needs to revalidate a dentry. This   * is called whenever a name lookup finds a dentry in the @@ -42,35 +42,35 @@   * Returns 1 if valid, 0 otherwise.   *   */ -static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd) +static int ecryptfs_d_revalidate(struct dentry *dentry, unsigned int flags)  {  	struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); -	struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); -	struct dentry *dentry_save; -	struct vfsmount *vfsmount_save; -	int rc = 1; +	int rc; -	if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate) -		goto out; -	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); -	nd->path.dentry = dentry_save; -	nd->path.mnt = vfsmount_save; +	if (!(lower_dentry->d_flags & DCACHE_OP_REVALIDATE)) +		return 1; + +	if (flags & LOOKUP_RCU) +		return -ECHILD; + +	rc = lower_dentry->d_op->d_revalidate(lower_dentry, flags);  	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; +static void ecryptfs_dentry_free_rcu(struct rcu_head *head) +{ +	kmem_cache_free(ecryptfs_dentry_info_cache, +		container_of(head, struct ecryptfs_dentry_info, rcu)); +} +  /**   * ecryptfs_d_release   * @dentry: The ecryptfs dentry @@ -79,15 +79,11 @@ struct kmem_cache *ecryptfs_dentry_info_cache;   */  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)); +	struct ecryptfs_dentry_info *p = dentry->d_fsdata; +	if (p) { +		path_put(&p->lower_path); +		call_rcu(&p->rcu, ecryptfs_dentry_free_rcu);  	} -	return;  }  const struct dentry_operations ecryptfs_dops = { diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 413a3c48f0b..90d1882b306 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -29,6 +29,7 @@  #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> @@ -36,125 +37,19 @@  #include <linux/hash.h>  #include <linux/nsproxy.h>  #include <linux/backing-dev.h> +#include <linux/ecryptfs.h> +#include <linux/crypto.h> -/* Version verification for shared data structures w/ userspace */ -#define ECRYPTFS_VERSION_MAJOR 0x00 -#define ECRYPTFS_VERSION_MINOR 0x04 -#define ECRYPTFS_SUPPORTED_FILE_VERSION 0x03 -/* These flags indicate which features are supported by the kernel - * module; userspace tools such as the mount helper read - * ECRYPTFS_VERSIONING_MASK from a sysfs handle in order to determine - * how to behave. */ -#define ECRYPTFS_VERSIONING_PASSPHRASE            0x00000001 -#define ECRYPTFS_VERSIONING_PUBKEY                0x00000002 -#define ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH 0x00000004 -#define ECRYPTFS_VERSIONING_POLICY                0x00000008 -#define ECRYPTFS_VERSIONING_XATTR                 0x00000010 -#define ECRYPTFS_VERSIONING_MULTKEY               0x00000020 -#define ECRYPTFS_VERSIONING_DEVMISC               0x00000040 -#define ECRYPTFS_VERSIONING_HMAC                  0x00000080 -#define ECRYPTFS_VERSIONING_FILENAME_ENCRYPTION   0x00000100 -#define ECRYPTFS_VERSIONING_GCM                   0x00000200 -#define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \ -				  | ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH \ -				  | ECRYPTFS_VERSIONING_PUBKEY \ -				  | ECRYPTFS_VERSIONING_XATTR \ -				  | ECRYPTFS_VERSIONING_MULTKEY \ -				  | ECRYPTFS_VERSIONING_DEVMISC \ -				  | ECRYPTFS_VERSIONING_FILENAME_ENCRYPTION) -#define ECRYPTFS_MAX_PASSWORD_LENGTH 64 -#define ECRYPTFS_MAX_PASSPHRASE_BYTES ECRYPTFS_MAX_PASSWORD_LENGTH -#define ECRYPTFS_SALT_SIZE 8 -#define ECRYPTFS_SALT_SIZE_HEX (ECRYPTFS_SALT_SIZE*2) -/* The original signature size is only for what is stored on disk; all - * in-memory representations are expanded hex, so it better adapted to - * be passed around or referenced on the command line */ -#define ECRYPTFS_SIG_SIZE 8 -#define ECRYPTFS_SIG_SIZE_HEX (ECRYPTFS_SIG_SIZE*2) -#define ECRYPTFS_PASSWORD_SIG_SIZE ECRYPTFS_SIG_SIZE_HEX -#define ECRYPTFS_MAX_KEY_BYTES 64 -#define ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES 512  #define ECRYPTFS_DEFAULT_IV_BYTES 16 -#define ECRYPTFS_FILE_VERSION 0x03  #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_MAX_PKI_NAME_BYTES 16  #define ECRYPTFS_DEFAULT_NUM_USERS 4  #define ECRYPTFS_MAX_NUM_USERS 32768  #define ECRYPTFS_XATTR_NAME "user.ecryptfs" -#define RFC2440_CIPHER_DES3_EDE 0x02 -#define RFC2440_CIPHER_CAST_5 0x03 -#define RFC2440_CIPHER_BLOWFISH 0x04 -#define RFC2440_CIPHER_AES_128 0x07 -#define RFC2440_CIPHER_AES_192 0x08 -#define RFC2440_CIPHER_AES_256 0x09 -#define RFC2440_CIPHER_TWOFISH 0x0a -#define RFC2440_CIPHER_CAST_6 0x0b - -#define RFC2440_CIPHER_RSA 0x01 - -/** - * For convenience, we may need to pass around the encrypted session - * key between kernel and userspace because the authentication token - * may not be extractable.  For example, the TPM may not release the - * private key, instead requiring the encrypted data and returning the - * decrypted data. - */ -struct ecryptfs_session_key { -#define ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT 0x00000001 -#define ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT 0x00000002 -#define ECRYPTFS_CONTAINS_DECRYPTED_KEY 0x00000004 -#define ECRYPTFS_CONTAINS_ENCRYPTED_KEY 0x00000008 -	u32 flags; -	u32 encrypted_key_size; -	u32 decrypted_key_size; -	u8 encrypted_key[ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES]; -	u8 decrypted_key[ECRYPTFS_MAX_KEY_BYTES]; -}; - -struct ecryptfs_password { -	u32 password_bytes; -	s32 hash_algo; -	u32 hash_iterations; -	u32 session_key_encryption_key_bytes; -#define ECRYPTFS_PERSISTENT_PASSWORD 0x01 -#define ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET 0x02 -	u32 flags; -	/* Iterated-hash concatenation of salt and passphrase */ -	u8 session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES]; -	u8 signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1]; -	/* Always in expanded hex */ -	u8 salt[ECRYPTFS_SALT_SIZE]; -}; - -enum ecryptfs_token_types {ECRYPTFS_PASSWORD, ECRYPTFS_PRIVATE_KEY}; - -struct ecryptfs_private_key { -	u32 key_size; -	u32 data_len; -	u8 signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1]; -	char pki_type[ECRYPTFS_MAX_PKI_NAME_BYTES + 1]; -	u8 data[]; -}; - -/* May be a password or a private key */ -struct ecryptfs_auth_tok { -	u16 version; /* 8-bit major and 8-bit minor */ -	u16 token_type; -#define ECRYPTFS_ENCRYPT_ONLY 0x00000001 -	u32 flags; -	struct ecryptfs_session_key session_key; -	u8 reserved[32]; -	union { -		struct ecryptfs_password password; -		struct ecryptfs_private_key private_key; -	} token; -} __attribute__ ((packed)); -  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); @@ -185,14 +80,49 @@ struct ecryptfs_page_crypt_context {  	} 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)  { -	return (struct ecryptfs_auth_tok *) -		(((struct user_key_payload*)key->payload.data)->data); +	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_SUPER_MAGIC 0xf15f  #define ECRYPTFS_MAX_KEYSET_SIZE 1024  #define ECRYPTFS_MAX_CIPHER_NAME_SIZE 32  #define ECRYPTFS_MAX_NUM_ENC_KEYS 64 @@ -201,6 +131,8 @@ ecryptfs_get_key_payload_data(struct key *key)  #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" @@ -220,21 +152,43 @@ ecryptfs_get_key_payload_data(struct key *key)  					  * 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) +#ifdef CONFIG_ECRYPT_FS_MESSAGING +# define ECRYPTFS_VERSIONING_MASK_MESSAGING (ECRYPTFS_VERSIONING_DEVMISC \ +					     | ECRYPTFS_VERSIONING_PUBKEY) +#else +# define ECRYPTFS_VERSIONING_MASK_MESSAGING 0 +#endif + +#define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \ +				  | ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH \ +				  | ECRYPTFS_VERSIONING_XATTR \ +				  | ECRYPTFS_VERSIONING_MULTKEY \ +				  | ECRYPTFS_VERSIONING_MASK_MESSAGING \ +				  | ECRYPTFS_VERSIONING_FILENAME_ENCRYPTION)  struct ecryptfs_key_sig {  	struct list_head crypt_stat_list; -	char keysig[ECRYPTFS_SIG_SIZE_HEX]; +	char keysig[ECRYPTFS_SIG_SIZE_HEX + 1];  };  struct ecryptfs_filename { @@ -258,19 +212,19 @@ struct ecryptfs_filename {  struct ecryptfs_crypt_stat {  #define ECRYPTFS_STRUCT_INITIALIZED   0x00000001  #define ECRYPTFS_POLICY_APPLIED       0x00000002 -#define ECRYPTFS_NEW_FILE             0x00000004 -#define ECRYPTFS_ENCRYPTED            0x00000008 -#define ECRYPTFS_SECURITY_WARNING     0x00000010 -#define ECRYPTFS_ENABLE_HMAC          0x00000020 -#define ECRYPTFS_ENCRYPT_IV_PAGES     0x00000040 -#define ECRYPTFS_KEY_VALID            0x00000080 -#define ECRYPTFS_METADATA_IN_XATTR    0x00000100 -#define ECRYPTFS_VIEW_AS_ENCRYPTED    0x00000200 -#define ECRYPTFS_KEY_SET              0x00000400 -#define ECRYPTFS_ENCRYPT_FILENAMES    0x00000800 -#define ECRYPTFS_ENCFN_USE_MOUNT_FNEK 0x00001000 -#define ECRYPTFS_ENCFN_USE_FEK        0x00002000 -#define ECRYPTFS_UNLINK_SIGS	      0x00004000 +#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; @@ -280,7 +234,7 @@ struct ecryptfs_crypt_stat {  	size_t extent_shift;  	unsigned int extent_mask;  	struct ecryptfs_mount_crypt_stat *mount_crypt_stat; -	struct crypto_blkcipher *tfm; +	struct crypto_ablkcipher *tfm;  	struct crypto_hash *hash_tfm; /* Crypto context for generating  				       * the initialization vectors */  	unsigned char cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE]; @@ -297,8 +251,9 @@ struct ecryptfs_crypt_stat {  struct ecryptfs_inode_info {  	struct inode vfs_inode;  	struct inode *wii_inode; -	struct file *lower_file;  	struct mutex lower_file_mutex; +	atomic_t lower_file_count; +	struct file *lower_file;  	struct ecryptfs_crypt_stat crypt_stat;  }; @@ -306,7 +261,10 @@ struct ecryptfs_inode_info {   * vfsmount too. */  struct ecryptfs_dentry_info {  	struct path lower_path; -	struct ecryptfs_crypt_stat *crypt_stat; +	union { +		struct ecryptfs_crypt_stat *crypt_stat; +		struct rcu_head rcu; +	};  };  /** @@ -334,7 +292,6 @@ struct ecryptfs_global_auth_tok {  	u32 flags;  	struct list_head mount_crypt_stat_list;  	struct key *global_auth_tok_key; -	struct ecryptfs_auth_tok *global_auth_tok;  	unsigned char sig[ECRYPTFS_SIG_SIZE_HEX + 1];  }; @@ -381,7 +338,6 @@ struct ecryptfs_mount_crypt_stat {  	u32 flags;  	struct list_head global_auth_tok_list;  	struct mutex global_auth_tok_list_mutex; -	size_t num_global_auth_toks;  	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 @@ -446,8 +402,6 @@ struct ecryptfs_msg_ctx {  	struct mutex mux;  }; -struct ecryptfs_daemon; -  struct ecryptfs_daemon {  #define ECRYPTFS_DAEMON_IN_READ      0x00000001  #define ECRYPTFS_DAEMON_IN_POLL      0x00000002 @@ -455,17 +409,16 @@ struct ecryptfs_daemon {  #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 file *file;  	struct mutex mux;  	struct list_head msg_ctx_out_queue;  	wait_queue_head_t wait;  	struct hlist_node euid_chain;  }; +#ifdef CONFIG_ECRYPT_FS_MESSAGING  extern struct mutex ecryptfs_daemon_hash_mux; +#endif  static inline size_t  ecryptfs_lower_header_size(struct ecryptfs_crypt_stat *crypt_stat) @@ -562,28 +515,21 @@ 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) +static inline struct path * +ecryptfs_dentry_to_lower_path(struct dentry *dentry)  { -	((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.mnt = -		lower_mnt; +	return &((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path;  }  #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; @@ -604,39 +550,21 @@ 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_1; -extern struct kmem_cache *ecryptfs_header_cache_2; +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; -}; -#define ECRYPTFS_INTERPOSE_FLAG_D_ADD                 0x00000001 -int ecryptfs_interpose(struct dentry *hidden_dentry, -		       struct dentry *this_dentry, struct super_block *sb, -		       u32 flags); -int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, -					struct dentry *lower_dentry, -					struct inode *ecryptfs_dir_inode, -					struct nameidata *ecryptfs_nd); +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_initialize_file(struct dentry *ecryptfs_dentry, +			     struct inode *ecryptfs_inode);  int ecryptfs_decode_and_decrypt_filename(char **decrypted_name,  					 size_t *decrypted_name_size, -					 struct dentry *ecryptfs_dentry, +					 struct super_block *sb,  					 const char *name, size_t name_size);  int ecryptfs_fill_zeros(struct file *file, loff_t new_length);  int ecryptfs_encrypt_and_encode_filename( @@ -659,16 +587,16 @@ 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); +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 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(char *data, -					     struct inode *ecryptfs_inode); -int ecryptfs_read_and_validate_xattr_region(char *page_virt, -					    struct dentry *ecryptfs_dentry); +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); @@ -680,9 +608,6 @@ 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); -int ecryptfs_inode_test(struct inode *inode, void *candidate_lower_inode); -int ecryptfs_inode_set(struct inode *inode, void *lower_inode); -void ecryptfs_init_inode(struct inode *inode, struct inode *lower_inode);  ssize_t  ecryptfs_getxattr_lower(struct dentry *lower_dentry, const char *name,  			void *value, size_t size); @@ -690,19 +615,33 @@ 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); +#ifdef CONFIG_ECRYPT_FS_MESSAGING +int ecryptfs_process_response(struct ecryptfs_daemon *daemon, +			      struct ecryptfs_message *msg, 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); +#else +static inline int ecryptfs_init_messaging(void) +{ +	return 0; +} +static inline void ecryptfs_release_messaging(void) +{ } +static inline int ecryptfs_send_message(char *data, int data_len, +					struct ecryptfs_msg_ctx **msg_ctx) +{ +	return -ENOTCONN; +} +static inline int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx, +					     struct ecryptfs_message **emsg) +{ +	return -ENOMSG; +} +#endif  void  ecryptfs_write_header_metadata(char *virt, @@ -740,13 +679,11 @@ int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs,  				     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); +#ifdef CONFIG_ECRYPT_FS_MESSAGING  int ecryptfs_init_ecryptfs_miscdev(void);  void ecryptfs_destroy_ecryptfs_miscdev(void);  int ecryptfs_send_miscdev(char *data, size_t data_size, @@ -754,15 +691,18 @@ int ecryptfs_send_miscdev(char *data, size_t data_size,  			  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); +ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, struct file *file); +int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon); +int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon); +#endif  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_init_persistent_file(struct dentry *ecryptfs_dentry); +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, @@ -773,6 +713,8 @@ 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); diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index 91da02987bf..db0fad3269c 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -31,6 +31,7 @@  #include <linux/security.h>  #include <linux/compat.h>  #include <linux/fs_stack.h> +#include <linux/aio.h>  #include "ecryptfs_kernel.h"  /** @@ -44,15 +45,13 @@   * 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) +				struct iov_iter *to)  { -	int rc; -	struct dentry *lower_dentry; -	struct vfsmount *lower_vfsmount; +	ssize_t rc; +	struct path *path;  	struct file *file = iocb->ki_filp; -	rc = generic_file_aio_read(iocb, iov, nr_segs, pos); +	rc = generic_file_read_iter(iocb, to);  	/*  	 * Even though this is a async interface, we need to wait  	 * for IO to finish to update atime @@ -60,17 +59,16 @@ static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb,  	if (-EIOCBQUEUED == rc)  		rc = wait_on_sync_kiocb(iocb);  	if (rc >= 0) { -		lower_dentry = ecryptfs_dentry_to_lower(file->f_path.dentry); -		lower_vfsmount = ecryptfs_dentry_to_lower_mnt(file->f_path.dentry); -		touch_atime(lower_vfsmount, lower_dentry); +		path = ecryptfs_dentry_to_lower_path(file->f_path.dentry); +		touch_atime(path);  	}  	return rc;  }  struct ecryptfs_getdents_callback { -	void *dirent; -	struct dentry *dentry; -	filldir_t filldir; +	struct dir_context ctx; +	struct dir_context *caller; +	struct super_block *sb;  	int filldir_called;  	int entries_written;  }; @@ -88,7 +86,7 @@ ecryptfs_filldir(void *dirent, const char *lower_name, int lower_namelen,  	buf->filldir_called++;  	rc = ecryptfs_decode_and_decrypt_filename(&name, &name_size, -						  buf->dentry, lower_name, +						  buf->sb, lower_name,  						  lower_namelen);  	if (rc) {  		printk(KERN_ERR "%s: Error attempting to decode and decrypt " @@ -96,9 +94,10 @@ ecryptfs_filldir(void *dirent, const char *lower_name, int lower_namelen,  		       rc);  		goto out;  	} -	rc = buf->filldir(buf->dirent, name, name_size, offset, ino, d_type); +	buf->caller->pos = buf->ctx.pos; +	rc = !dir_emit(buf->caller, name, name_size, ino, d_type);  	kfree(name); -	if (rc >= 0) +	if (!rc)  		buf->entries_written++;  out:  	return rc; @@ -107,40 +106,77 @@ out:  /**   * ecryptfs_readdir   * @file: The eCryptfs directory file - * @dirent: Directory entry handle - * @filldir: The filldir callback function + * @ctx: The actor to feed the entries to   */ -static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir) +static int ecryptfs_readdir(struct file *file, struct dir_context *ctx)  {  	int rc;  	struct file *lower_file; -	struct inode *inode; -	struct ecryptfs_getdents_callback buf; - +	struct inode *inode = file_inode(file); +	struct ecryptfs_getdents_callback buf = { +		.ctx.actor = ecryptfs_filldir, +		.caller = ctx, +		.sb = inode->i_sb, +	};  	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; +	lower_file->f_pos = ctx->pos; +	rc = iterate_dir(lower_file, &buf.ctx); +	ctx->pos = buf.ctx.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); +					file_inode(lower_file));  out:  	return rc;  }  struct kmem_cache *ecryptfs_file_info_cache; +static int read_or_initialize_metadata(struct dentry *dentry) +{ +	struct inode *inode = dentry->d_inode; +	struct ecryptfs_mount_crypt_stat *mount_crypt_stat; +	struct ecryptfs_crypt_stat *crypt_stat; +	int rc; + +	crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; +	mount_crypt_stat = &ecryptfs_superblock_to_private( +						inode->i_sb)->mount_crypt_stat; +	mutex_lock(&crypt_stat->cs_mutex); + +	if (crypt_stat->flags & ECRYPTFS_POLICY_APPLIED && +	    crypt_stat->flags & ECRYPTFS_KEY_VALID) { +		rc = 0; +		goto out; +	} + +	rc = ecryptfs_read_metadata(dentry); +	if (!rc) +		goto out; + +	if (mount_crypt_stat->flags & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED) { +		crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED +				       | ECRYPTFS_ENCRYPTED); +		rc = 0; +		goto out; +	} + +	if (!(mount_crypt_stat->flags & ECRYPTFS_XATTR_METADATA_ENABLED) && +	    !i_size_read(ecryptfs_inode_to_lower(inode))) { +		rc = ecryptfs_initialize_file(dentry, inode); +		if (!rc) +			goto out; +	} + +	rc = -EIO; +out: +	mutex_unlock(&crypt_stat->cs_mutex); +	return rc; +} +  /**   * ecryptfs_open   * @inode: inode speciying file to open @@ -158,7 +194,6 @@ static int ecryptfs_open(struct inode *inode, struct file *file)  	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( @@ -181,7 +216,6 @@ static int ecryptfs_open(struct inode *inode, struct file *file)  		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)) { @@ -191,22 +225,20 @@ static int ecryptfs_open(struct inode *inode, struct file *file)  				      | ECRYPTFS_ENCRYPTED);  	}  	mutex_unlock(&crypt_stat->cs_mutex); -	if (!ecryptfs_inode_to_private(inode)->lower_file) { -		rc = ecryptfs_init_persistent_file(ecryptfs_dentry); -		if (rc) { -			printk(KERN_ERR "%s: Error attempting to initialize " -			       "the persistent file for the dentry with name " -			       "[%s]; rc = [%d]\n", __func__, -			       ecryptfs_dentry->d_name.name, rc); -			goto out_free; -		} +	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_RDONLY) -	    && !(file->f_flags & O_RDONLY)) { +	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 persistent file is RO; eCryptfs " +		printk(KERN_WARNING "%s: Lower file is RO; eCryptfs "  		       "file must hence be opened RO\n", __func__); -		goto out_free; +		goto out_put;  	}  	ecryptfs_set_file_lower(  		file, ecryptfs_inode_to_private(inode)->lower_file); @@ -218,35 +250,15 @@ static int ecryptfs_open(struct inode *inode, struct file *file)  		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_free; -			} -			rc = 0; -			crypt_stat->flags &= ~(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%.16x] " -			"size: [0x%.16x]\n", inode, inode->i_ino, -			i_size_read(inode)); +	rc = read_or_initialize_metadata(ecryptfs_dentry); +	if (rc) +		goto out_put; +	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)); @@ -256,25 +268,33 @@ out:  static int ecryptfs_flush(struct file *file, fl_owner_t td)  { -	int rc = 0; -	struct file *lower_file = NULL; +	struct file *lower_file = ecryptfs_file_to_lower(file); -	lower_file = ecryptfs_file_to_lower(file); -	if (lower_file->f_op && lower_file->f_op->flush) -		rc = lower_file->f_op->flush(lower_file, td); -	return rc; +	if (lower_file->f_op->flush) { +		filemap_write_and_wait(file->f_mapping); +		return lower_file->f_op->flush(lower_file, td); +	} + +	return 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, int datasync) +ecryptfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)  { +	int rc; + +	rc = filemap_write_and_wait(file->f_mapping); +	if (rc) +		return rc; +  	return vfs_fsync(ecryptfs_file_to_lower(file), datasync);  } @@ -284,7 +304,7 @@ static int ecryptfs_fasync(int fd, struct file *file, int flag)  	struct file *lower_file = NULL;  	lower_file = ecryptfs_file_to_lower(file); -	if (lower_file->f_op && lower_file->f_op->fasync) +	if (lower_file->f_op->fasync)  		rc = lower_file->f_op->fasync(fd, lower_file, flag);  	return rc;  } @@ -292,12 +312,10 @@ static int ecryptfs_fasync(int fd, struct file *file, int flag)  static long  ecryptfs_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)  { -	struct file *lower_file = NULL; +	struct file *lower_file = ecryptfs_file_to_lower(file);  	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) +	if (lower_file->f_op->unlocked_ioctl)  		rc = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg);  	return rc;  } @@ -306,19 +324,18 @@ ecryptfs_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)  static long  ecryptfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)  { -	struct file *lower_file = NULL; +	struct file *lower_file = ecryptfs_file_to_lower(file);  	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) +	if (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, +	.iterate = ecryptfs_readdir, +	.read = generic_read_dir,  	.unlocked_ioctl = ecryptfs_unlocked_ioctl,  #ifdef CONFIG_COMPAT  	.compat_ioctl = ecryptfs_compat_ioctl, @@ -334,11 +351,11 @@ const struct file_operations ecryptfs_dir_fops = {  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, +	.read = new_sync_read, +	.read_iter = ecryptfs_read_update_atime, +	.write = new_sync_write, +	.write_iter = generic_file_write_iter, +	.iterate = ecryptfs_readdir,  	.unlocked_ioctl = ecryptfs_unlocked_ioctl,  #ifdef CONFIG_COMPAT  	.compat_ioctl = ecryptfs_compat_ioctl, diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 9d1a22d6276..d4a9431ec73 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -51,39 +51,120 @@ static void unlock_dir(struct dentry *dir)  	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_create_underlying_file - * @lower_dir_inode: inode of the parent in the lower fs of the new file - * @dentry: New file's dentry - * @mode: The mode of the new file - * @nd: nameidata of ecryptfs' parent's dentry & vfsmount + * ecryptfs_interpose + * @lower_dentry: Existing dentry in the lower filesystem + * @dentry: ecryptfs' dentry + * @sb: ecryptfs's super_block   * - * Creates the file in the lower file system. + * Interposes upper and lower dentries.   * - * Returns zero on success; non-zero on error condition + * Returns zero on success; non-zero otherwise   */ -static int -ecryptfs_create_underlying_file(struct inode *lower_dir_inode, -				struct dentry *dentry, int mode, -				struct nameidata *nd) +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; +} + +static int ecryptfs_do_unlink(struct inode *dir, struct dentry *dentry, +			      struct inode *inode)  {  	struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); -	struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); -	struct dentry *dentry_save; -	struct vfsmount *vfsmount_save; -	unsigned int flags_save; +	struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir); +	struct dentry *lower_dir_dentry;  	int rc; -	dentry_save = nd->path.dentry; -	vfsmount_save = nd->path.mnt; -	flags_save = nd->flags; -	nd->path.dentry = lower_dentry; -	nd->path.mnt = lower_mnt; -	nd->flags &= ~LOOKUP_OPEN; -	rc = vfs_create(lower_dir_inode, lower_dentry, mode, nd); -	nd->path.dentry = dentry_save; -	nd->path.mnt = vfsmount_save; -	nd->flags = flags_save; +	dget(lower_dentry); +	lower_dir_dentry = lock_parent(lower_dentry); +	rc = vfs_unlink(lower_dir_inode, lower_dentry, NULL); +	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(inode, ecryptfs_inode_to_lower(inode)->i_nlink); +	inode->i_ctime = dir->i_ctime; +	d_drop(dentry); +out_unlock: +	unlock_dir(lower_dir_dentry); +	dput(lower_dentry);  	return rc;  } @@ -98,36 +179,36 @@ ecryptfs_create_underlying_file(struct inode *lower_dir_inode,   * it. It will also update the eCryptfs directory inode to mimic the   * stat of the lower directory inode.   * - * Returns zero on success; non-zero on error condition + * Returns the new eCryptfs inode on success; an ERR_PTR on error condition   */ -static int +static struct inode *  ecryptfs_do_create(struct inode *directory_inode, -		   struct dentry *ecryptfs_dentry, int mode, -		   struct nameidata *nd) +		   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"); -		rc = PTR_ERR(lower_dir_dentry); +		inode = ERR_CAST(lower_dir_dentry);  		goto out;  	} -	rc = ecryptfs_create_underlying_file(lower_dir_dentry->d_inode, -					     ecryptfs_dentry, mode, nd); +	rc = vfs_create(lower_dir_dentry->d_inode, lower_dentry, mode, true);  	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;  	} -	rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry, -				directory_inode->i_sb, 0); -	if (rc) { -		ecryptfs_printk(KERN_ERR, "Failure in ecryptfs_interpose\n"); +	inode = __ecryptfs_get_inode(lower_dentry->d_inode, +				     directory_inode->i_sb); +	if (IS_ERR(inode)) { +		vfs_unlink(lower_dir_dentry->d_inode, lower_dentry, NULL);  		goto out_lock;  	}  	fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode); @@ -135,27 +216,7 @@ ecryptfs_do_create(struct inode *directory_inode,  out_lock:  	unlock_dir(lower_dir_dentry);  out: -	return rc; -} - -/** - * grow_file - * @ecryptfs_dentry: the eCryptfs dentry - * - * This is the code which will grow the file to its correct size. - */ -static int grow_file(struct dentry *ecryptfs_dentry) -{ -	struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode; -	char zero_virt[] = { 0x00 }; -	int rc = 0; - -	rc = ecryptfs_write(ecryptfs_inode, zero_virt, 0, 1); -	i_size_write(ecryptfs_inode, 0); -	rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode); -	ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat.flags |= -		ECRYPTFS_NEW_FILE; -	return rc; +	return inode;  }  /** @@ -166,43 +227,37 @@ static int grow_file(struct dentry *ecryptfs_dentry)   *   * Returns zero on success   */ -static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) +int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry, +			     struct inode *ecryptfs_inode)  {  	struct ecryptfs_crypt_stat *crypt_stat = -		&ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat; +		&ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;  	int rc = 0; -	if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { +	if (S_ISDIR(ecryptfs_inode->i_mode)) {  		ecryptfs_printk(KERN_DEBUG, "This is a directory\n");  		crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);  		goto out;  	} -	crypt_stat->flags |= ECRYPTFS_NEW_FILE;  	ecryptfs_printk(KERN_DEBUG, "Initializing crypto context\n"); -	rc = ecryptfs_new_file_context(ecryptfs_dentry); +	rc = ecryptfs_new_file_context(ecryptfs_inode);  	if (rc) {  		ecryptfs_printk(KERN_ERR, "Error creating new file "  				"context; rc = [%d]\n", rc);  		goto out;  	} -	if (!ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->lower_file) { -		rc = ecryptfs_init_persistent_file(ecryptfs_dentry); -		if (rc) { -			printk(KERN_ERR "%s: Error attempting to initialize " -			       "the persistent 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); +	rc = ecryptfs_get_lower_file(ecryptfs_dentry, ecryptfs_inode);  	if (rc) { -		printk(KERN_ERR "Error writing headers; rc = [%d]\n", 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 = grow_file(ecryptfs_dentry); +	rc = ecryptfs_write_metadata(ecryptfs_dentry, ecryptfs_inode);  	if (rc) -		printk(KERN_ERR "Error growing file; rc = [%d]\n", rc); +		printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc); +	ecryptfs_put_lower_file(ecryptfs_inode);  out:  	return rc;  } @@ -212,7 +267,6 @@ out:   * @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.   * @@ -220,205 +274,120 @@ out:   */  static int  ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry, -		int mode, struct nameidata *nd) +		umode_t mode, bool excl)  { +	struct inode *ecryptfs_inode;  	int rc; -	/* ecryptfs_do_create() calls ecryptfs_interpose() */ -	rc = ecryptfs_do_create(directory_inode, ecryptfs_dentry, mode, nd); -	if (unlikely(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); +	rc = ecryptfs_initialize_file(ecryptfs_dentry, ecryptfs_inode); +	if (rc) { +		ecryptfs_do_unlink(directory_inode, ecryptfs_dentry, +				   ecryptfs_inode); +		make_bad_inode(ecryptfs_inode); +		unlock_new_inode(ecryptfs_inode); +		iput(ecryptfs_inode); +		goto out; +	} +	unlock_new_inode(ecryptfs_inode); +	d_instantiate(ecryptfs_dentry, ecryptfs_inode);  out:  	return rc;  } -/** - * ecryptfs_lookup_and_interpose_lower - Perform a lookup - */ -int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, -					struct dentry *lower_dentry, -					struct inode *ecryptfs_dir_inode, -					struct nameidata *ecryptfs_nd) +static int ecryptfs_i_size_read(struct dentry *dentry, struct inode *inode)  { -	struct dentry *lower_dir_dentry; -	struct vfsmount *lower_mnt; -	struct inode *lower_inode; -	struct ecryptfs_mount_crypt_stat *mount_crypt_stat;  	struct ecryptfs_crypt_stat *crypt_stat; -	char *page_virt = NULL; -	u64 file_size; -	int rc = 0; +	int rc; -	lower_dir_dentry = lower_dentry->d_parent; -	lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt( -				   ecryptfs_dentry->d_parent)); -	lower_inode = lower_dentry->d_inode; -	fsstack_copy_attr_atime(ecryptfs_dir_inode, lower_dir_dentry->d_inode); -	BUG_ON(!atomic_read(&lower_dentry->d_count)); -	ecryptfs_set_dentry_private(ecryptfs_dentry, -				    kmem_cache_alloc(ecryptfs_dentry_info_cache, -						     GFP_KERNEL)); -	if (!ecryptfs_dentry_to_private(ecryptfs_dentry)) { -		rc = -ENOMEM; -		printk(KERN_ERR "%s: Out of memory whilst attempting " -		       "to allocate ecryptfs_dentry_info struct\n", -			__func__); -		goto out_put; -	} -	ecryptfs_set_dentry_lower(ecryptfs_dentry, lower_dentry); -	ecryptfs_set_dentry_lower_mnt(ecryptfs_dentry, lower_mnt); -	if (!lower_dentry->d_inode) { -		/* We want to add because we couldn't find in lower */ -		d_add(ecryptfs_dentry, NULL); -		goto out; -	} -	rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry, -				ecryptfs_dir_inode->i_sb, -				ECRYPTFS_INTERPOSE_FLAG_D_ADD); +	rc = ecryptfs_get_lower_file(dentry, inode);  	if (rc) { -		printk(KERN_ERR "%s: Error interposing; rc = [%d]\n", -		       __func__, rc); -		goto out; -	} -	if (S_ISDIR(lower_inode->i_mode)) -		goto out; -	if (S_ISLNK(lower_inode->i_mode)) -		goto out; -	if (special_file(lower_inode->i_mode)) -		goto out; -	if (!ecryptfs_nd) -		goto out; -	/* Released in this function */ -	page_virt = kmem_cache_zalloc(ecryptfs_header_cache_2, GFP_USER); -	if (!page_virt) { -		printk(KERN_ERR "%s: Cannot kmem_cache_zalloc() a page\n", -		       __func__); -		rc = -ENOMEM; -		goto out; +		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;  	} -	if (!ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->lower_file) { -		rc = ecryptfs_init_persistent_file(ecryptfs_dentry); -		if (rc) { -			printk(KERN_ERR "%s: Error attempting to initialize " -			       "the persistent file for the dentry with name " -			       "[%s]; rc = [%d]\n", __func__, -			       ecryptfs_dentry->d_name.name, rc); -			goto out_free_kmem; -		} -	} -	crypt_stat = &ecryptfs_inode_to_private( -					ecryptfs_dentry->d_inode)->crypt_stat; + +	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(page_virt, -						      ecryptfs_dentry->d_inode); +		ecryptfs_set_default_sizes(crypt_stat); + +	rc = ecryptfs_read_and_validate_header_region(inode); +	ecryptfs_put_lower_file(inode);  	if (rc) { -		memset(page_virt, 0, PAGE_CACHE_SIZE); -		rc = ecryptfs_read_and_validate_xattr_region(page_virt, -							     ecryptfs_dentry); -		if (rc) { -			rc = 0; -			goto out_free_kmem; -		} -		crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; +		rc = ecryptfs_read_and_validate_xattr_region(dentry, inode); +		if (!rc) +			crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;  	} -	mount_crypt_stat = &ecryptfs_superblock_to_private( -		ecryptfs_dentry->d_sb)->mount_crypt_stat; -	if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { -		if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) -			file_size = (crypt_stat->metadata_size -				     + i_size_read(lower_dentry->d_inode)); -		else -			file_size = i_size_read(lower_dentry->d_inode); -	} else { -		file_size = get_unaligned_be64(page_virt); -	} -	i_size_write(ecryptfs_dentry->d_inode, (loff_t)file_size); -out_free_kmem: -	kmem_cache_free(ecryptfs_header_cache_2, page_virt); -	goto out; -out_put: -	dput(lower_dentry); -	mntput(lower_mnt); -	d_drop(ecryptfs_dentry); -out: -	return rc; -} - -/** - * ecryptfs_new_lower_dentry - * @name: The name of the new dentry. - * @lower_dir_dentry: Parent directory of the new dentry. - * @nd: nameidata from last lookup. - * - * Create a new dentry or get it from lower parent dir. - */ -static struct dentry * -ecryptfs_new_lower_dentry(struct qstr *name, struct dentry *lower_dir_dentry, -			  struct nameidata *nd) -{ -	struct dentry *new_dentry; -	struct dentry *tmp; -	struct inode *lower_dir_inode; - -	lower_dir_inode = lower_dir_dentry->d_inode; - -	tmp = d_alloc(lower_dir_dentry, name); -	if (!tmp) -		return ERR_PTR(-ENOMEM); - -	mutex_lock(&lower_dir_inode->i_mutex); -	new_dentry = lower_dir_inode->i_op->lookup(lower_dir_inode, tmp, nd); -	mutex_unlock(&lower_dir_inode->i_mutex); -	if (!new_dentry) -		new_dentry = tmp; -	else -		dput(tmp); - -	return new_dentry; +	/* Must return 0 to allow non-eCryptfs files to be looked up, too */ +	return 0;  } -  /** - * ecryptfs_lookup_one_lower - * @ecryptfs_dentry: The eCryptfs dentry that we are looking up - * @lower_dir_dentry: lower parent directory - * @name: lower file name - * - * Get the lower dentry from vfs. If lower dentry does not exist yet, - * create it. + * ecryptfs_lookup_interpose - Dentry interposition for a lookup   */ -static struct dentry * -ecryptfs_lookup_one_lower(struct dentry *ecryptfs_dentry, -			  struct dentry *lower_dir_dentry, struct qstr *name) +static int ecryptfs_lookup_interpose(struct dentry *dentry, +				     struct dentry *lower_dentry, +				     struct inode *dir_inode)  { -	struct nameidata nd; +	struct inode *inode, *lower_inode = lower_dentry->d_inode; +	struct ecryptfs_dentry_info *dentry_info;  	struct vfsmount *lower_mnt; -	int err; +	int rc = 0; -	lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt( -				    ecryptfs_dentry->d_parent)); -	err = vfs_path_lookup(lower_dir_dentry, lower_mnt, name->name , 0, &nd); -	mntput(lower_mnt); +	dentry_info = kmem_cache_alloc(ecryptfs_dentry_info_cache, GFP_KERNEL); +	if (!dentry_info) { +		printk(KERN_ERR "%s: Out of memory whilst attempting " +		       "to allocate ecryptfs_dentry_info struct\n", +			__func__); +		dput(lower_dentry); +		return -ENOMEM; +	} + +	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(!d_count(lower_dentry)); -	if (!err) { -		/* we dont need the mount */ -		mntput(nd.path.mnt); -		return nd.path.dentry; +	ecryptfs_set_dentry_private(dentry, dentry_info); +	dentry_info->lower_path.mnt = lower_mnt; +	dentry_info->lower_path.dentry = lower_dentry; + +	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 (err != -ENOENT) -		return ERR_PTR(err); -	/* create a new lower dentry */ -	return ecryptfs_new_lower_dentry(name, lower_dir_dentry, &nd); +	if (inode->i_state & I_NEW) +		unlock_new_inode(inode); +	d_add(dentry, inode); + +	return rc;  }  /** @@ -432,48 +401,34 @@ ecryptfs_lookup_one_lower(struct dentry *ecryptfs_dentry,   */  static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,  				      struct dentry *ecryptfs_dentry, -				      struct nameidata *ecryptfs_nd) +				      unsigned int flags)  {  	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; -	struct qstr lower_name;  	int rc = 0; -	ecryptfs_dentry->d_op = &ecryptfs_dops; -	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); -	lower_name.name = ecryptfs_dentry->d_name.name; -	lower_name.len = ecryptfs_dentry->d_name.len; -	lower_name.hash = ecryptfs_dentry->d_name.hash; -	if (lower_dir_dentry->d_op && lower_dir_dentry->d_op->d_hash) { -		rc = lower_dir_dentry->d_op->d_hash(lower_dir_dentry, -						    &lower_name); -		if (rc < 0) -			goto out_d_drop; -	} -	lower_dentry = ecryptfs_lookup_one_lower(ecryptfs_dentry, -						 lower_dir_dentry, &lower_name); +	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_lower() returned " +		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; +				ecryptfs_dentry->d_name.name); +		goto out;  	}  	if (lower_dentry->d_inode) -		goto lookup_and_interpose; +		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 lookup_and_interpose; +		goto interpose;  	dput(lower_dentry);  	rc = ecryptfs_encrypt_and_encode_filename(  		&encrypted_and_encoded_name, &encrypted_and_encoded_name_size, @@ -482,33 +437,23 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,  	if (rc) {  		printk(KERN_ERR "%s: Error attempting to encrypt and encode "  		       "filename; rc = [%d]\n", __func__, rc); -		goto out_d_drop; -	} -	lower_name.name = encrypted_and_encoded_name; -	lower_name.len = encrypted_and_encoded_name_size; -	lower_name.hash = full_name_hash(lower_name.name, lower_name.len); -	if (lower_dir_dentry->d_op && lower_dir_dentry->d_op->d_hash) { -		rc = lower_dir_dentry->d_op->d_hash(lower_dir_dentry, -						    &lower_name); -		if (rc < 0) -			goto out_d_drop; +		goto out;  	} -	lower_dentry = ecryptfs_lookup_one_lower(ecryptfs_dentry, -						 lower_dir_dentry, &lower_name); +	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_lower() returned " +		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; +		goto out;  	} -lookup_and_interpose: -	rc = ecryptfs_lookup_and_interpose_lower(ecryptfs_dentry, lower_dentry, -						 ecryptfs_dir_inode, -						 ecryptfs_nd); -	goto out; -out_d_drop: -	d_drop(ecryptfs_dentry); +interpose: +	rc = ecryptfs_lookup_interpose(ecryptfs_dentry, lower_dentry, +				       ecryptfs_dir_inode);  out:  	kfree(encrypted_and_encoded_name);  	return ERR_PTR(rc); @@ -530,16 +475,16 @@ static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir,  	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); +		      lower_new_dentry, NULL);  	if (rc || !lower_new_dentry->d_inode)  		goto out_lock; -	rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb, 0); +	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); -	old_dentry->d_inode->i_nlink = -		ecryptfs_inode_to_lower(old_dentry->d_inode)->i_nlink; +	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); @@ -550,27 +495,7 @@ out_lock:  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); -	dentry->d_inode->i_nlink = -		ecryptfs_inode_to_lower(dentry->d_inode)->i_nlink; -	dentry->d_inode->i_ctime = dir->i_ctime; -	d_drop(dentry); -out_unlock: -	unlock_dir(lower_dir_dentry); -	dput(lower_dentry); -	return rc; +	return ecryptfs_do_unlink(dir, dentry, dentry->d_inode);  }  static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry, @@ -600,7 +525,7 @@ static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry,  	kfree(encoded_symname);  	if (rc || !lower_dentry->d_inode)  		goto out_lock; -	rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0); +	rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb);  	if (rc)  		goto out_lock;  	fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); @@ -613,7 +538,7 @@ out_lock:  	return rc;  } -static int ecryptfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) +static int ecryptfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)  {  	int rc;  	struct dentry *lower_dentry; @@ -624,12 +549,12 @@ static int ecryptfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)  	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, 0); +	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); -	dir->i_nlink = lower_dir_dentry->d_inode->i_nlink; +	set_nlink(dir, lower_dir_dentry->d_inode->i_nlink);  out:  	unlock_dir(lower_dir_dentry);  	if (!dentry->d_inode) @@ -649,10 +574,10 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)  	dget(lower_dentry);  	rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);  	dput(lower_dentry); -	if (!rc) -		d_delete(lower_dentry); +	if (!rc && dentry->d_inode) +		clear_nlink(dentry->d_inode);  	fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); -	dir->i_nlink = lower_dir_dentry->d_inode->i_nlink; +	set_nlink(dir, lower_dir_dentry->d_inode->i_nlink);  	unlock_dir(lower_dir_dentry);  	if (!rc)  		d_drop(dentry); @@ -661,7 +586,7 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)  }  static int -ecryptfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) +ecryptfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)  {  	int rc;  	struct dentry *lower_dentry; @@ -672,7 +597,7 @@ ecryptfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)  	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, 0); +	rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb);  	if (rc)  		goto out;  	fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); @@ -694,6 +619,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,  	struct dentry *lower_old_dir_dentry;  	struct dentry *lower_new_dir_dentry;  	struct dentry *trap = NULL; +	struct inode *target_inode;  	lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);  	lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry); @@ -701,6 +627,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,  	dget(lower_new_dentry);  	lower_old_dir_dentry = dget_parent(lower_old_dentry);  	lower_new_dir_dentry = dget_parent(lower_new_dentry); +	target_inode = new_dentry->d_inode;  	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);  	/* source should not be ancestor of target */  	if (trap == lower_old_dentry) { @@ -713,106 +640,65 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,  		goto out_lock;  	}  	rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry, -			lower_new_dir_dentry->d_inode, lower_new_dentry); +			lower_new_dir_dentry->d_inode, lower_new_dentry, +			NULL, 0);  	if (rc)  		goto out_lock; +	if (target_inode) +		fsstack_copy_attr_all(target_inode, +				      ecryptfs_inode_to_lower(target_inode));  	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_dentry->d_parent); -	dput(lower_old_dentry->d_parent); +	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) +static char *ecryptfs_readlink_lower(struct dentry *dentry, size_t *bufsiz)  {  	struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);  	char *lower_buf; -	size_t lower_bufsiz = PATH_MAX; +	char *buf;  	mm_segment_t old_fs;  	int rc; -	lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL); -	if (!lower_buf) { -		rc = -ENOMEM; -		goto out; -	} +	lower_buf = kmalloc(PATH_MAX, GFP_KERNEL); +	if (!lower_buf) +		return ERR_PTR(-ENOMEM);  	old_fs = get_fs();  	set_fs(get_ds());  	rc = lower_dentry->d_inode->i_op->readlink(lower_dentry,  						   (char __user *)lower_buf, -						   lower_bufsiz); +						   PATH_MAX);  	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); +	rc = ecryptfs_decode_and_decrypt_filename(&buf, bufsiz, dentry->d_sb, +						  lower_buf, rc);  out:  	kfree(lower_buf); -	return rc; +	return rc ? ERR_PTR(rc) : buf;  } -static int -ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) +static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd)  { -	char *kbuf; -	size_t kbufsiz, copied; -	int rc; - -	rc = ecryptfs_readlink_lower(dentry, &kbuf, &kbufsiz); -	if (rc) +	size_t len; +	char *buf = ecryptfs_readlink_lower(dentry, &len); +	if (IS_ERR(buf))  		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'; +	buf[len] = '\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 @@ -870,8 +756,11 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,  	if (unlikely((ia->ia_size == i_size))) {  		lower_ia->ia_valid &= ~ATTR_SIZE; -		goto out; +		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) { @@ -892,18 +781,6 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,  		size_t num_zeros = (PAGE_CACHE_SIZE  				    - (ia->ia_size & ~PAGE_CACHE_MASK)); - -		/* -		 * XXX(truncate) this should really happen at the begginning -		 * of ->setattr.  But the code is too messy to that as part -		 * of a larger patch.  ecryptfs is also totally missing out -		 * on the inode_change_ok check at the beginning of -		 * ->setattr while would include this. -		 */ -		rc = inode_newsize_ok(inode, ia->ia_size); -		if (rc) -			goto out; -  		if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {  			truncate_setsize(inode, ia->ia_size);  			lower_ia->ia_size = ia->ia_size; @@ -949,9 +826,32 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,  			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 @@ -968,12 +868,16 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t 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); +		rc = notify_change(lower_dentry, &lower_ia, NULL);  		mutex_unlock(&lower_dentry->d_inode->i_mutex);  	}  	return rc; @@ -1022,7 +926,13 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)  		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)) { @@ -1036,10 +946,21 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)  				goto out;  			}  			rc = 0; -			crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); +			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; +	} +  	memcpy(&lower_ia, ia, sizeof(lower_ia));  	if (ia->ia_valid & ATTR_FILE)  		lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file); @@ -1057,15 +978,15 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)  		lower_ia.ia_valid &= ~ATTR_MODE;  	mutex_lock(&lower_dentry->d_inode->i_mutex); -	rc = notify_change(lower_dentry, &lower_ia); +	rc = notify_change(lower_dentry, &lower_ia, NULL);  	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) +static int ecryptfs_getattr_link(struct vfsmount *mnt, struct dentry *dentry, +				 struct kstat *stat)  {  	struct ecryptfs_mount_crypt_stat *mount_crypt_stat;  	int rc = 0; @@ -1077,24 +998,27 @@ int ecryptfs_getattr_link(struct vfsmount *mnt, struct dentry *dentry,  		char *target;  		size_t targetsiz; -		rc = ecryptfs_readlink_lower(dentry, &target, &targetsiz); -		if (!rc) { +		target = ecryptfs_readlink_lower(dentry, &targetsiz); +		if (!IS_ERR(target)) {  			kfree(target);  			stat->size = targetsiz; +		} else { +			rc = PTR_ERR(target);  		}  	}  	return rc;  } -int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry, -		     struct kstat *stat) +static 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); +	rc = vfs_getattr(ecryptfs_dentry_to_lower_path(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;  	} @@ -1115,6 +1039,8 @@ ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,  	}  	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;  } @@ -1180,25 +1106,10 @@ out:  	return rc;  } -int ecryptfs_inode_test(struct inode *inode, void *candidate_lower_inode) -{ -	if ((ecryptfs_inode_to_lower(inode) -	     == (struct inode *)candidate_lower_inode)) -		return 1; -	else -		return 0; -} - -int ecryptfs_inode_set(struct inode *inode, void *lower_inode) -{ -	ecryptfs_init_inode(inode, (struct inode *)lower_inode); -	return 0; -} -  const struct inode_operations ecryptfs_symlink_iops = { -	.readlink = ecryptfs_readlink, +	.readlink = generic_readlink,  	.follow_link = ecryptfs_follow_link, -	.put_link = ecryptfs_put_link, +	.put_link = kfree_put_link,  	.permission = ecryptfs_permission,  	.setattr = ecryptfs_setattr,  	.getattr = ecryptfs_getattr_link, diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index b1f6858a522..4725a07f003 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -59,12 +59,30 @@ static int process_request_key_err(long err_code)  		break;  	default:  		ecryptfs_printk(KERN_WARNING, "Unknown error code: " -				"[0x%.16x]\n", err_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 @@ -91,7 +109,7 @@ int ecryptfs_parse_packet_length(unsigned char *data, size_t *size,  		(*size) += ((unsigned char)(data[1]) + 192);  		(*length_size) = 2;  	} else if (data[0] == 255) { -		/* Five-byte length; we're not supposed to see this */ +		/* If support is added, adjust ECRYPTFS_MAX_PKT_LEN_SIZE */  		ecryptfs_printk(KERN_ERR, "Five-byte packet length not "  				"supported\n");  		rc = -EINVAL; @@ -108,7 +126,7 @@ out:  /**   * ecryptfs_write_packet_length   * @dest: The byte array target into which to write the length. Must - *        have at least 5 bytes allocated. + *        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. @@ -128,9 +146,10 @@ int ecryptfs_write_packet_length(char *dest, size_t size,  		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: [%d]\n", size); +				"Unsupported packet size: [%zd]\n", size);  	}  	return rc;  } @@ -403,27 +422,120 @@ 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 ecryptfs_global_auth_tok **global_auth_tok, +	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; -	(*global_auth_tok) = NULL; +	(*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) == 0) { -			rc = key_validate(walker->global_auth_tok_key); -			if (!rc) -				(*global_auth_tok) = walker; +		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 = -EINVAL; +	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; @@ -451,14 +563,11 @@ ecryptfs_find_auth_tok_for_sig(  	struct ecryptfs_mount_crypt_stat *mount_crypt_stat,  	char *sig)  { -	struct ecryptfs_global_auth_tok *global_auth_tok;  	int rc = 0; -	(*auth_tok_key) = NULL; -	(*auth_tok) = NULL; -	if (ecryptfs_find_global_auth_tok_for_sig(&global_auth_tok, -						  mount_crypt_stat, sig)) { - +	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 @@ -470,8 +579,7 @@ ecryptfs_find_auth_tok_for_sig(  		rc = ecryptfs_keyring_auth_tok_for_sig(auth_tok_key, auth_tok,  						       sig); -	} else -		(*auth_tok) = global_auth_tok->global_auth_tok; +	}  	return rc;  } @@ -492,8 +600,8 @@ struct ecryptfs_write_tag_70_packet_silly_stack {  	struct mutex *tfm_mutex;  	char *block_aligned_filename;  	struct ecryptfs_auth_tok *auth_tok; -	struct scatterlist src_sg; -	struct scatterlist dst_sg; +	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]; @@ -531,6 +639,16 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,  	}  	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); @@ -561,10 +679,7 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,  	 * 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 = (1                   /* Tag 70 identifier */ -			      + 3                 /* Max Tag 70 packet size */ -			      + ECRYPTFS_SIG_SIZE /* FNEK sig */ -			      + 1                 /* Cipher identifier */ +	s->max_packet_size = (ECRYPTFS_TAG_70_MAX_METADATA_SIZE  			      + s->block_aligned_filename_size);  	if (dest == NULL) {  		(*packet_size) = s->max_packet_size; @@ -616,16 +731,6 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,  		goto out_free_unlock;  	}  	dest[s->i++] = s->cipher_code; -	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_free_unlock; -	}  	/* TODO: Support other key modules than passphrase for  	 * filename encryption */  	if (s->auth_tok->token_type != ECRYPTFS_PASSWORD) { @@ -709,23 +814,21 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,  	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, 1); -	if (rc != 1) { +				 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; " -		       "expected rc = 1; got rc = [%d]. " +		       "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, 1); -	if (rc != 1) { +				 s->dst_sg, 2); +	if (rc < 1) {  		printk(KERN_ERR "%s: Internal error whilst attempting to "  		       "convert encrypted filename memory to scatterlist; " -		       "expected rc = 1; got rc = [%d]. " -		       "block_aligned_filename_size = [%zd]\n", __func__, rc, -		       s->block_aligned_filename_size); +		       "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 @@ -748,7 +851,7 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,  		       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, +	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; " @@ -765,8 +868,10 @@ out_free_unlock:  out_unlock:  	mutex_unlock(s->tfm_mutex);  out: -	if (auth_tok_key) +	if (auth_tok_key) { +		up_write(&(auth_tok_key->sem));  		key_put(auth_tok_key); +	}  	kfree(s);  	return rc;  } @@ -782,8 +887,8 @@ struct ecryptfs_parse_tag_70_packet_silly_stack {  	struct mutex *tfm_mutex;  	char *decrypted_filename;  	struct ecryptfs_auth_tok *auth_tok; -	struct scatterlist src_sg; -	struct scatterlist dst_sg; +	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]; @@ -826,10 +931,10 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,  		goto out;  	}  	s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; -	if (max_packet_size < (1 + 1 + ECRYPTFS_SIG_SIZE + 1 + 1)) { +	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, -			(1 + 1 + ECRYPTFS_SIG_SIZE + 1 + 1)); +		       ECRYPTFS_TAG_70_MIN_METADATA_SIZE);  		rc = -EINVAL;  		goto out;  	} @@ -879,6 +984,15 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,  		       __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); @@ -890,13 +1004,12 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,  	}  	mutex_lock(s->tfm_mutex);  	rc = virt_to_scatterlist(&data[(*packet_size)], -				 s->block_aligned_filename_size, &s->src_sg, 1); -	if (rc != 1) { +				 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; " -		       "expected rc = 1; got rc = [%d]. " -		       "block_aligned_filename_size = [%zd]\n", __func__, rc, -		       s->block_aligned_filename_size); +		       "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; @@ -910,13 +1023,12 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,  		goto out_unlock;  	}  	rc = virt_to_scatterlist(s->decrypted_filename, -				 s->block_aligned_filename_size, &s->dst_sg, 1); -	if (rc != 1) { +				 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; " -		       "expected rc = 1; got rc = [%d]. " -		       "block_aligned_filename_size = [%zd]\n", __func__, rc, -		       s->block_aligned_filename_size); +		       "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 @@ -925,15 +1037,6 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,  	 * >= ECRYPTFS_MAX_IV_BYTES. */  	memset(s->iv, 0, ECRYPTFS_MAX_IV_BYTES);  	s->desc.info = s->iv; -	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_free_unlock; -	}  	/* TODO: Support other key modules than passphrase for  	 * filename encryption */  	if (s->auth_tok->token_type != ECRYPTFS_PASSWORD) { @@ -956,7 +1059,7 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,  		       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, +	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; " @@ -1002,8 +1105,10 @@ out:  		(*filename_size) = 0;  		(*filename) = NULL;  	} -	if (auth_tok_key) +	if (auth_tok_key) { +		up_write(&(auth_tok_key->sem));  		key_put(auth_tok_key); +	}  	kfree(s);  	return rc;  } @@ -1044,8 +1149,8 @@ decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,  	struct ecryptfs_msg_ctx *msg_ctx;  	struct ecryptfs_message *msg = NULL;  	char *auth_tok_sig; -	char *payload; -	size_t payload_len; +	char *payload = NULL; +	size_t payload_len = 0;  	int rc;  	rc = ecryptfs_get_auth_tok_sig(&auth_tok_sig, auth_tok); @@ -1063,7 +1168,7 @@ decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,  	rc = ecryptfs_send_message(payload, payload_len, &msg_ctx);  	if (rc) {  		ecryptfs_printk(KERN_ERR, "Error sending message to " -				"ecryptfsd\n"); +				"ecryptfsd: %d\n", rc);  		goto out;  	}  	rc = ecryptfs_wait_for_response(msg_ctx, &msg); @@ -1097,8 +1202,8 @@ decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,  				  crypt_stat->key_size);  	}  out: -	if (msg) -		kfree(msg); +	kfree(msg); +	kfree(payload);  	return rc;  } @@ -1520,38 +1625,6 @@ 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; -} -  int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,  				      struct ecryptfs_auth_tok **auth_tok,  				      char *sig) @@ -1560,34 +1633,22 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,  	(*auth_tok_key) = request_key(&key_type_user, sig, NULL);  	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)); -		goto out; -	} -	(*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_release_key; -	} -	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_release_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; +		}  	} -out_release_key: +	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; @@ -1672,7 +1733,7 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,  	       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 [%d]:\n", +		ecryptfs_printk(KERN_DEBUG, "FEK of size [%zd]:\n",  				crypt_stat->key_size);  		ecryptfs_dump_hex(crypt_stat->key,  				  crypt_stat->key_size); @@ -1754,7 +1815,7 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,  			if (ECRYPTFS_SIG_SIZE != tag_11_contents_size) {  				ecryptfs_printk(KERN_ERR, "Expected "  						"signature of size [%d]; " -						"read size [%d]\n", +						"read size [%zd]\n",  						ECRYPTFS_SIG_SIZE,  						tag_11_contents_size);  				rc = -EIO; @@ -1787,8 +1848,8 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,  			goto out_wipe_list;  			break;  		default: -			ecryptfs_printk(KERN_DEBUG, "No packet at offset " -					"[%d] of the file header; hex value of " +			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;  		} @@ -1808,10 +1869,6 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,  	 * just one will be sufficient to decrypt to get the FEK. */  find_next_matching_auth_tok:  	found_auth_tok = 0; -	if (auth_tok_key) { -		key_put(auth_tok_key); -		auth_tok_key = NULL; -	}  	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)) { @@ -1848,14 +1905,22 @@ found_matching_auth_tok:  		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; @@ -1864,8 +1929,8 @@ found_matching_auth_tok:  				"session key for authentication token with sig "  				"[%.*s]; rc = [%d]. Removing auth tok "  				"candidate from the list and searching for " -				"the next match.\n", candidate_auth_tok_sig, -				ECRYPTFS_SIG_SIZE_HEX, rc); +				"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) { @@ -1895,19 +1960,18 @@ found_matching_auth_tok:  out_wipe_list:  	wipe_auth_tok_list(&auth_tok_list);  out: -	if (auth_tok_key) -		key_put(auth_tok_key);  	return rc;  }  static int -pki_encrypt_session_key(struct ecryptfs_auth_tok *auth_tok, +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; +	size_t payload_len = 0;  	struct ecryptfs_message *msg;  	int rc; @@ -1916,6 +1980,8 @@ pki_encrypt_session_key(struct ecryptfs_auth_tok *auth_tok,  					 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; @@ -1923,7 +1989,7 @@ pki_encrypt_session_key(struct ecryptfs_auth_tok *auth_tok,  	rc = ecryptfs_send_message(payload, payload_len, &msg_ctx);  	if (rc) {  		ecryptfs_printk(KERN_ERR, "Error sending message to " -				"ecryptfsd\n"); +				"ecryptfsd: %d\n", rc);  		goto out;  	}  	rc = ecryptfs_wait_for_response(msg_ctx, &msg); @@ -1945,6 +2011,8 @@ out:   * 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 @@ -1955,7 +2023,7 @@ out:   */  static int  write_tag_1_packet(char *dest, size_t *remaining_bytes, -		   struct ecryptfs_auth_tok *auth_tok, +		   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)  { @@ -1976,12 +2044,15 @@ write_tag_1_packet(char *dest, size_t *remaining_bytes,  		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, crypt_stat, key_rec); +	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); @@ -2168,7 +2239,7 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,  	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 = [%d]\n", +				"where key_rec->enc_key_size = [%zd]\n",  				key_rec->enc_key_size);  		memcpy(key_rec->enc_key,  		       auth_tok->session_key.encrypted_key, @@ -2185,7 +2256,7 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,  		       auth_tok->token.password.session_key_encryption_key,  		       crypt_stat->key_size);  		ecryptfs_printk(KERN_DEBUG, -				"Cached session key " "encryption key: \n"); +				"Cached session key encryption key:\n");  		if (ecryptfs_verbosity > 0)  			ecryptfs_dump_hex(session_key_encryption_key, 16);  	} @@ -2198,7 +2269,7 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,  	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 = [%d]\n", +				"got rc = [%d]. key_rec->enc_key_size = [%zd]\n",  				rc, key_rec->enc_key_size);  		rc = -ENOMEM;  		goto out; @@ -2209,7 +2280,7 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,  		ecryptfs_printk(KERN_ERR, "Error generating scatterlist "  				"for crypt_stat encrypted session key; "  				"expected rc = 1; got rc = [%d]. " -				"key_rec->enc_key_size = [%d]\n", rc, +				"key_rec->enc_key_size = [%zd]\n", rc,  				key_rec->enc_key_size);  		rc = -ENOMEM;  		goto out; @@ -2224,7 +2295,7 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,  		goto out;  	}  	rc = 0; -	ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes of the key\n", +	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); @@ -2235,7 +2306,7 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,  	}  	ecryptfs_printk(KERN_DEBUG, "This should be the encrypted key:\n");  	if (ecryptfs_verbosity > 0) { -		ecryptfs_printk(KERN_DEBUG, "EFEK of size [%d]:\n", +		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); @@ -2324,7 +2395,7 @@ ecryptfs_generate_key_packet_set(char *dest_base,  				 size_t max)  {  	struct ecryptfs_auth_tok *auth_tok; -	struct ecryptfs_global_auth_tok *global_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; @@ -2343,26 +2414,23 @@ ecryptfs_generate_key_packet_set(char *dest_base,  	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(&global_auth_tok, +		rc = ecryptfs_find_global_auth_tok_for_sig(&auth_tok_key, +							   &auth_tok,  							   mount_crypt_stat,  							   key_sig->keysig);  		if (rc) { -			printk(KERN_ERR "Error attempting to get the global " -			       "auth_tok; rc = [%d]\n", 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 (global_auth_tok->flags & ECRYPTFS_AUTH_TOK_INVALID) { -			printk(KERN_WARNING -			       "Skipping invalid auth tok with sig = [%s]\n", -			       global_auth_tok->sig); -			continue; -		} -		auth_tok = global_auth_tok->global_auth_tok;  		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"); @@ -2380,8 +2448,8 @@ ecryptfs_generate_key_packet_set(char *dest_base,  			}  			(*len) += written;  		} else if (auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) { -			rc = write_tag_1_packet(dest_base + (*len), -						&max, auth_tok, +			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 " @@ -2390,6 +2458,8 @@ ecryptfs_generate_key_packet_set(char *dest_base,  			}  			(*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; @@ -2424,6 +2494,7 @@ int ecryptfs_add_keysig(struct ecryptfs_crypt_stat *crypt_stat, char *sig)  		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); @@ -2453,7 +2524,6 @@ ecryptfs_add_global_auth_tok(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,  	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); -	mount_crypt_stat->num_global_auth_toks++;  	mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);  out:  	return rc; diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c index 0851ab6980f..f1ea610362c 100644 --- a/fs/ecryptfs/kthread.c +++ b/fs/ecryptfs/kthread.c @@ -27,7 +27,12 @@  #include <linux/mount.h>  #include "ecryptfs_kernel.h" -struct kmem_cache *ecryptfs_open_req_cache; +struct ecryptfs_open_req { +	struct file **lower_file; +	struct path path; +	struct completion done; +	struct list_head kthread_ctl_list; +};  static struct ecryptfs_kthread_ctl {  #define ECRYPTFS_KTHREAD_ZOMBIE 0x00000001 @@ -44,7 +49,7 @@ static struct task_struct *ecryptfs_kthread;   * @ignored: ignored   *   * The eCryptfs kernel thread that has the responsibility of getting - * the lower persistent file with RW permissions. + * the lower file with RW permissions.   *   * Returns zero on success; non-zero otherwise   */ @@ -67,18 +72,10 @@ static int ecryptfs_threadfn(void *ignored)  			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); +			*req->lower_file = dentry_open(&req->path, +				(O_RDWR | O_LARGEFILE), current_cred()); +			complete(&req->done);  		}  		mutex_unlock(&ecryptfs_kthread_ctl.mux);  	} @@ -105,16 +102,15 @@ int __init ecryptfs_init_kthread(void)  void ecryptfs_destroy_kthread(void)  { -	struct ecryptfs_open_req *req; +	struct ecryptfs_open_req *req, *tmp;  	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); +	list_for_each_entry_safe(req, tmp, &ecryptfs_kthread_ctl.req_list, +				 kthread_ctl_list) { +		list_del(&req->kthread_ctl_list); +		*req->lower_file = ERR_PTR(-EIO); +		complete(&req->done);  	}  	mutex_unlock(&ecryptfs_kthread_ctl.mux);  	kthread_stop(ecryptfs_kthread); @@ -136,34 +132,26 @@ int ecryptfs_privileged_open(struct file **lower_file,  			     struct vfsmount *lower_mnt,  			     const struct cred *cred)  { -	struct ecryptfs_open_req *req; +	struct ecryptfs_open_req req;  	int flags = O_LARGEFILE;  	int rc = 0; +	init_completion(&req.done); +	req.lower_file = lower_file; +	req.path.dentry = lower_dentry; +	req.path.mnt = lower_mnt; +  	/* Corresponding dput() and mntput() are done when the -	 * persistent file is fput() when the eCryptfs inode is -	 * destroyed. */ -	dget(lower_dentry); -	mntget(lower_mnt); +	 * lower file is fput() when all eCryptfs files for the inode are +	 * released. */  	flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR; -	(*lower_file) = dentry_open(lower_dentry, lower_mnt, flags, cred); +	(*lower_file) = dentry_open(&req.path, flags, cred);  	if (!IS_ERR(*lower_file))  		goto out; -	if (flags & O_RDONLY) { +	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; @@ -171,27 +159,14 @@ int ecryptfs_privileged_open(struct file **lower_file,  		printk(KERN_ERR "%s: We are in the middle of shutting down; "  		       "aborting privileged request to open lower file\n",  			__func__); -		goto out_free; +		goto out;  	} -	list_add_tail(&req->kthread_ctl_list, &ecryptfs_kthread_ctl.req_list); +	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); +	wait_for_completion(&req.done); +	if (IS_ERR(*lower_file)) +		rc = PTR_ERR(*lower_file);  out:  	return rc;  } diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index a9dbd62518e..1b119d3bf92 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -36,6 +36,7 @@  #include <linux/parser.h>  #include <linux/fs_stack.h>  #include <linux/slab.h> +#include <linux/magic.h>  #include "ecryptfs_kernel.h"  /** @@ -95,7 +96,7 @@ void __ecryptfs_printk(const char *fmt, ...)  }  /** - * ecryptfs_init_persistent_file + * ecryptfs_init_lower_file   * @ecryptfs_dentry: Fully initialized eCryptfs dentry object, with   *                   the lower dentry and the lower mount set   * @@ -103,103 +104,68 @@ void __ecryptfs_printk(const char *fmt, ...)   * 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 - * persistent file struct and associates it with the eCryptfs - * inode. When the eCryptfs inode is destroyed, the file is closed. + * 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 persistent file will be opened with read/write permissions, if + * 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 persistent file is already + * This function does nothing if a lower file is already   * associated with the eCryptfs inode.   *   * Returns zero on success; non-zero otherwise   */ -int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry) +static int ecryptfs_init_lower_file(struct dentry *dentry, +				    struct file **lower_file)  {  	const struct cred *cred = current_cred(); -	struct ecryptfs_inode_info *inode_info = -		ecryptfs_inode_to_private(ecryptfs_dentry->d_inode); -	int rc = 0; +	struct path *path = ecryptfs_dentry_to_lower_path(dentry); +	int rc; + +	rc = ecryptfs_privileged_open(lower_file, path->dentry, path->mnt, +				      cred); +	if (rc) { +		printk(KERN_ERR "Error opening lower file " +		       "for lower_dentry [0x%p] and lower_mnt [0x%p]; " +		       "rc = [%d]\n", path->dentry, path->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); -	if (!inode_info->lower_file) { -		struct dentry *lower_dentry; -		struct vfsmount *lower_mnt = -			ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry); - -		lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); -		rc = ecryptfs_privileged_open(&inode_info->lower_file, -					      lower_dentry, lower_mnt, cred); -		if (rc) { -			printk(KERN_ERR "Error opening lower persistent file " -			       "for lower_dentry [0x%p] and lower_mnt [0x%p]; " -			       "rc = [%d]\n", lower_dentry, lower_mnt, rc); -			inode_info->lower_file = NULL; -		} +	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;  } -/** - * ecryptfs_interpose - * @lower_dentry: Existing dentry in the lower filesystem - * @dentry: ecryptfs' dentry - * @sb: ecryptfs's super_block - * @flags: flags to govern behavior of interpose procedure - * - * Interposes upper and lower dentries. - * - * Returns zero on success; non-zero otherwise - */ -int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry, -		       struct super_block *sb, u32 flags) +void ecryptfs_put_lower_file(struct inode *inode)  { -	struct inode *lower_inode; -	struct inode *inode; -	int rc = 0; +	struct ecryptfs_inode_info *inode_info; -	lower_inode = lower_dentry->d_inode; -	if (lower_inode->i_sb != ecryptfs_superblock_to_lower(sb)) { -		rc = -EXDEV; -		goto out; -	} -	if (!igrab(lower_inode)) { -		rc = -ESTALE; -		goto out; -	} -	inode = iget5_locked(sb, (unsigned long)lower_inode, -			     ecryptfs_inode_test, ecryptfs_inode_set, -			     lower_inode); -	if (!inode) { -		rc = -EACCES; -		iput(lower_inode); -		goto out; +	inode_info = ecryptfs_inode_to_private(inode); +	if (atomic_dec_and_mutex_lock(&inode_info->lower_file_count, +				      &inode_info->lower_file_mutex)) { +		filemap_write_and_wait(inode->i_mapping); +		fput(inode_info->lower_file); +		inode_info->lower_file = NULL; +		mutex_unlock(&inode_info->lower_file_mutex);  	} -	if (inode->i_state & I_NEW) -		unlock_new_inode(inode); -	else -		iput(lower_inode); -	if (S_ISLNK(lower_inode->i_mode)) -		inode->i_op = &ecryptfs_symlink_iops; -	else if (S_ISDIR(lower_inode->i_mode)) -		inode->i_op = &ecryptfs_dir_iops; -	if (S_ISDIR(lower_inode->i_mode)) -		inode->i_fop = &ecryptfs_dir_fops; -	if (special_file(lower_inode->i_mode)) -		init_special_inode(inode, lower_inode->i_mode, -				   lower_inode->i_rdev); -	dentry->d_op = &ecryptfs_dops; -	fsstack_copy_attr_all(inode, lower_inode); -	/* This size will be overwritten for real files w/ headers and -	 * other metadata */ -	fsstack_copy_inode_size(inode, lower_inode); -	if (flags & ECRYPTFS_INTERPOSE_FLAG_D_ADD) -		d_add(dentry, inode); -	else -		d_instantiate(dentry, inode); -out: -	return rc;  }  enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig, @@ -209,6 +175,7 @@ enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig,         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 = { @@ -225,6 +192,7 @@ static const match_table_t tokens = {  	{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}  }; @@ -232,14 +200,14 @@ 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, -			&global_auth_tok->global_auth_tok, +			&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 " @@ -247,8 +215,10 @@ static int ecryptfs_init_global_auth_toks(  			       "option: [%s]\n", global_auth_tok->sig);  			global_auth_tok->flags |= ECRYPTFS_AUTH_TOK_INVALID;  			goto out; -		} else +		} else {  			global_auth_tok->flags &= ~ECRYPTFS_AUTH_TOK_INVALID; +			up_write(&(global_auth_tok->global_auth_tok_key)->sem); +		}  	}  out:  	return rc; @@ -267,7 +237,8 @@ static void ecryptfs_init_mount_crypt_stat(  /**   * ecryptfs_parse_options   * @sb: The ecryptfs super block - * @options: The options pased to the kernel + * @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 @@ -283,7 +254,8 @@ static void ecryptfs_init_mount_crypt_stat(   *   * Returns zero on success; non-zero on error   */ -static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options) +static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options, +				  uid_t *check_ruid)  {  	char *p;  	int rc = 0; @@ -307,6 +279,9 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options)  	char *fnek_src;  	char *cipher_key_bytes_src;  	char *fn_cipher_key_bytes_src; +	u8 cipher_code; + +	*check_ruid = 0;  	if (!options) {  		rc = -EINVAL; @@ -412,6 +387,9 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options)  			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 @@ -443,6 +421,18 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options)  	    && !fn_cipher_key_bytes_set)  		mount_crypt_stat->global_default_fn_cipher_key_bytes =  			mount_crypt_stat->global_default_cipher_key_size; + +	cipher_code = ecryptfs_code_for_cipher_string( +		mount_crypt_stat->global_default_cipher_name, +		mount_crypt_stat->global_default_cipher_key_size); +	if (!cipher_code) { +		ecryptfs_printk(KERN_ERR, +				"eCryptfs doesn't support cipher: %s", +				mount_crypt_stat->global_default_cipher_name); +		rc = -EINVAL; +		goto out; +	} +  	mutex_lock(&key_tfm_list_mutex);  	if (!ecryptfs_tfm_exists(mount_crypt_stat->global_default_cipher_name,  				 NULL)) { @@ -492,59 +482,11 @@ struct kmem_cache *ecryptfs_sb_info_cache;  static struct file_system_type ecryptfs_fs_type;  /** - * ecryptfs_read_super - * @sb: The ecryptfs super block - * @dev_name: The path to mount over - * - * Read the super block of the lower filesystem, and use - * ecryptfs_interpose to create our initial inode and super block - * struct. - */ -static int ecryptfs_read_super(struct super_block *sb, const char *dev_name) -{ -	struct path path; -	int rc; - -	rc = kern_path(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path); -	if (rc) { -		ecryptfs_printk(KERN_WARNING, "path_lookup() failed\n"); -		goto out; -	} -	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; -	} -	ecryptfs_set_superblock_lower(sb, path.dentry->d_sb); -	sb->s_maxbytes = path.dentry->d_sb->s_maxbytes; -	sb->s_blocksize = path.dentry->d_sb->s_blocksize; -	ecryptfs_set_dentry_lower(sb->s_root, path.dentry); -	ecryptfs_set_dentry_lower_mnt(sb->s_root, path.mnt); -	rc = ecryptfs_interpose(path.dentry, sb->s_root, sb, 0); -	if (rc) -		goto out_free; -	rc = 0; -	goto out; -out_free: -	path_put(&path); -out: -	return rc; -} - -/**   * ecryptfs_get_sb   * @fs_type   * @flags   * @dev_name: The path to mount over   * @raw_data: The options passed into the kernel - * - * The whole ecryptfs_get_sb process is broken into 3 functions: - * ecryptfs_parse_options(): handle options passed to ecryptfs, if any - * ecryptfs_read_super(): this accesses the lower filesystem and uses - *                        ecryptfs_interpose to perform most of the linking - * ecryptfs_interpose(): links the lower filesystem into ecryptfs (inode.c)   */  static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags,  			const char *dev_name, void *raw_data) @@ -553,6 +495,9 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags  	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); @@ -561,24 +506,21 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags  		goto out;  	} -	rc = ecryptfs_parse_options(sbi, raw_data); +	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); +	s = sget(fs_type, NULL, set_anon_super, flags, 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) { -		deactivate_locked_super(s); -		goto out; -	} +	if (rc) +		goto out1;  	ecryptfs_set_superblock_private(s, sbi);  	s->s_bdi = &sbi->bdi; @@ -586,34 +528,72 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags  	/* ->kill_sb() will take care of sbi after that point */  	sbi = NULL;  	s->s_op = &ecryptfs_sops; +	s->s_d_op = &ecryptfs_dops; -	rc = -ENOMEM; -	s->s_root = d_alloc(NULL, &(const struct qstr) { -			     .hash = 0,.name = "/",.len = 1}); +	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 && !uid_eq(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", +			i_uid_read(path.dentry->d_inode), +			from_kuid(&init_user_ns, current_uid())); +		goto out_free; +	} + +	ecryptfs_set_superblock_lower(s, path.dentry->d_sb); + +	/** +	 * Set the POSIX ACL flag based on whether they're enabled in the lower +	 * mount. Force a read-only eCryptfs mount if the lower mount is ro. +	 * Allow a ro eCryptfs mount even when the lower mount is rw. +	 */ +	s->s_flags = flags & ~MS_POSIXACL; +	s->s_flags |= path.dentry->d_sb->s_flags & (MS_RDONLY | MS_POSIXACL); + +	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) { -		deactivate_locked_super(s); -		goto out; +		rc = -ENOMEM; +		goto out_free;  	} -	s->s_root->d_op = &ecryptfs_dops; -	s->s_root->d_sb = s; -	s->s_root->d_parent = s->s_root; +	rc = -ENOMEM;  	root_info = kmem_cache_zalloc(ecryptfs_dentry_info_cache, GFP_KERNEL); -	if (!root_info) { -		deactivate_locked_super(s); -		goto out; -	} +	if (!root_info) +		goto out_free; +  	/* ->kill_sb() will take care of root_info */  	ecryptfs_set_dentry_private(s->s_root, root_info); +	root_info->lower_path = path; +  	s->s_flags |= MS_ACTIVE; -	rc = ecryptfs_read_super(s, dev_name); -	if (rc) { -		deactivate_locked_super(s); -		err = "Reading sb failed"; -		goto out; -	}  	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); @@ -647,6 +627,7 @@ static struct file_system_type ecryptfs_fs_type = {  	.kill_sb = ecryptfs_kill_block_super,  	.fs_flags = 0  }; +MODULE_ALIAS_FS("ecryptfs");  /**   * inode_info_init_once @@ -694,13 +675,8 @@ static struct ecryptfs_cache_info {  		.size = sizeof(struct ecryptfs_sb_info),  	},  	{ -		.cache = &ecryptfs_header_cache_1, -		.name = "ecryptfs_headers_1", -		.size = PAGE_CACHE_SIZE, -	}, -	{ -		.cache = &ecryptfs_header_cache_2, -		.name = "ecryptfs_headers_2", +		.cache = &ecryptfs_header_cache, +		.name = "ecryptfs_headers",  		.size = PAGE_CACHE_SIZE,  	},  	{ @@ -728,17 +704,18 @@ static struct ecryptfs_cache_info {  		.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; +	/* +	 * Make sure all delayed rcu free inodes are flushed before we +	 * destroy cache. +	 */ +	rcu_barrier(); +  	for (i = 0; i < ARRAY_SIZE(ecryptfs_cache_infos); i++) {  		struct ecryptfs_cache_info *info; @@ -828,9 +805,10 @@ static int __init ecryptfs_init(void)  		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 [%d] bytes; " -				"the page size is [%d] bytes.\n", -				ECRYPTFS_DEFAULT_EXTENT_SIZE, PAGE_CACHE_SIZE); +				"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(); @@ -839,15 +817,10 @@ static int __init ecryptfs_init(void)  		       "Failed to allocate one or more kmem_cache objects\n");  		goto out;  	} -	rc = register_filesystem(&ecryptfs_fs_type); -	if (rc) { -		printk(KERN_ERR "Failed to register filesystem\n"); -		goto out_free_kmem_caches; -	}  	rc = do_sysfs_registration();  	if (rc) {  		printk(KERN_ERR "sysfs registration failed\n"); -		goto out_unregister_filesystem; +		goto out_free_kmem_caches;  	}  	rc = ecryptfs_init_kthread();  	if (rc) { @@ -857,7 +830,7 @@ static int __init ecryptfs_init(void)  	}  	rc = ecryptfs_init_messaging();  	if (rc) { -		printk(KERN_ERR "Failure occured while attempting to " +		printk(KERN_ERR "Failure occurred while attempting to "  				"initialize the communications channel to "  				"ecryptfsd\n");  		goto out_destroy_kthread; @@ -868,19 +841,24 @@ static int __init ecryptfs_init(void)  		       "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_unregister_filesystem: -	unregister_filesystem(&ecryptfs_fs_type);  out_free_kmem_caches:  	ecryptfs_free_kmem_caches();  out: diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c index ab224809051..e57380e5f6b 100644 --- a/fs/ecryptfs/messaging.c +++ b/fs/ecryptfs/messaging.c @@ -32,8 +32,8 @@ 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) +#define ecryptfs_current_euid_hash(uid) \ +	hash_long((unsigned long)from_kuid(&init_user_ns, current_euid()), ecryptfs_hash_bits)  static u32 ecryptfs_msg_counter;  static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr; @@ -97,34 +97,29 @@ static void ecryptfs_msg_ctx_free_to_alloc(struct ecryptfs_msg_ctx *msg_ctx)  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); +	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. + * Search the hash list for the current effective 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) +int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon)  { -	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) { +	hlist_for_each_entry(*daemon, +			    &ecryptfs_daemon_hash[ecryptfs_current_euid_hash()], +			    euid_chain) { +		if (uid_eq((*daemon)->file->f_cred->euid, current_euid())) {  			rc = 0;  			goto out;  		} @@ -137,9 +132,7 @@ out:  /**   * 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 + * @file: File used when opening /dev/ecryptfs   *   * Must be called ceremoniously while in possession of   * ecryptfs_sacred_daemon_hash_mux @@ -147,8 +140,7 @@ out:   * 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) +ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, struct file *file)  {  	int rc = 0; @@ -159,16 +151,13 @@ ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid,  		       "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; +	(*daemon)->file = file;  	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)]); +		       &ecryptfs_daemon_hash[ecryptfs_current_euid_hash()]);  out:  	return rc;  } @@ -188,9 +177,6 @@ int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon)  	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;  	} @@ -203,12 +189,6 @@ int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon)  		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: @@ -216,42 +196,9 @@ out:  }  /** - * 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 @@ -270,16 +217,11 @@ out_unlock:   *   * 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) +int ecryptfs_process_response(struct ecryptfs_daemon *daemon, +			      struct ecryptfs_message *msg, 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) { @@ -292,51 +234,6 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,  	}  	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 " @@ -350,18 +247,16 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,  		goto unlock;  	}  	msg_size = (sizeof(*msg) + msg->data_len); -	msg_ctx->msg = kmalloc(msg_size, GFP_KERNEL); +	msg_ctx->msg = kmemdup(msg, 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); +	rc = 0;  unlock:  	mutex_unlock(&msg_ctx->mux);  out: @@ -383,14 +278,11 @@ 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 = ecryptfs_find_daemon_by_euid(&daemon); +	if (rc) {  		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); @@ -550,7 +442,6 @@ void ecryptfs_release_messaging(void)  		mutex_unlock(&ecryptfs_msg_ctx_lists_mux);  	}  	if (ecryptfs_daemon_hash) { -		struct hlist_node *elem;  		struct ecryptfs_daemon *daemon;  		int i; @@ -558,7 +449,7 @@ void ecryptfs_release_messaging(void)  		for (i = 0; i < (1 << ecryptfs_hash_bits); i++) {  			int rc; -			hlist_for_each_entry(daemon, elem, +			hlist_for_each_entry(daemon,  					     &ecryptfs_daemon_hash[i],  					     euid_chain) {  				rc = ecryptfs_exorcise_daemon(daemon); diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c index 940a82e63dc..e4141f25749 100644 --- a/fs/ecryptfs/miscdev.c +++ b/fs/ecryptfs/miscdev.c @@ -33,7 +33,7 @@ static atomic_t ecryptfs_num_miscdev_opens;  /**   * ecryptfs_miscdev_poll - * @file: dev file (ignored) + * @file: dev file   * @pt: dev poll table (ignored)   *   * Returns the poll mask @@ -41,17 +41,10 @@ static atomic_t ecryptfs_num_miscdev_opens;  static unsigned int  ecryptfs_miscdev_poll(struct file *file, poll_table *pt)  { -	struct ecryptfs_daemon *daemon; +	struct ecryptfs_daemon *daemon = file->private_data;  	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()); -	BUG_ON(rc || !daemon);  	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__); @@ -76,7 +69,7 @@ out_unlock_daemon:  /**   * ecryptfs_miscdev_open   * @inode: inode of miscdev handle (ignored) - * @file: file for miscdev handle (ignored) + * @file: file for miscdev handle   *   * Returns zero on success; non-zero otherwise   */ @@ -84,50 +77,30 @@ 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); +	rc = ecryptfs_find_daemon_by_euid(&daemon); +	if (!rc) { +		rc = -EINVAL;  		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; -		} +	rc = ecryptfs_spawn_daemon(&daemon, file); +	if (rc) { +		printk(KERN_ERR "%s: Error attempting to spawn daemon; " +		       "rc = [%d]\n", __func__, rc); +		goto out_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; @@ -136,7 +109,7 @@ out_unlock_daemon_list:  /**   * ecryptfs_miscdev_release   * @inode: inode of fs/ecryptfs/euid handle (ignored) - * @file: file for fs/ecryptfs/euid handle (ignored) + * @file: file for fs/ecryptfs/euid handle   *   * This keeps the daemon registered until the daemon sends another   * ioctl to fs/ecryptfs/ctl or until the kernel module unregisters. @@ -146,28 +119,24 @@ out_unlock_daemon_list:  static int  ecryptfs_miscdev_release(struct inode *inode, struct file *file)  { -	struct ecryptfs_daemon *daemon = NULL; -	uid_t euid = current_euid(); +	struct ecryptfs_daemon *daemon = file->private_data;  	int rc; -	mutex_lock(&ecryptfs_daemon_hash_mux); -	rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); -	BUG_ON(rc || !daemon);  	mutex_lock(&daemon->mux); -	BUG_ON(daemon->pid != task_pid(current));  	BUG_ON(!(daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN));  	daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN;  	atomic_dec(&ecryptfs_num_miscdev_opens);  	mutex_unlock(&daemon->mux); + +	mutex_lock(&ecryptfs_daemon_hash_mux);  	rc = ecryptfs_exorcise_daemon(daemon); +	mutex_unlock(&ecryptfs_daemon_hash_mux);  	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;  } @@ -191,36 +160,60 @@ 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)  { -	int rc = 0; +	struct ecryptfs_message *msg; -	mutex_lock(&msg_ctx->mux); -	msg_ctx->msg = kmalloc((sizeof(*msg_ctx->msg) + data_size), -			       GFP_KERNEL); -	if (!msg_ctx->msg) { -		rc = -ENOMEM; +	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_ctx->msg) + data_size)); -		goto out_unlock; +		       (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); -	mutex_lock(&daemon->mux);  	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); -out_unlock: -	mutex_unlock(&msg_ctx->mux); -	return rc; + +	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) + * @file: miscdevfs handle   * @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) @@ -234,35 +227,27 @@ static ssize_t  ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count,  		      loff_t *ppos)  { -	struct ecryptfs_daemon *daemon; +	struct ecryptfs_daemon *daemon = file->private_data;  	struct ecryptfs_msg_ctx *msg_ctx;  	size_t packet_length_size; -	char packet_length[3]; +	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()); -	BUG_ON(rc || !daemon);  	mutex_lock(&daemon->mux);  	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); @@ -284,9 +269,6 @@ check_list:  		 * message from the queue; try again */  		goto check_list;  	} -	BUG_ON(euid != daemon->euid); -	BUG_ON(current_user_ns() != daemon->user_ns); -	BUG_ON(task_pid(current) != daemon->pid);  	msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue,  				   struct ecryptfs_msg_ctx, daemon_out_list);  	BUG_ON(!msg_ctx); @@ -305,15 +287,8 @@ check_list:  		packet_length_size = 0;  		msg_ctx->msg_size = 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 */ -	total_length = (1 + 4 + packet_length_size + msg_ctx->msg_size); +	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 " @@ -324,9 +299,10 @@ check_list:  	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 + 1))) +	if (put_user(cpu_to_be32(msg_ctx->counter), +		     (__be32 __user *)(&buf[PKT_CTR_OFFSET])))  		goto out_unlock_msg_ctx; -	i = 5; +	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; @@ -355,16 +331,12 @@ out_unlock_daemon:   * 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) +static int ecryptfs_miscdev_response(struct ecryptfs_daemon *daemon, char *data, +				     size_t data_size, u32 seq)  {  	struct ecryptfs_message *msg = (struct ecryptfs_message *)data;  	int rc; @@ -376,7 +348,7 @@ static int ecryptfs_miscdev_response(char *data, size_t data_size,  		rc = -EINVAL;  		goto out;  	} -	rc = ecryptfs_process_response(msg, euid, user_ns, pid, seq); +	rc = ecryptfs_process_response(daemon, msg, seq);  	if (rc)  		printk(KERN_ERR  		       "Error processing response message; rc = [%d]\n", rc); @@ -386,17 +358,11 @@ out:  /**   * ecryptfs_miscdev_write - handle write to daemon miscdev handle - * @file: File for misc dev handle (ignored) + * @file: File for misc dev handle   * @buf: Buffer containing user data   * @count: Amount of data in @buf   * @ppos: Pointer to offset in file (ignored)   * - * miscdevfs packet format: - *  Octet 0: Type - *  Octets 1-4: network byte order msg_ctx->counter (0's for non-response) - *  Octets 5-N0: Size of struct ecryptfs_message to follow - *  Octets N0-N1: struct ecryptfs_message (including data) - *   * Returns the number of bytes read from @buf   */  static ssize_t @@ -405,60 +371,76 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,  {  	__be32 counter_nbo;  	u32 seq; -	size_t packet_size, packet_size_length, i; -	ssize_t sz = 0; +	size_t packet_size, packet_size_length;  	char *data; -	uid_t euid = current_euid(); -	int rc; +	unsigned char packet_size_peek[ECRYPTFS_MAX_PKT_LEN_SIZE]; +	ssize_t rc; -	if (count == 0) -		goto out; +	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)); -		goto out; +		return PTR_ERR(data);  	} -	sz = count; -	i = 0; -	switch (data[i++]) { +	switch (data[PKT_TYPE_OFFSET]) {  	case ECRYPTFS_MSG_RESPONSE: -		if (count < (1 + 4 + 1 + sizeof(struct ecryptfs_message))) { +		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__, -			       (1 + 4 + 1 + sizeof(struct ecryptfs_message)), -			       count); +			       (MIN_MSG_PKT_SIZE +				+ sizeof(struct ecryptfs_message)), count); +			rc = -EINVAL;  			goto out_free;  		} -		memcpy(&counter_nbo, &data[i], 4); +		memcpy(&counter_nbo, &data[PKT_CTR_OFFSET], PKT_CTR_SIZE);  		seq = be32_to_cpu(counter_nbo); -		i += 4; -		rc = ecryptfs_parse_packet_length(&data[i], &packet_size, -						  &packet_size_length); +		rc = ecryptfs_miscdev_response(file->private_data, +				&data[PKT_LEN_OFFSET + packet_size_length], +				packet_size, seq);  		if (rc) { -			printk(KERN_WARNING "%s: Error parsing packet length; " -			       "rc = [%d]\n", __func__, rc); -			goto out_free; -		} -		i += packet_size_length; -		if ((1 + 4 + packet_size_length + packet_size) != count) { -			printk(KERN_WARNING "%s: (1 + packet_size_length([%zd])" -			       " + packet_size([%zd]))([%zd]) != " -			       "count([%zd]). Invalid packet format.\n", -			       __func__, packet_size_length, packet_size, -			       (1 + packet_size_length + packet_size), count); -			goto out_free; -		} -		rc = ecryptfs_miscdev_response(&data[i], 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 = [%d]\n", +			       "response to requesting operation; rc = [%zd]\n",  			       __func__, rc); +			goto out_free; +		}  		break;  	case ECRYPTFS_MSG_HELO:  	case ECRYPTFS_MSG_QUIT: @@ -467,16 +449,18 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,  		ecryptfs_printk(KERN_WARNING, "Dropping miscdev "  				"message of unrecognized type [%d]\n",  				data[0]); -		break; +		rc = -EINVAL; +		goto out_free;  	} +	rc = count;  out_free:  	kfree(data); -out: -	return sz; +	return rc;  }  static const struct file_operations ecryptfs_miscdev_fops = { +	.owner   = THIS_MODULE,  	.open    = ecryptfs_miscdev_open,  	.poll    = ecryptfs_miscdev_poll,  	.read    = ecryptfs_miscdev_read, diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index b1d82756544..564a1fa34b9 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -57,6 +57,10 @@ struct page *ecryptfs_get_locked_page(struct inode *inode, loff_t index)   * @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)  { @@ -65,13 +69,13 @@ static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc)  	rc = ecryptfs_encrypt_page(page);  	if (rc) {  		ecryptfs_printk(KERN_WARNING, "Error encrypting " -				"page (upper index [0x%.16x])\n", page->index); +				"page (upper index [0x%.16lx])\n", page->index);  		ClearPageUptodate(page);  		goto out;  	}  	SetPageUptodate(page); -	unlock_page(page);  out: +	unlock_page(page);  	return rc;  } @@ -134,7 +138,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,  			/* This is a header extent */  			char *page_virt; -			page_virt = kmap_atomic(page, KM_USER0); +			page_virt = kmap_atomic(page);  			memset(page_virt, 0, PAGE_CACHE_SIZE);  			/* TODO: Support more than one header extent */  			if (view_extent_num == 0) { @@ -147,7 +151,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,  							       crypt_stat,  							       &written);  			} -			kunmap_atomic(page_virt, KM_USER0); +			kunmap_atomic(page_virt);  			flush_dcache_page(page);  			if (rc) {  				printk(KERN_ERR "%s: Error reading xattr " @@ -193,11 +197,7 @@ static int ecryptfs_readpage(struct file *file, struct page *page)  		&ecryptfs_inode_to_private(page->mapping->host)->crypt_stat;  	int rc = 0; -	if (!crypt_stat -	    || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED) -	    || (crypt_stat->flags & ECRYPTFS_NEW_FILE)) { -		ecryptfs_printk(KERN_DEBUG, -				"Passing through unencrypted page\n"); +	if (!crypt_stat || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {  		rc = ecryptfs_read_lower_page_segment(page, page->index, 0,  						      PAGE_CACHE_SIZE,  						      page->mapping->host); @@ -237,7 +237,7 @@ out:  		ClearPageUptodate(page);  	else  		SetPageUptodate(page); -	ecryptfs_printk(KERN_DEBUG, "Unlocking page with index = [0x%.16x]\n", +	ecryptfs_printk(KERN_DEBUG, "Unlocking page with index = [0x%.16lx]\n",  			page->index);  	unlock_page(page);  	return rc; @@ -290,12 +290,12 @@ static int ecryptfs_write_begin(struct file *file,  		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) -		    || (crypt_stat->flags & ECRYPTFS_NEW_FILE)) { +		if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {  			rc = ecryptfs_read_lower_page_segment(  				page, index, 0, PAGE_CACHE_SIZE, mapping->host);  			if (rc) { @@ -335,18 +335,24 @@ static int ecryptfs_write_begin(struct file *file,  				SetPageUptodate(page);  			}  		} 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; +			if (prev_page_end_size +			    >= i_size_read(page->mapping->host)) { +				zero_user(page, 0, PAGE_CACHE_SIZE); +				SetPageUptodate(page); +			} else if (len < PAGE_CACHE_SIZE) { +				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);  			} -			SetPageUptodate(page);  		}  	} -	prev_page_end_size = ((loff_t)index << PAGE_CACHE_SHIFT);  	/* If creating a page or more of holes, zero them out via truncate.  	 * Note, this will increase i_size. */  	if (index != 0) { @@ -368,6 +374,11 @@ static int ecryptfs_write_begin(struct file *file,  	    && (pos != 0))  		zero_user(page, 0, PAGE_CACHE_SIZE);  out: +	if (unlikely(rc)) { +		unlock_page(page); +		page_cache_release(page); +		*pagep = NULL; +	}  	return rc;  } @@ -463,10 +474,6 @@ int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode)   * @copied: The amount of data copied   * @page: The eCryptfs page   * @fsdata: The fsdata (unused) - * - * 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_write_end(struct file *file,  			struct address_space *mapping, @@ -481,14 +488,8 @@ static int ecryptfs_write_end(struct file *file,  		&ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;  	int rc; -	if (crypt_stat->flags & ECRYPTFS_NEW_FILE) { -		ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_NEW_FILE flag set in " -			"crypt_stat at memory location [%p]\n", crypt_stat); -		crypt_stat->flags &= ~(ECRYPTFS_NEW_FILE); -	} else -		ecryptfs_printk(KERN_DEBUG, "Not a new file\n");  	ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page" -			"(page w/ index = [0x%.16x], to = [%d])\n", index, to); +			"(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); @@ -499,23 +500,31 @@ static int ecryptfs_write_end(struct file *file,  		}  		goto out;  	} +	if (!PageUptodate(page)) { +		if (copied < PAGE_CACHE_SIZE) { +			rc = 0; +			goto out; +		} +		SetPageUptodate(page); +	}  	/* 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%.16x]\n", index); +			"zeros in page with index = [0x%.16lx]\n", index);  		goto out;  	}  	rc = ecryptfs_encrypt_page(page);  	if (rc) {  		ecryptfs_printk(KERN_WARNING, "Error encrypting page (upper " -				"index [0x%.16x])\n", index); +				"index [0x%.16lx])\n", index);  		goto out;  	}  	if (pos + copied > i_size_read(ecryptfs_inode)) {  		i_size_write(ecryptfs_inode, pos + copied);  		ecryptfs_printk(KERN_DEBUG, "Expanded file size to " -				"[0x%.16x]\n", i_size_read(ecryptfs_inode)); +			"[0x%.16llx]\n", +			(unsigned long long)i_size_read(ecryptfs_inode));  	}  	rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode);  	if (rc) diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c index db184ef15d3..09fe622274e 100644 --- a/fs/ecryptfs/read_write.c +++ b/fs/ecryptfs/read_write.c @@ -39,20 +39,13 @@  int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data,  			 loff_t offset, size_t size)  { -	struct ecryptfs_inode_info *inode_info; -	mm_segment_t fs_save; +	struct file *lower_file;  	ssize_t rc; -	inode_info = ecryptfs_inode_to_private(ecryptfs_inode); -	mutex_lock(&inode_info->lower_file_mutex); -	BUG_ON(!inode_info->lower_file); -	inode_info->lower_file->f_pos = offset; -	fs_save = get_fs(); -	set_fs(get_ds()); -	rc = vfs_write(inode_info->lower_file, data, size, -		       &inode_info->lower_file->f_pos); -	set_fs(fs_save); -	mutex_unlock(&inode_info->lower_file_mutex); +	lower_file = ecryptfs_inode_to_private(ecryptfs_inode)->lower_file; +	if (!lower_file) +		return -EIO; +	rc = kernel_write(lower_file, data, size, offset);  	mark_inode_dirty_sync(ecryptfs_inode);  	return rc;  } @@ -133,13 +126,18 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,  		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); -		size_t total_remaining_bytes = ((offset + size) - pos); +		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 */ -			size_t total_remaining_zeros = (offset - pos); +			loff_t total_remaining_zeros = (offset - pos);  			if (num_bytes > total_remaining_zeros)  				num_bytes = total_remaining_zeros; @@ -154,7 +152,7 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,  			       ecryptfs_page_idx, rc);  			goto out;  		} -		ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0); +		ecryptfs_page_virt = kmap_atomic(ecryptfs_page);  		/*  		 * pos: where we're now writing, offset: where the request was @@ -177,7 +175,7 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,  			       (data + data_offset), num_bytes);  			data_offset += num_bytes;  		} -		kunmap_atomic(ecryptfs_page_virt, KM_USER0); +		kunmap_atomic(ecryptfs_page_virt);  		flush_dcache_page(ecryptfs_page);  		SetPageUptodate(ecryptfs_page);  		unlock_page(ecryptfs_page); @@ -196,15 +194,19 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,  		}  		pos += num_bytes;  	} -	if ((offset + size) > ecryptfs_file_size) { -		i_size_write(ecryptfs_inode, (offset + size)); +	if (pos > ecryptfs_file_size) { +		i_size_write(ecryptfs_inode, pos);  		if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) { -			rc = ecryptfs_write_inode_size_to_metadata( +			int rc2; + +			rc2 = ecryptfs_write_inode_size_to_metadata(  								ecryptfs_inode); -			if (rc) { +			if (rc2) {  				printk(KERN_ERR	"Problem with "  				       "ecryptfs_write_inode_size_to_metadata; " -				       "rc = [%d]\n", rc); +				       "rc = [%d]\n", rc2); +				if (!rc) +					rc = rc2;  				goto out;  			}  		} @@ -229,21 +231,11 @@ out:  int ecryptfs_read_lower(char *data, loff_t offset, size_t size,  			struct inode *ecryptfs_inode)  { -	struct ecryptfs_inode_info *inode_info = -		ecryptfs_inode_to_private(ecryptfs_inode); -	mm_segment_t fs_save; -	ssize_t rc; - -	mutex_lock(&inode_info->lower_file_mutex); -	BUG_ON(!inode_info->lower_file); -	inode_info->lower_file->f_pos = offset; -	fs_save = get_fs(); -	set_fs(get_ds()); -	rc = vfs_read(inode_info->lower_file, data, size, -		      &inode_info->lower_file->f_pos); -	set_fs(fs_save); -	mutex_unlock(&inode_info->lower_file_mutex); -	return rc; +	struct file *lower_file; +	lower_file = ecryptfs_inode_to_private(ecryptfs_inode)->lower_file; +	if (!lower_file) +		return -EIO; +	return kernel_read(lower_file, offset, data, size);  }  /** @@ -279,76 +271,3 @@ int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs,  	flush_dcache_page(page_for_ecryptfs);  	return rc;  } - -#if 0 -/** - * ecryptfs_read - * @data: The virtual address into which to write the data read (and - *        possibly decrypted) from the lower file - * @offset: The offset in the decrypted view of the file from which to - *          read into @data - * @size: The number of bytes to read into @data - * @ecryptfs_file: The eCryptfs file from which to read - * - * Read an arbitrary amount of data from an arbitrary location in the - * eCryptfs page cache. This is done on an extent-by-extent basis; - * individual extents are decrypted and read from the lower page - * cache (via VFS reads). This function takes care of all the - * address translation to locations in the lower filesystem. - * - * Returns zero on success; non-zero otherwise - */ -int ecryptfs_read(char *data, loff_t offset, size_t size, -		  struct file *ecryptfs_file) -{ -	struct inode *ecryptfs_inode = ecryptfs_file->f_dentry->d_inode; -	struct page *ecryptfs_page; -	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; - -	if ((offset + size) > ecryptfs_file_size) { -		rc = -EINVAL; -		printk(KERN_ERR "%s: Attempt to read data past the end of the " -			"file; offset = [%lld]; size = [%td]; " -		       "ecryptfs_file_size = [%lld]\n", -		       __func__, offset, size, ecryptfs_file_size); -		goto out; -	} -	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); -		size_t total_remaining_bytes = ((offset + size) - pos); - -		if (num_bytes > total_remaining_bytes) -			num_bytes = total_remaining_bytes; -		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, KM_USER0); -		memcpy((data + data_offset), -		       ((char *)ecryptfs_page_virt + start_offset_in_page), -		       num_bytes); -		kunmap_atomic(ecryptfs_page_virt, KM_USER0); -		flush_dcache_page(ecryptfs_page); -		SetPageUptodate(ecryptfs_page); -		unlock_page(ecryptfs_page); -		page_cache_release(ecryptfs_page); -		pos += num_bytes; -		data_offset += num_bytes; -	} -out: -	return rc; -} -#endif  /*  0  */ diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c index 253732382d3..afa1b81c341 100644 --- a/fs/ecryptfs/super.c +++ b/fs/ecryptfs/super.c @@ -28,9 +28,10 @@  #include <linux/key.h>  #include <linux/slab.h>  #include <linux/seq_file.h> -#include <linux/smp_lock.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; @@ -57,20 +58,29 @@ static struct inode *ecryptfs_alloc_inode(struct super_block *sb)  		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. This - * function also fput()'s the persistent file for the lower inode. + * 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) @@ -78,34 +88,9 @@ static void ecryptfs_destroy_inode(struct inode *inode)  	struct ecryptfs_inode_info *inode_info;  	inode_info = ecryptfs_inode_to_private(inode); -	if (inode_info->lower_file) { -		struct dentry *lower_dentry = -			inode_info->lower_file->f_dentry; - -		BUG_ON(!lower_dentry); -		if (lower_dentry->d_inode) { -			fput(inode_info->lower_file); -			inode_info->lower_file = NULL; -		} -	} +	BUG_ON(inode_info->lower_file);  	ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat); -	kmem_cache_free(ecryptfs_inode_info_cache, inode_info); -} - -/** - * ecryptfs_init_inode - * @inode: The ecryptfs inode - * - * Set up the ecryptfs inode. - */ -void ecryptfs_init_inode(struct inode *inode, struct inode *lower_inode) -{ -	ecryptfs_set_inode_lower(inode, lower_inode); -	inode->i_ino = lower_inode->i_ino; -	inode->i_version++; -	inode->i_op = &ecryptfs_main_iops; -	inode->i_fop = &ecryptfs_main_fops; -	inode->i_mapping->a_ops = &ecryptfs_aops; +	call_rcu(&inode->i_rcu, ecryptfs_i_callback);  }  /** @@ -119,10 +104,20 @@ void ecryptfs_init_inode(struct inode *inode, struct inode *lower_inode)  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; -	return lower_dentry->d_sb->s_op->statfs(lower_dentry, buf); + +	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;  }  /** @@ -137,8 +132,8 @@ static int ecryptfs_statfs(struct dentry *dentry, struct kstatfs *buf)   */  static void ecryptfs_evict_inode(struct inode *inode)  { -	truncate_inode_pages(&inode->i_data, 0); -	end_writeback(inode); +	truncate_inode_pages_final(&inode->i_data); +	clear_inode(inode);  	iput(ecryptfs_inode_to_lower(inode));  } @@ -148,9 +143,9 @@ static void ecryptfs_evict_inode(struct inode *inode)   * Prints the mount options for a given superblock.   * Returns zero; does not fail.   */ -static int ecryptfs_show_options(struct seq_file *m, struct vfsmount *mnt) +static int ecryptfs_show_options(struct seq_file *m, struct dentry *root)  { -	struct super_block *sb = mnt->mnt_sb; +	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; @@ -189,7 +184,6 @@ static int ecryptfs_show_options(struct seq_file *m, struct vfsmount *mnt)  const struct super_operations ecryptfs_sops = {  	.alloc_inode = ecryptfs_alloc_inode,  	.destroy_inode = ecryptfs_destroy_inode, -	.drop_inode = generic_delete_inode,  	.statfs = ecryptfs_statfs,  	.remount_fs = NULL,  	.evict_inode = ecryptfs_evict_inode,  | 
