diff options
Diffstat (limited to 'fs/ecryptfs/mmap.c')
| -rw-r--r-- | fs/ecryptfs/mmap.c | 79 | 
1 files changed, 44 insertions, 35 deletions
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)  | 
