mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 05:02:12 +00:00
vfs-6.13.ecryptfs
-----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQRAhzRXHqcMeLMyaSiRxhvAZXjcogUCZzcmVQAKCRCRxhvAZXjc ogE8AP9fT1T0rkYHT2ym2ulnQ2oARqO5VOnGmzYiTs2oHAfn4wD9GwH1nkMvlNTY l7zalIg2AIdN6qvTATSoD3sN+fJXXgU= =RNSE -----END PGP SIGNATURE----- Merge tag 'vfs-6.13.ecryptfs' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull ecryptfs updates from Christian Brauner: "The folio project is about to remove page->index. This contains the work required for ecryptfs" * tag 'vfs-6.13.ecryptfs' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: ecryptfs: Pass the folio index to crypt_extent() ecryptfs: Convert lower_offset_for_page() to take a folio ecryptfs: Convert ecryptfs_decrypt_page() to take a folio ecryptfs: Convert ecryptfs_encrypt_page() to take a folio ecryptfs: Convert ecryptfs_write_lower_page_segment() to take a folio ecryptfs: Convert ecryptfs_write() to use a folio ecryptfs: Convert ecryptfs_read_lower_page_segment() to take a folio ecryptfs: Convert ecryptfs_copy_up_encrypted_with_header() to take a folio ecryptfs: Use a folio throughout ecryptfs_read_folio() ecryptfs: Convert ecryptfs_writepage() to ecryptfs_writepages()
This commit is contained in:
commit
23acd17754
@ -328,10 +328,10 @@ out:
|
|||||||
* Convert an eCryptfs page index into a lower byte offset
|
* Convert an eCryptfs page index into a lower byte offset
|
||||||
*/
|
*/
|
||||||
static loff_t lower_offset_for_page(struct ecryptfs_crypt_stat *crypt_stat,
|
static loff_t lower_offset_for_page(struct ecryptfs_crypt_stat *crypt_stat,
|
||||||
struct page *page)
|
struct folio *folio)
|
||||||
{
|
{
|
||||||
return ecryptfs_lower_header_size(crypt_stat) +
|
return ecryptfs_lower_header_size(crypt_stat) +
|
||||||
((loff_t)page->index << PAGE_SHIFT);
|
(loff_t)folio->index * PAGE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -340,6 +340,7 @@ static loff_t lower_offset_for_page(struct ecryptfs_crypt_stat *crypt_stat,
|
|||||||
* encryption operation
|
* encryption operation
|
||||||
* @dst_page: The page to write the result into
|
* @dst_page: The page to write the result into
|
||||||
* @src_page: The page to read from
|
* @src_page: The page to read from
|
||||||
|
* @page_index: The offset in the file (in units of PAGE_SIZE)
|
||||||
* @extent_offset: Page extent offset for use in generating IV
|
* @extent_offset: Page extent offset for use in generating IV
|
||||||
* @op: ENCRYPT or DECRYPT to indicate the desired operation
|
* @op: ENCRYPT or DECRYPT to indicate the desired operation
|
||||||
*
|
*
|
||||||
@ -350,9 +351,9 @@ static loff_t lower_offset_for_page(struct ecryptfs_crypt_stat *crypt_stat,
|
|||||||
static int crypt_extent(struct ecryptfs_crypt_stat *crypt_stat,
|
static int crypt_extent(struct ecryptfs_crypt_stat *crypt_stat,
|
||||||
struct page *dst_page,
|
struct page *dst_page,
|
||||||
struct page *src_page,
|
struct page *src_page,
|
||||||
|
pgoff_t page_index,
|
||||||
unsigned long extent_offset, int op)
|
unsigned long extent_offset, int op)
|
||||||
{
|
{
|
||||||
pgoff_t page_index = op == ENCRYPT ? src_page->index : dst_page->index;
|
|
||||||
loff_t extent_base;
|
loff_t extent_base;
|
||||||
char extent_iv[ECRYPTFS_MAX_IV_BYTES];
|
char extent_iv[ECRYPTFS_MAX_IV_BYTES];
|
||||||
struct scatterlist src_sg, dst_sg;
|
struct scatterlist src_sg, dst_sg;
|
||||||
@ -392,7 +393,7 @@ out:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* ecryptfs_encrypt_page
|
* ecryptfs_encrypt_page
|
||||||
* @page: Page mapped from the eCryptfs inode for the file; contains
|
* @folio: Folio mapped from the eCryptfs inode for the file; contains
|
||||||
* decrypted content that needs to be encrypted (to a temporary
|
* decrypted content that needs to be encrypted (to a temporary
|
||||||
* page; not in place) and written out to the lower file
|
* page; not in place) and written out to the lower file
|
||||||
*
|
*
|
||||||
@ -406,7 +407,7 @@ out:
|
|||||||
*
|
*
|
||||||
* Returns zero on success; negative on error
|
* Returns zero on success; negative on error
|
||||||
*/
|
*/
|
||||||
int ecryptfs_encrypt_page(struct page *page)
|
int ecryptfs_encrypt_page(struct folio *folio)
|
||||||
{
|
{
|
||||||
struct inode *ecryptfs_inode;
|
struct inode *ecryptfs_inode;
|
||||||
struct ecryptfs_crypt_stat *crypt_stat;
|
struct ecryptfs_crypt_stat *crypt_stat;
|
||||||
@ -416,7 +417,7 @@ int ecryptfs_encrypt_page(struct page *page)
|
|||||||
loff_t lower_offset;
|
loff_t lower_offset;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
ecryptfs_inode = page->mapping->host;
|
ecryptfs_inode = folio->mapping->host;
|
||||||
crypt_stat =
|
crypt_stat =
|
||||||
&(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat);
|
&(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat);
|
||||||
BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED));
|
BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED));
|
||||||
@ -431,8 +432,9 @@ int ecryptfs_encrypt_page(struct page *page)
|
|||||||
for (extent_offset = 0;
|
for (extent_offset = 0;
|
||||||
extent_offset < (PAGE_SIZE / crypt_stat->extent_size);
|
extent_offset < (PAGE_SIZE / crypt_stat->extent_size);
|
||||||
extent_offset++) {
|
extent_offset++) {
|
||||||
rc = crypt_extent(crypt_stat, enc_extent_page, page,
|
rc = crypt_extent(crypt_stat, enc_extent_page,
|
||||||
extent_offset, ENCRYPT);
|
folio_page(folio, 0), folio->index,
|
||||||
|
extent_offset, ENCRYPT);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
printk(KERN_ERR "%s: Error encrypting extent; "
|
printk(KERN_ERR "%s: Error encrypting extent; "
|
||||||
"rc = [%d]\n", __func__, rc);
|
"rc = [%d]\n", __func__, rc);
|
||||||
@ -440,7 +442,7 @@ int ecryptfs_encrypt_page(struct page *page)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lower_offset = lower_offset_for_page(crypt_stat, page);
|
lower_offset = lower_offset_for_page(crypt_stat, folio);
|
||||||
enc_extent_virt = kmap_local_page(enc_extent_page);
|
enc_extent_virt = kmap_local_page(enc_extent_page);
|
||||||
rc = ecryptfs_write_lower(ecryptfs_inode, enc_extent_virt, lower_offset,
|
rc = ecryptfs_write_lower(ecryptfs_inode, enc_extent_virt, lower_offset,
|
||||||
PAGE_SIZE);
|
PAGE_SIZE);
|
||||||
@ -461,7 +463,7 @@ out:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* ecryptfs_decrypt_page
|
* ecryptfs_decrypt_page
|
||||||
* @page: Page mapped from the eCryptfs inode for the file; data read
|
* @folio: Folio mapped from the eCryptfs inode for the file; data read
|
||||||
* and decrypted from the lower file will be written into this
|
* and decrypted from the lower file will be written into this
|
||||||
* page
|
* page
|
||||||
*
|
*
|
||||||
@ -475,7 +477,7 @@ out:
|
|||||||
*
|
*
|
||||||
* Returns zero on success; negative on error
|
* Returns zero on success; negative on error
|
||||||
*/
|
*/
|
||||||
int ecryptfs_decrypt_page(struct page *page)
|
int ecryptfs_decrypt_page(struct folio *folio)
|
||||||
{
|
{
|
||||||
struct inode *ecryptfs_inode;
|
struct inode *ecryptfs_inode;
|
||||||
struct ecryptfs_crypt_stat *crypt_stat;
|
struct ecryptfs_crypt_stat *crypt_stat;
|
||||||
@ -484,13 +486,13 @@ int ecryptfs_decrypt_page(struct page *page)
|
|||||||
loff_t lower_offset;
|
loff_t lower_offset;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
ecryptfs_inode = page->mapping->host;
|
ecryptfs_inode = folio->mapping->host;
|
||||||
crypt_stat =
|
crypt_stat =
|
||||||
&(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat);
|
&(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat);
|
||||||
BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED));
|
BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED));
|
||||||
|
|
||||||
lower_offset = lower_offset_for_page(crypt_stat, page);
|
lower_offset = lower_offset_for_page(crypt_stat, folio);
|
||||||
page_virt = kmap_local_page(page);
|
page_virt = kmap_local_folio(folio, 0);
|
||||||
rc = ecryptfs_read_lower(page_virt, lower_offset, PAGE_SIZE,
|
rc = ecryptfs_read_lower(page_virt, lower_offset, PAGE_SIZE,
|
||||||
ecryptfs_inode);
|
ecryptfs_inode);
|
||||||
kunmap_local(page_virt);
|
kunmap_local(page_virt);
|
||||||
@ -504,8 +506,9 @@ int ecryptfs_decrypt_page(struct page *page)
|
|||||||
for (extent_offset = 0;
|
for (extent_offset = 0;
|
||||||
extent_offset < (PAGE_SIZE / crypt_stat->extent_size);
|
extent_offset < (PAGE_SIZE / crypt_stat->extent_size);
|
||||||
extent_offset++) {
|
extent_offset++) {
|
||||||
rc = crypt_extent(crypt_stat, page, page,
|
struct page *page = folio_page(folio, 0);
|
||||||
extent_offset, DECRYPT);
|
rc = crypt_extent(crypt_stat, page, page, folio->index,
|
||||||
|
extent_offset, DECRYPT);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
printk(KERN_ERR "%s: Error decrypting extent; "
|
printk(KERN_ERR "%s: Error decrypting extent; "
|
||||||
"rc = [%d]\n", __func__, rc);
|
"rc = [%d]\n", __func__, rc);
|
||||||
|
@ -569,8 +569,8 @@ void ecryptfs_destroy_mount_crypt_stat(
|
|||||||
struct ecryptfs_mount_crypt_stat *mount_crypt_stat);
|
struct ecryptfs_mount_crypt_stat *mount_crypt_stat);
|
||||||
int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat);
|
int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat);
|
||||||
int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode);
|
int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode);
|
||||||
int ecryptfs_encrypt_page(struct page *page);
|
int ecryptfs_encrypt_page(struct folio *folio);
|
||||||
int ecryptfs_decrypt_page(struct page *page);
|
int ecryptfs_decrypt_page(struct folio *folio);
|
||||||
int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry,
|
int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry,
|
||||||
struct inode *ecryptfs_inode);
|
struct inode *ecryptfs_inode);
|
||||||
int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry);
|
int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry);
|
||||||
@ -653,16 +653,15 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,
|
|||||||
int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data,
|
int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data,
|
||||||
loff_t offset, size_t size);
|
loff_t offset, size_t size);
|
||||||
int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode,
|
int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode,
|
||||||
struct page *page_for_lower,
|
struct folio *folio_for_lower,
|
||||||
size_t offset_in_page, size_t size);
|
size_t offset_in_page, size_t size);
|
||||||
int ecryptfs_write(struct inode *inode, char *data, loff_t offset, size_t size);
|
int ecryptfs_write(struct inode *inode, char *data, loff_t offset, size_t size);
|
||||||
int ecryptfs_read_lower(char *data, loff_t offset, size_t size,
|
int ecryptfs_read_lower(char *data, loff_t offset, size_t size,
|
||||||
struct inode *ecryptfs_inode);
|
struct inode *ecryptfs_inode);
|
||||||
int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs,
|
int ecryptfs_read_lower_page_segment(struct folio *folio_for_ecryptfs,
|
||||||
pgoff_t page_index,
|
pgoff_t page_index,
|
||||||
size_t offset_in_page, size_t size,
|
size_t offset_in_page, size_t size,
|
||||||
struct inode *ecryptfs_inode);
|
struct inode *ecryptfs_inode);
|
||||||
struct page *ecryptfs_get_locked_page(struct inode *inode, loff_t index);
|
|
||||||
int ecryptfs_parse_packet_length(unsigned char *data, size_t *size,
|
int ecryptfs_parse_packet_length(unsigned char *data, size_t *size,
|
||||||
size_t *length_size);
|
size_t *length_size);
|
||||||
int ecryptfs_write_packet_length(char *dest, size_t size,
|
int ecryptfs_write_packet_length(char *dest, size_t size,
|
||||||
|
@ -23,47 +23,29 @@
|
|||||||
#include "ecryptfs_kernel.h"
|
#include "ecryptfs_kernel.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ecryptfs_get_locked_page
|
|
||||||
*
|
|
||||||
* Get one page from cache or lower f/s, return error otherwise.
|
|
||||||
*
|
|
||||||
* Returns locked and up-to-date page (if ok), with increased
|
|
||||||
* refcnt.
|
|
||||||
*/
|
|
||||||
struct page *ecryptfs_get_locked_page(struct inode *inode, loff_t index)
|
|
||||||
{
|
|
||||||
struct page *page = read_mapping_page(inode->i_mapping, index, NULL);
|
|
||||||
if (!IS_ERR(page))
|
|
||||||
lock_page(page);
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ecryptfs_writepage
|
|
||||||
* @page: Page that is locked before this call is made
|
|
||||||
* @wbc: Write-back control structure
|
|
||||||
*
|
|
||||||
* Returns zero on success; non-zero otherwise
|
|
||||||
*
|
|
||||||
* This is where we encrypt the data and pass the encrypted data to
|
* This is where we encrypt the data and pass the encrypted data to
|
||||||
* the lower filesystem. In OpenPGP-compatible mode, we operate on
|
* the lower filesystem. In OpenPGP-compatible mode, we operate on
|
||||||
* entire underlying packets.
|
* entire underlying packets.
|
||||||
*/
|
*/
|
||||||
static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc)
|
static int ecryptfs_writepages(struct address_space *mapping,
|
||||||
|
struct writeback_control *wbc)
|
||||||
{
|
{
|
||||||
int rc;
|
struct folio *folio = NULL;
|
||||||
|
int error;
|
||||||
|
|
||||||
rc = ecryptfs_encrypt_page(page);
|
while ((folio = writeback_iter(mapping, wbc, folio, &error))) {
|
||||||
if (rc) {
|
error = ecryptfs_encrypt_page(folio);
|
||||||
ecryptfs_printk(KERN_WARNING, "Error encrypting "
|
if (error) {
|
||||||
"page (upper index [0x%.16lx])\n", page->index);
|
ecryptfs_printk(KERN_WARNING,
|
||||||
ClearPageUptodate(page);
|
"Error encrypting folio (index [0x%.16lx])\n",
|
||||||
goto out;
|
folio->index);
|
||||||
|
folio_clear_uptodate(folio);
|
||||||
|
mapping_set_error(mapping, error);
|
||||||
|
}
|
||||||
|
folio_unlock(folio);
|
||||||
}
|
}
|
||||||
SetPageUptodate(page);
|
|
||||||
out:
|
return error;
|
||||||
unlock_page(page);
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void strip_xattr_flag(char *page_virt,
|
static void strip_xattr_flag(char *page_virt,
|
||||||
@ -97,7 +79,7 @@ static void strip_xattr_flag(char *page_virt,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* ecryptfs_copy_up_encrypted_with_header
|
* ecryptfs_copy_up_encrypted_with_header
|
||||||
* @page: Sort of a ``virtual'' representation of the encrypted lower
|
* @folio: Sort of a ``virtual'' representation of the encrypted lower
|
||||||
* file. The actual lower file does not have the metadata in
|
* file. The actual lower file does not have the metadata in
|
||||||
* the header. This is locked.
|
* the header. This is locked.
|
||||||
* @crypt_stat: The eCryptfs inode's cryptographic context
|
* @crypt_stat: The eCryptfs inode's cryptographic context
|
||||||
@ -106,7 +88,7 @@ static void strip_xattr_flag(char *page_virt,
|
|||||||
* seeing, with the header information inserted.
|
* seeing, with the header information inserted.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
ecryptfs_copy_up_encrypted_with_header(struct page *page,
|
ecryptfs_copy_up_encrypted_with_header(struct folio *folio,
|
||||||
struct ecryptfs_crypt_stat *crypt_stat)
|
struct ecryptfs_crypt_stat *crypt_stat)
|
||||||
{
|
{
|
||||||
loff_t extent_num_in_page = 0;
|
loff_t extent_num_in_page = 0;
|
||||||
@ -115,9 +97,9 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
while (extent_num_in_page < num_extents_per_page) {
|
while (extent_num_in_page < num_extents_per_page) {
|
||||||
loff_t view_extent_num = ((((loff_t)page->index)
|
loff_t view_extent_num = ((loff_t)folio->index
|
||||||
* num_extents_per_page)
|
* num_extents_per_page)
|
||||||
+ extent_num_in_page);
|
+ extent_num_in_page;
|
||||||
size_t num_header_extents_at_front =
|
size_t num_header_extents_at_front =
|
||||||
(crypt_stat->metadata_size / crypt_stat->extent_size);
|
(crypt_stat->metadata_size / crypt_stat->extent_size);
|
||||||
|
|
||||||
@ -125,21 +107,21 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
|
|||||||
/* This is a header extent */
|
/* This is a header extent */
|
||||||
char *page_virt;
|
char *page_virt;
|
||||||
|
|
||||||
page_virt = kmap_local_page(page);
|
page_virt = kmap_local_folio(folio, 0);
|
||||||
memset(page_virt, 0, PAGE_SIZE);
|
memset(page_virt, 0, PAGE_SIZE);
|
||||||
/* TODO: Support more than one header extent */
|
/* TODO: Support more than one header extent */
|
||||||
if (view_extent_num == 0) {
|
if (view_extent_num == 0) {
|
||||||
size_t written;
|
size_t written;
|
||||||
|
|
||||||
rc = ecryptfs_read_xattr_region(
|
rc = ecryptfs_read_xattr_region(
|
||||||
page_virt, page->mapping->host);
|
page_virt, folio->mapping->host);
|
||||||
strip_xattr_flag(page_virt + 16, crypt_stat);
|
strip_xattr_flag(page_virt + 16, crypt_stat);
|
||||||
ecryptfs_write_header_metadata(page_virt + 20,
|
ecryptfs_write_header_metadata(page_virt + 20,
|
||||||
crypt_stat,
|
crypt_stat,
|
||||||
&written);
|
&written);
|
||||||
}
|
}
|
||||||
kunmap_local(page_virt);
|
kunmap_local(page_virt);
|
||||||
flush_dcache_page(page);
|
flush_dcache_folio(folio);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
printk(KERN_ERR "%s: Error reading xattr "
|
printk(KERN_ERR "%s: Error reading xattr "
|
||||||
"region; rc = [%d]\n", __func__, rc);
|
"region; rc = [%d]\n", __func__, rc);
|
||||||
@ -152,9 +134,9 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
|
|||||||
- crypt_stat->metadata_size);
|
- crypt_stat->metadata_size);
|
||||||
|
|
||||||
rc = ecryptfs_read_lower_page_segment(
|
rc = ecryptfs_read_lower_page_segment(
|
||||||
page, (lower_offset >> PAGE_SHIFT),
|
folio, (lower_offset >> PAGE_SHIFT),
|
||||||
(lower_offset & ~PAGE_MASK),
|
(lower_offset & ~PAGE_MASK),
|
||||||
crypt_stat->extent_size, page->mapping->host);
|
crypt_stat->extent_size, folio->mapping->host);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
printk(KERN_ERR "%s: Error attempting to read "
|
printk(KERN_ERR "%s: Error attempting to read "
|
||||||
"extent at offset [%lld] in the lower "
|
"extent at offset [%lld] in the lower "
|
||||||
@ -180,55 +162,50 @@ out:
|
|||||||
*/
|
*/
|
||||||
static int ecryptfs_read_folio(struct file *file, struct folio *folio)
|
static int ecryptfs_read_folio(struct file *file, struct folio *folio)
|
||||||
{
|
{
|
||||||
struct page *page = &folio->page;
|
struct inode *inode = folio->mapping->host;
|
||||||
struct ecryptfs_crypt_stat *crypt_stat =
|
struct ecryptfs_crypt_stat *crypt_stat =
|
||||||
&ecryptfs_inode_to_private(page->mapping->host)->crypt_stat;
|
&ecryptfs_inode_to_private(inode)->crypt_stat;
|
||||||
int rc = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (!crypt_stat || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
|
if (!crypt_stat || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
|
||||||
rc = ecryptfs_read_lower_page_segment(page, page->index, 0,
|
err = ecryptfs_read_lower_page_segment(folio, folio->index, 0,
|
||||||
PAGE_SIZE,
|
folio_size(folio), inode);
|
||||||
page->mapping->host);
|
|
||||||
} else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) {
|
} else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) {
|
||||||
if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) {
|
if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) {
|
||||||
rc = ecryptfs_copy_up_encrypted_with_header(page,
|
err = ecryptfs_copy_up_encrypted_with_header(folio,
|
||||||
crypt_stat);
|
crypt_stat);
|
||||||
if (rc) {
|
if (err) {
|
||||||
printk(KERN_ERR "%s: Error attempting to copy "
|
printk(KERN_ERR "%s: Error attempting to copy "
|
||||||
"the encrypted content from the lower "
|
"the encrypted content from the lower "
|
||||||
"file whilst inserting the metadata "
|
"file whilst inserting the metadata "
|
||||||
"from the xattr into the header; rc = "
|
"from the xattr into the header; err = "
|
||||||
"[%d]\n", __func__, rc);
|
"[%d]\n", __func__, err);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
rc = ecryptfs_read_lower_page_segment(
|
err = ecryptfs_read_lower_page_segment(folio,
|
||||||
page, page->index, 0, PAGE_SIZE,
|
folio->index, 0, folio_size(folio),
|
||||||
page->mapping->host);
|
inode);
|
||||||
if (rc) {
|
if (err) {
|
||||||
printk(KERN_ERR "Error reading page; rc = "
|
printk(KERN_ERR "Error reading page; err = "
|
||||||
"[%d]\n", rc);
|
"[%d]\n", err);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rc = ecryptfs_decrypt_page(page);
|
err = ecryptfs_decrypt_page(folio);
|
||||||
if (rc) {
|
if (err) {
|
||||||
ecryptfs_printk(KERN_ERR, "Error decrypting page; "
|
ecryptfs_printk(KERN_ERR, "Error decrypting page; "
|
||||||
"rc = [%d]\n", rc);
|
"err = [%d]\n", err);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
if (rc)
|
ecryptfs_printk(KERN_DEBUG, "Unlocking folio with index = [0x%.16lx]\n",
|
||||||
ClearPageUptodate(page);
|
folio->index);
|
||||||
else
|
folio_end_read(folio, err == 0);
|
||||||
SetPageUptodate(page);
|
return err;
|
||||||
ecryptfs_printk(KERN_DEBUG, "Unlocking page with index = [0x%.16lx]\n",
|
|
||||||
page->index);
|
|
||||||
unlock_page(page);
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -285,7 +262,7 @@ static int ecryptfs_write_begin(struct file *file,
|
|||||||
|
|
||||||
if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
|
if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
|
||||||
rc = ecryptfs_read_lower_page_segment(
|
rc = ecryptfs_read_lower_page_segment(
|
||||||
&folio->page, index, 0, PAGE_SIZE, mapping->host);
|
folio, index, 0, PAGE_SIZE, mapping->host);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
printk(KERN_ERR "%s: Error attempting to read "
|
printk(KERN_ERR "%s: Error attempting to read "
|
||||||
"lower page segment; rc = [%d]\n",
|
"lower page segment; rc = [%d]\n",
|
||||||
@ -297,7 +274,7 @@ static int ecryptfs_write_begin(struct file *file,
|
|||||||
} else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) {
|
} else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) {
|
||||||
if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) {
|
if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) {
|
||||||
rc = ecryptfs_copy_up_encrypted_with_header(
|
rc = ecryptfs_copy_up_encrypted_with_header(
|
||||||
&folio->page, crypt_stat);
|
folio, crypt_stat);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
printk(KERN_ERR "%s: Error attempting "
|
printk(KERN_ERR "%s: Error attempting "
|
||||||
"to copy the encrypted content "
|
"to copy the encrypted content "
|
||||||
@ -311,7 +288,7 @@ static int ecryptfs_write_begin(struct file *file,
|
|||||||
folio_mark_uptodate(folio);
|
folio_mark_uptodate(folio);
|
||||||
} else {
|
} else {
|
||||||
rc = ecryptfs_read_lower_page_segment(
|
rc = ecryptfs_read_lower_page_segment(
|
||||||
&folio->page, index, 0, PAGE_SIZE,
|
folio, index, 0, PAGE_SIZE,
|
||||||
mapping->host);
|
mapping->host);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
printk(KERN_ERR "%s: Error reading "
|
printk(KERN_ERR "%s: Error reading "
|
||||||
@ -328,7 +305,7 @@ static int ecryptfs_write_begin(struct file *file,
|
|||||||
folio_zero_range(folio, 0, PAGE_SIZE);
|
folio_zero_range(folio, 0, PAGE_SIZE);
|
||||||
folio_mark_uptodate(folio);
|
folio_mark_uptodate(folio);
|
||||||
} else if (len < PAGE_SIZE) {
|
} else if (len < PAGE_SIZE) {
|
||||||
rc = ecryptfs_decrypt_page(&folio->page);
|
rc = ecryptfs_decrypt_page(folio);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
printk(KERN_ERR "%s: Error decrypting "
|
printk(KERN_ERR "%s: Error decrypting "
|
||||||
"page at index [%ld]; "
|
"page at index [%ld]; "
|
||||||
@ -477,7 +454,7 @@ static int ecryptfs_write_end(struct file *file,
|
|||||||
"(page w/ index = [0x%.16lx], to = [%d])\n", index, to);
|
"(page w/ index = [0x%.16lx], to = [%d])\n", index, to);
|
||||||
if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
|
if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
|
||||||
rc = ecryptfs_write_lower_page_segment(ecryptfs_inode,
|
rc = ecryptfs_write_lower_page_segment(ecryptfs_inode,
|
||||||
&folio->page, 0, to);
|
folio, 0, to);
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
rc = copied;
|
rc = copied;
|
||||||
fsstack_copy_inode_size(ecryptfs_inode,
|
fsstack_copy_inode_size(ecryptfs_inode,
|
||||||
@ -499,7 +476,7 @@ static int ecryptfs_write_end(struct file *file,
|
|||||||
"zeros in page with index = [0x%.16lx]\n", index);
|
"zeros in page with index = [0x%.16lx]\n", index);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
rc = ecryptfs_encrypt_page(&folio->page);
|
rc = ecryptfs_encrypt_page(folio);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ecryptfs_printk(KERN_WARNING, "Error encrypting page (upper "
|
ecryptfs_printk(KERN_WARNING, "Error encrypting page (upper "
|
||||||
"index [0x%.16lx])\n", index);
|
"index [0x%.16lx])\n", index);
|
||||||
@ -548,9 +525,10 @@ const struct address_space_operations ecryptfs_aops = {
|
|||||||
.dirty_folio = block_dirty_folio,
|
.dirty_folio = block_dirty_folio,
|
||||||
.invalidate_folio = block_invalidate_folio,
|
.invalidate_folio = block_invalidate_folio,
|
||||||
#endif
|
#endif
|
||||||
.writepage = ecryptfs_writepage,
|
.writepages = ecryptfs_writepages,
|
||||||
.read_folio = ecryptfs_read_folio,
|
.read_folio = ecryptfs_read_folio,
|
||||||
.write_begin = ecryptfs_write_begin,
|
.write_begin = ecryptfs_write_begin,
|
||||||
.write_end = ecryptfs_write_end,
|
.write_end = ecryptfs_write_end,
|
||||||
|
.migrate_folio = filemap_migrate_folio,
|
||||||
.bmap = ecryptfs_bmap,
|
.bmap = ecryptfs_bmap,
|
||||||
};
|
};
|
||||||
|
@ -41,30 +41,29 @@ int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data,
|
|||||||
/**
|
/**
|
||||||
* ecryptfs_write_lower_page_segment
|
* ecryptfs_write_lower_page_segment
|
||||||
* @ecryptfs_inode: The eCryptfs inode
|
* @ecryptfs_inode: The eCryptfs inode
|
||||||
* @page_for_lower: The page containing the data to be written to the
|
* @folio_for_lower: The folio containing the data to be written to the
|
||||||
* lower file
|
* lower file
|
||||||
* @offset_in_page: The offset in the @page_for_lower from which to
|
* @offset_in_page: The offset in the @folio_for_lower from which to
|
||||||
* start writing the data
|
* start writing the data
|
||||||
* @size: The amount of data from @page_for_lower to write to the
|
* @size: The amount of data from @folio_for_lower to write to the
|
||||||
* lower file
|
* lower file
|
||||||
*
|
*
|
||||||
* Determines the byte offset in the file for the given page and
|
* Determines the byte offset in the file for the given page and
|
||||||
* offset within the page, maps the page, and makes the call to write
|
* offset within the page, maps the page, and makes the call to write
|
||||||
* the contents of @page_for_lower to the lower inode.
|
* the contents of @folio_for_lower to the lower inode.
|
||||||
*
|
*
|
||||||
* Returns zero on success; non-zero otherwise
|
* Returns zero on success; non-zero otherwise
|
||||||
*/
|
*/
|
||||||
int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode,
|
int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode,
|
||||||
struct page *page_for_lower,
|
struct folio *folio_for_lower,
|
||||||
size_t offset_in_page, size_t size)
|
size_t offset_in_page, size_t size)
|
||||||
{
|
{
|
||||||
char *virt;
|
char *virt;
|
||||||
loff_t offset;
|
loff_t offset;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
offset = ((((loff_t)page_for_lower->index) << PAGE_SHIFT)
|
offset = (loff_t)folio_for_lower->index * PAGE_SIZE + offset_in_page;
|
||||||
+ offset_in_page);
|
virt = kmap_local_folio(folio_for_lower, 0);
|
||||||
virt = kmap_local_page(page_for_lower);
|
|
||||||
rc = ecryptfs_write_lower(ecryptfs_inode, virt, offset, size);
|
rc = ecryptfs_write_lower(ecryptfs_inode, virt, offset, size);
|
||||||
if (rc > 0)
|
if (rc > 0)
|
||||||
rc = 0;
|
rc = 0;
|
||||||
@ -93,7 +92,6 @@ int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode,
|
|||||||
int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,
|
int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,
|
||||||
size_t size)
|
size_t size)
|
||||||
{
|
{
|
||||||
struct page *ecryptfs_page;
|
|
||||||
struct ecryptfs_crypt_stat *crypt_stat;
|
struct ecryptfs_crypt_stat *crypt_stat;
|
||||||
char *ecryptfs_page_virt;
|
char *ecryptfs_page_virt;
|
||||||
loff_t ecryptfs_file_size = i_size_read(ecryptfs_inode);
|
loff_t ecryptfs_file_size = i_size_read(ecryptfs_inode);
|
||||||
@ -111,6 +109,7 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,
|
|||||||
else
|
else
|
||||||
pos = offset;
|
pos = offset;
|
||||||
while (pos < (offset + size)) {
|
while (pos < (offset + size)) {
|
||||||
|
struct folio *ecryptfs_folio;
|
||||||
pgoff_t ecryptfs_page_idx = (pos >> PAGE_SHIFT);
|
pgoff_t ecryptfs_page_idx = (pos >> PAGE_SHIFT);
|
||||||
size_t start_offset_in_page = (pos & ~PAGE_MASK);
|
size_t start_offset_in_page = (pos & ~PAGE_MASK);
|
||||||
size_t num_bytes = (PAGE_SIZE - start_offset_in_page);
|
size_t num_bytes = (PAGE_SIZE - start_offset_in_page);
|
||||||
@ -130,17 +129,18 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,
|
|||||||
if (num_bytes > total_remaining_zeros)
|
if (num_bytes > total_remaining_zeros)
|
||||||
num_bytes = total_remaining_zeros;
|
num_bytes = total_remaining_zeros;
|
||||||
}
|
}
|
||||||
ecryptfs_page = ecryptfs_get_locked_page(ecryptfs_inode,
|
ecryptfs_folio = read_mapping_folio(ecryptfs_inode->i_mapping,
|
||||||
ecryptfs_page_idx);
|
ecryptfs_page_idx, NULL);
|
||||||
if (IS_ERR(ecryptfs_page)) {
|
if (IS_ERR(ecryptfs_folio)) {
|
||||||
rc = PTR_ERR(ecryptfs_page);
|
rc = PTR_ERR(ecryptfs_folio);
|
||||||
printk(KERN_ERR "%s: Error getting page at "
|
printk(KERN_ERR "%s: Error getting page at "
|
||||||
"index [%ld] from eCryptfs inode "
|
"index [%ld] from eCryptfs inode "
|
||||||
"mapping; rc = [%d]\n", __func__,
|
"mapping; rc = [%d]\n", __func__,
|
||||||
ecryptfs_page_idx, rc);
|
ecryptfs_page_idx, rc);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ecryptfs_page_virt = kmap_local_page(ecryptfs_page);
|
folio_lock(ecryptfs_folio);
|
||||||
|
ecryptfs_page_virt = kmap_local_folio(ecryptfs_folio, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* pos: where we're now writing, offset: where the request was
|
* pos: where we're now writing, offset: where the request was
|
||||||
@ -164,17 +164,17 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,
|
|||||||
data_offset += num_bytes;
|
data_offset += num_bytes;
|
||||||
}
|
}
|
||||||
kunmap_local(ecryptfs_page_virt);
|
kunmap_local(ecryptfs_page_virt);
|
||||||
flush_dcache_page(ecryptfs_page);
|
flush_dcache_folio(ecryptfs_folio);
|
||||||
SetPageUptodate(ecryptfs_page);
|
folio_mark_uptodate(ecryptfs_folio);
|
||||||
unlock_page(ecryptfs_page);
|
folio_unlock(ecryptfs_folio);
|
||||||
if (crypt_stat->flags & ECRYPTFS_ENCRYPTED)
|
if (crypt_stat->flags & ECRYPTFS_ENCRYPTED)
|
||||||
rc = ecryptfs_encrypt_page(ecryptfs_page);
|
rc = ecryptfs_encrypt_page(ecryptfs_folio);
|
||||||
else
|
else
|
||||||
rc = ecryptfs_write_lower_page_segment(ecryptfs_inode,
|
rc = ecryptfs_write_lower_page_segment(ecryptfs_inode,
|
||||||
ecryptfs_page,
|
ecryptfs_folio,
|
||||||
start_offset_in_page,
|
start_offset_in_page,
|
||||||
data_offset);
|
data_offset);
|
||||||
put_page(ecryptfs_page);
|
folio_put(ecryptfs_folio);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
printk(KERN_ERR "%s: Error encrypting "
|
printk(KERN_ERR "%s: Error encrypting "
|
||||||
"page; rc = [%d]\n", __func__, rc);
|
"page; rc = [%d]\n", __func__, rc);
|
||||||
@ -228,7 +228,7 @@ int ecryptfs_read_lower(char *data, loff_t offset, size_t size,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* ecryptfs_read_lower_page_segment
|
* ecryptfs_read_lower_page_segment
|
||||||
* @page_for_ecryptfs: The page into which data for eCryptfs will be
|
* @folio_for_ecryptfs: The folio into which data for eCryptfs will be
|
||||||
* written
|
* written
|
||||||
* @page_index: Page index in @page_for_ecryptfs from which to start
|
* @page_index: Page index in @page_for_ecryptfs from which to start
|
||||||
* writing
|
* writing
|
||||||
@ -243,7 +243,7 @@ int ecryptfs_read_lower(char *data, loff_t offset, size_t size,
|
|||||||
*
|
*
|
||||||
* Returns zero on success; non-zero otherwise
|
* Returns zero on success; non-zero otherwise
|
||||||
*/
|
*/
|
||||||
int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs,
|
int ecryptfs_read_lower_page_segment(struct folio *folio_for_ecryptfs,
|
||||||
pgoff_t page_index,
|
pgoff_t page_index,
|
||||||
size_t offset_in_page, size_t size,
|
size_t offset_in_page, size_t size,
|
||||||
struct inode *ecryptfs_inode)
|
struct inode *ecryptfs_inode)
|
||||||
@ -252,12 +252,12 @@ int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs,
|
|||||||
loff_t offset;
|
loff_t offset;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
offset = ((((loff_t)page_index) << PAGE_SHIFT) + offset_in_page);
|
offset = (loff_t)page_index * PAGE_SIZE + offset_in_page;
|
||||||
virt = kmap_local_page(page_for_ecryptfs);
|
virt = kmap_local_folio(folio_for_ecryptfs, 0);
|
||||||
rc = ecryptfs_read_lower(virt, offset, size, ecryptfs_inode);
|
rc = ecryptfs_read_lower(virt, offset, size, ecryptfs_inode);
|
||||||
if (rc > 0)
|
if (rc > 0)
|
||||||
rc = 0;
|
rc = 0;
|
||||||
kunmap_local(virt);
|
kunmap_local(virt);
|
||||||
flush_dcache_page(page_for_ecryptfs);
|
flush_dcache_folio(folio_for_ecryptfs);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user