diff options
Diffstat (limited to 'fs/ecryptfs')
-rw-r--r-- | fs/ecryptfs/crypto.c | 41 | ||||
-rw-r--r-- | fs/ecryptfs/dentry.c | 18 | ||||
-rw-r--r-- | fs/ecryptfs/ecryptfs_kernel.h | 9 | ||||
-rw-r--r-- | fs/ecryptfs/inode.c | 50 | ||||
-rw-r--r-- | fs/ecryptfs/keystore.c | 4 | ||||
-rw-r--r-- | fs/ecryptfs/main.c | 415 | ||||
-rw-r--r-- | fs/ecryptfs/mmap.c | 212 | ||||
-rw-r--r-- | fs/ecryptfs/read_write.c | 50 | ||||
-rw-r--r-- | fs/ecryptfs/super.c | 1 |
9 files changed, 392 insertions, 408 deletions
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 2fe0f3af1a08..69536cacdea8 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -21,7 +21,7 @@ #include <linux/file.h> #include <linux/scatterlist.h> #include <linux/slab.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <linux/kernel.h> #include <linux/xattr.h> #include "ecryptfs_kernel.h" @@ -328,10 +328,10 @@ out: * Convert an eCryptfs page index into a lower byte offset */ 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) + - ((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 * @dst_page: The page to write the result into * @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 * @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, struct page *dst_page, struct page *src_page, + pgoff_t page_index, 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; @@ -392,7 +393,7 @@ out: /** * 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 * page; not in place) and written out to the lower file * @@ -406,7 +407,7 @@ out: * * 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 ecryptfs_crypt_stat *crypt_stat; @@ -416,7 +417,7 @@ int ecryptfs_encrypt_page(struct page *page) loff_t lower_offset; int rc = 0; - ecryptfs_inode = page->mapping->host; + ecryptfs_inode = folio->mapping->host; crypt_stat = &(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat); BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)); @@ -431,8 +432,9 @@ int ecryptfs_encrypt_page(struct page *page) for (extent_offset = 0; extent_offset < (PAGE_SIZE / crypt_stat->extent_size); extent_offset++) { - rc = crypt_extent(crypt_stat, enc_extent_page, page, - extent_offset, ENCRYPT); + rc = crypt_extent(crypt_stat, enc_extent_page, + folio_page(folio, 0), folio->index, + extent_offset, ENCRYPT); if (rc) { printk(KERN_ERR "%s: Error encrypting extent; " "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); rc = ecryptfs_write_lower(ecryptfs_inode, enc_extent_virt, lower_offset, PAGE_SIZE); @@ -461,7 +463,7 @@ out: /** * 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 * page * @@ -475,7 +477,7 @@ out: * * 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 ecryptfs_crypt_stat *crypt_stat; @@ -484,13 +486,13 @@ int ecryptfs_decrypt_page(struct page *page) loff_t lower_offset; int rc = 0; - ecryptfs_inode = page->mapping->host; + ecryptfs_inode = folio->mapping->host; crypt_stat = &(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat); BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)); - lower_offset = lower_offset_for_page(crypt_stat, page); - page_virt = kmap_local_page(page); + lower_offset = lower_offset_for_page(crypt_stat, folio); + page_virt = kmap_local_folio(folio, 0); rc = ecryptfs_read_lower(page_virt, lower_offset, PAGE_SIZE, ecryptfs_inode); kunmap_local(page_virt); @@ -504,8 +506,9 @@ int ecryptfs_decrypt_page(struct page *page) for (extent_offset = 0; extent_offset < (PAGE_SIZE / crypt_stat->extent_size); extent_offset++) { - rc = crypt_extent(crypt_stat, page, page, - extent_offset, DECRYPT); + struct page *page = folio_page(folio, 0); + rc = crypt_extent(crypt_stat, page, page, folio->index, + extent_offset, DECRYPT); if (rc) { printk(KERN_ERR "%s: Error decrypting extent; " "rc = [%d]\n", __func__, rc); @@ -1606,9 +1609,7 @@ ecryptfs_add_new_key_tfm(struct ecryptfs_key_tfm **key_tfm, char *cipher_name, goto out; } mutex_init(&tmp_tfm->key_tfm_mutex); - strncpy(tmp_tfm->cipher_name, cipher_name, - ECRYPTFS_MAX_CIPHER_NAME_SIZE); - tmp_tfm->cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE] = '\0'; + strscpy(tmp_tfm->cipher_name, cipher_name); tmp_tfm->key_size = key_size; rc = ecryptfs_process_key_cipher(&tmp_tfm->key_tfm, tmp_tfm->cipher_name, diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c index acaa0825e9bb..1dfd5b81d831 100644 --- a/fs/ecryptfs/dentry.c +++ b/fs/ecryptfs/dentry.c @@ -17,7 +17,9 @@ /** * ecryptfs_d_revalidate - revalidate an ecryptfs dentry - * @dentry: The ecryptfs dentry + * @dir: inode of expected parent + * @name: expected name + * @dentry: dentry to revalidate * @flags: lookup flags * * Called when the VFS needs to revalidate a dentry. This @@ -28,7 +30,8 @@ * Returns 1 if valid, 0 otherwise. * */ -static int ecryptfs_d_revalidate(struct dentry *dentry, unsigned int flags) +static int ecryptfs_d_revalidate(struct inode *dir, const struct qstr *name, + struct dentry *dentry, unsigned int flags) { struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); int rc = 1; @@ -36,8 +39,15 @@ static int ecryptfs_d_revalidate(struct dentry *dentry, unsigned int flags) if (flags & LOOKUP_RCU) return -ECHILD; - if (lower_dentry->d_flags & DCACHE_OP_REVALIDATE) - rc = lower_dentry->d_op->d_revalidate(lower_dentry, flags); + if (lower_dentry->d_flags & DCACHE_OP_REVALIDATE) { + struct inode *lower_dir = ecryptfs_inode_to_lower(dir); + struct name_snapshot n; + + take_dentry_name_snapshot(&n, lower_dentry); + rc = lower_dentry->d_op->d_revalidate(lower_dir, &n.name, + lower_dentry, flags); + release_dentry_name_snapshot(&n); + } if (d_really_is_positive(dentry)) { struct inode *inode = d_inode(dentry); diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index c586c5db18b5..1f562e75d0e4 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -569,8 +569,8 @@ void ecryptfs_destroy_mount_crypt_stat( struct ecryptfs_mount_crypt_stat *mount_crypt_stat); int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat); int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode); -int ecryptfs_encrypt_page(struct page *page); -int ecryptfs_decrypt_page(struct page *page); +int ecryptfs_encrypt_page(struct folio *folio); +int ecryptfs_decrypt_page(struct folio *folio); int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry, struct inode *ecryptfs_inode); 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, loff_t offset, size_t size); 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); int ecryptfs_write(struct inode *inode, char *data, loff_t offset, size_t size); int ecryptfs_read_lower(char *data, loff_t offset, size_t size, struct inode *ecryptfs_inode); -int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs, +int ecryptfs_read_lower_page_segment(struct folio *folio_for_ecryptfs, pgoff_t page_index, size_t offset_in_page, size_t size, struct inode *ecryptfs_inode); -struct page *ecryptfs_get_locked_page(struct inode *inode, loff_t index); int ecryptfs_parse_packet_length(unsigned char *data, size_t *size, size_t *length_size); int ecryptfs_write_packet_length(char *dest, size_t size, diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 5ed1e4cf6c0b..493d7f194956 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -21,7 +21,7 @@ #include <linux/posix_acl.h> #include <linux/posix_acl_xattr.h> #include <linux/fileattr.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include "ecryptfs_kernel.h" static int lock_parent(struct dentry *dentry, @@ -394,8 +394,8 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, char *encrypted_and_encoded_name = NULL; struct ecryptfs_mount_crypt_stat *mount_crypt_stat; struct dentry *lower_dir_dentry, *lower_dentry; - const char *name = ecryptfs_dentry->d_name.name; - size_t len = ecryptfs_dentry->d_name.len; + struct qstr qname = QSTR_INIT(ecryptfs_dentry->d_name.name, + ecryptfs_dentry->d_name.len); struct dentry *res; int rc = 0; @@ -404,23 +404,25 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, mount_crypt_stat = &ecryptfs_superblock_to_private( ecryptfs_dentry->d_sb)->mount_crypt_stat; if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) { + size_t len = qname.len; rc = ecryptfs_encrypt_and_encode_filename( &encrypted_and_encoded_name, &len, - mount_crypt_stat, name, len); + mount_crypt_stat, qname.name, len); if (rc) { printk(KERN_ERR "%s: Error attempting to encrypt and encode " "filename; rc = [%d]\n", __func__, rc); return ERR_PTR(rc); } - name = encrypted_and_encoded_name; + qname.name = encrypted_and_encoded_name; + qname.len = len; } - lower_dentry = lookup_one_len_unlocked(name, lower_dir_dentry, len); + lower_dentry = lookup_noperm_unlocked(&qname, lower_dir_dentry); if (IS_ERR(lower_dentry)) { - ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " + ecryptfs_printk(KERN_DEBUG, "%s: lookup_noperm() returned " "[%ld] on lower_dentry = [%s]\n", __func__, PTR_ERR(lower_dentry), - name); + qname.name); res = ERR_CAST(lower_dentry); } else { res = ecryptfs_lookup_interpose(ecryptfs_dentry, lower_dentry); @@ -503,18 +505,24 @@ out_lock: return rc; } -static int ecryptfs_mkdir(struct mnt_idmap *idmap, struct inode *dir, - struct dentry *dentry, umode_t mode) +static struct dentry *ecryptfs_mkdir(struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, umode_t mode) { int rc; struct dentry *lower_dentry; struct inode *lower_dir; rc = lock_parent(dentry, &lower_dentry, &lower_dir); - if (!rc) - rc = vfs_mkdir(&nop_mnt_idmap, lower_dir, - lower_dentry, mode); - if (rc || d_really_is_negative(lower_dentry)) + if (rc) + goto out; + + lower_dentry = vfs_mkdir(&nop_mnt_idmap, lower_dir, + lower_dentry, mode); + rc = PTR_ERR(lower_dentry); + if (IS_ERR(lower_dentry)) + goto out; + rc = 0; + if (d_unhashed(lower_dentry)) goto out; rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb); if (rc) @@ -526,7 +534,7 @@ out: inode_unlock(lower_dir); if (d_really_is_negative(dentry)) d_drop(dentry); - return rc; + return ERR_PTR(rc); } static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) @@ -1008,14 +1016,6 @@ static int ecryptfs_getattr_link(struct mnt_idmap *idmap, return rc; } -static int ecryptfs_do_getattr(const struct path *path, struct kstat *stat, - u32 request_mask, unsigned int flags) -{ - if (flags & AT_GETATTR_NOSEC) - return vfs_getattr_nosec(path, stat, request_mask, flags); - return vfs_getattr(path, stat, request_mask, flags); -} - static int ecryptfs_getattr(struct mnt_idmap *idmap, const struct path *path, struct kstat *stat, u32 request_mask, unsigned int flags) @@ -1024,8 +1024,8 @@ static int ecryptfs_getattr(struct mnt_idmap *idmap, struct kstat lower_stat; int rc; - rc = ecryptfs_do_getattr(ecryptfs_dentry_to_lower_path(dentry), - &lower_stat, request_mask, flags); + rc = vfs_getattr_nosec(ecryptfs_dentry_to_lower_path(dentry), + &lower_stat, request_mask, flags); if (!rc) { fsstack_copy_attr_all(d_inode(dentry), ecryptfs_inode_to_lower(d_inode(dentry))); diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 3fe41964c0d8..7f9f68c00ef6 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -300,9 +300,11 @@ write_tag_66_packet(char *signature, u8 cipher_code, * | Key Identifier Size | 1 or 2 bytes | * | Key Identifier | arbitrary | * | File Encryption Key Size | 1 or 2 bytes | + * | Cipher Code | 1 byte | * | File Encryption Key | arbitrary | + * | Checksum | 2 bytes | */ - data_len = (5 + ECRYPTFS_SIG_SIZE_HEX + crypt_stat->key_size); + data_len = (8 + ECRYPTFS_SIG_SIZE_HEX + crypt_stat->key_size); *packet = kmalloc(data_len, GFP_KERNEL); message = *packet; if (!message) { diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 2dc927ba067f..8dd1d7189c3b 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -15,10 +15,10 @@ #include <linux/module.h> #include <linux/namei.h> #include <linux/skbuff.h> -#include <linux/mount.h> #include <linux/pagemap.h> #include <linux/key.h> -#include <linux/parser.h> +#include <linux/fs_context.h> +#include <linux/fs_parser.h> #include <linux/fs_stack.h> #include <linux/slab.h> #include <linux/magic.h> @@ -153,32 +153,30 @@ void ecryptfs_put_lower_file(struct inode *inode) } } -enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig, - ecryptfs_opt_cipher, ecryptfs_opt_ecryptfs_cipher, - ecryptfs_opt_ecryptfs_key_bytes, - ecryptfs_opt_passthrough, ecryptfs_opt_xattr_metadata, - ecryptfs_opt_encrypted_view, ecryptfs_opt_fnek_sig, - ecryptfs_opt_fn_cipher, ecryptfs_opt_fn_cipher_key_bytes, - ecryptfs_opt_unlink_sigs, ecryptfs_opt_mount_auth_tok_only, - ecryptfs_opt_check_dev_ruid, - ecryptfs_opt_err }; - -static const match_table_t tokens = { - {ecryptfs_opt_sig, "sig=%s"}, - {ecryptfs_opt_ecryptfs_sig, "ecryptfs_sig=%s"}, - {ecryptfs_opt_cipher, "cipher=%s"}, - {ecryptfs_opt_ecryptfs_cipher, "ecryptfs_cipher=%s"}, - {ecryptfs_opt_ecryptfs_key_bytes, "ecryptfs_key_bytes=%u"}, - {ecryptfs_opt_passthrough, "ecryptfs_passthrough"}, - {ecryptfs_opt_xattr_metadata, "ecryptfs_xattr_metadata"}, - {ecryptfs_opt_encrypted_view, "ecryptfs_encrypted_view"}, - {ecryptfs_opt_fnek_sig, "ecryptfs_fnek_sig=%s"}, - {ecryptfs_opt_fn_cipher, "ecryptfs_fn_cipher=%s"}, - {ecryptfs_opt_fn_cipher_key_bytes, "ecryptfs_fn_key_bytes=%u"}, - {ecryptfs_opt_unlink_sigs, "ecryptfs_unlink_sigs"}, - {ecryptfs_opt_mount_auth_tok_only, "ecryptfs_mount_auth_tok_only"}, - {ecryptfs_opt_check_dev_ruid, "ecryptfs_check_dev_ruid"}, - {ecryptfs_opt_err, NULL} +enum { + Opt_sig, Opt_ecryptfs_sig, Opt_cipher, Opt_ecryptfs_cipher, + Opt_ecryptfs_key_bytes, Opt_passthrough, Opt_xattr_metadata, + Opt_encrypted_view, Opt_fnek_sig, Opt_fn_cipher, + Opt_fn_cipher_key_bytes, Opt_unlink_sigs, Opt_mount_auth_tok_only, + Opt_check_dev_ruid +}; + +static const struct fs_parameter_spec ecryptfs_fs_param_spec[] = { + fsparam_string ("sig", Opt_sig), + fsparam_string ("ecryptfs_sig", Opt_ecryptfs_sig), + fsparam_string ("cipher", Opt_cipher), + fsparam_string ("ecryptfs_cipher", Opt_ecryptfs_cipher), + fsparam_u32 ("ecryptfs_key_bytes", Opt_ecryptfs_key_bytes), + fsparam_flag ("ecryptfs_passthrough", Opt_passthrough), + fsparam_flag ("ecryptfs_xattr_metadata", Opt_xattr_metadata), + fsparam_flag ("ecryptfs_encrypted_view", Opt_encrypted_view), + fsparam_string ("ecryptfs_fnek_sig", Opt_fnek_sig), + fsparam_string ("ecryptfs_fn_cipher", Opt_fn_cipher), + fsparam_u32 ("ecryptfs_fn_key_bytes", Opt_fn_cipher_key_bytes), + fsparam_flag ("ecryptfs_unlink_sigs", Opt_unlink_sigs), + fsparam_flag ("ecryptfs_mount_auth_tok_only", Opt_mount_auth_tok_only), + fsparam_flag ("ecryptfs_check_dev_ruid", Opt_check_dev_ruid), + {} }; static int ecryptfs_init_global_auth_toks( @@ -219,19 +217,20 @@ static void ecryptfs_init_mount_crypt_stat( mount_crypt_stat->flags |= ECRYPTFS_MOUNT_CRYPT_STAT_INITIALIZED; } +struct ecryptfs_fs_context { + /* Mount option status trackers */ + bool check_ruid; + bool sig_set; + bool cipher_name_set; + bool cipher_key_bytes_set; + bool fn_cipher_name_set; + bool fn_cipher_key_bytes_set; +}; + /** - * ecryptfs_parse_options - * @sbi: The ecryptfs super block - * @options: The options passed to the kernel - * @check_ruid: set to 1 if device uid should be checked against the ruid - * - * Parse mount options: - * debug=N - ecryptfs_verbosity level for debug output - * sig=XXX - description(signature) of the key to use - * - * Returns the dentry object of the lower-level (lower/interposed) - * directory; We want to mount our stackable file system on top of - * that lower directory. + * ecryptfs_parse_param + * @fc: The ecryptfs filesystem context + * @param: The mount parameter to parse * * The signature of the key to use must be the description of a key * already in the keyring. Mounting will fail if the key can not be @@ -239,157 +238,118 @@ 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, - uid_t *check_ruid) +static int ecryptfs_parse_param( + struct fs_context *fc, + struct fs_parameter *param) { - char *p; - int rc = 0; - int sig_set = 0; - int cipher_name_set = 0; - int fn_cipher_name_set = 0; - int cipher_key_bytes; - int cipher_key_bytes_set = 0; - int fn_cipher_key_bytes; - int fn_cipher_key_bytes_set = 0; + int rc; + int opt; + struct fs_parse_result result; + struct ecryptfs_fs_context *ctx = fc->fs_private; + struct ecryptfs_sb_info *sbi = fc->s_fs_info; struct ecryptfs_mount_crypt_stat *mount_crypt_stat = &sbi->mount_crypt_stat; - substring_t args[MAX_OPT_ARGS]; - int token; - char *sig_src; - char *cipher_name_dst; - char *cipher_name_src; - char *fn_cipher_name_dst; - char *fn_cipher_name_src; - char *fnek_dst; - char *fnek_src; - char *cipher_key_bytes_src; - char *fn_cipher_key_bytes_src; - u8 cipher_code; - *check_ruid = 0; + opt = fs_parse(fc, ecryptfs_fs_param_spec, param, &result); + if (opt < 0) + return opt; - if (!options) { - rc = -EINVAL; - goto out; - } - ecryptfs_init_mount_crypt_stat(mount_crypt_stat); - while ((p = strsep(&options, ",")) != NULL) { - if (!*p) - continue; - token = match_token(p, tokens, args); - switch (token) { - case ecryptfs_opt_sig: - case ecryptfs_opt_ecryptfs_sig: - sig_src = args[0].from; - rc = ecryptfs_add_global_auth_tok(mount_crypt_stat, - sig_src, 0); - if (rc) { - printk(KERN_ERR "Error attempting to register " - "global sig; rc = [%d]\n", rc); - goto out; - } - sig_set = 1; - break; - case ecryptfs_opt_cipher: - case ecryptfs_opt_ecryptfs_cipher: - cipher_name_src = args[0].from; - cipher_name_dst = - mount_crypt_stat-> - global_default_cipher_name; - strncpy(cipher_name_dst, cipher_name_src, - ECRYPTFS_MAX_CIPHER_NAME_SIZE); - cipher_name_dst[ECRYPTFS_MAX_CIPHER_NAME_SIZE] = '\0'; - cipher_name_set = 1; - break; - case ecryptfs_opt_ecryptfs_key_bytes: - cipher_key_bytes_src = args[0].from; - cipher_key_bytes = - (int)simple_strtol(cipher_key_bytes_src, - &cipher_key_bytes_src, 0); - mount_crypt_stat->global_default_cipher_key_size = - cipher_key_bytes; - cipher_key_bytes_set = 1; - break; - case ecryptfs_opt_passthrough: - mount_crypt_stat->flags |= - ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED; - break; - case ecryptfs_opt_xattr_metadata: - mount_crypt_stat->flags |= - ECRYPTFS_XATTR_METADATA_ENABLED; - break; - case ecryptfs_opt_encrypted_view: - mount_crypt_stat->flags |= - ECRYPTFS_XATTR_METADATA_ENABLED; - mount_crypt_stat->flags |= - ECRYPTFS_ENCRYPTED_VIEW_ENABLED; - break; - case ecryptfs_opt_fnek_sig: - fnek_src = args[0].from; - fnek_dst = - mount_crypt_stat->global_default_fnek_sig; - strncpy(fnek_dst, fnek_src, ECRYPTFS_SIG_SIZE_HEX); - mount_crypt_stat->global_default_fnek_sig[ - ECRYPTFS_SIG_SIZE_HEX] = '\0'; - rc = ecryptfs_add_global_auth_tok( - mount_crypt_stat, - mount_crypt_stat->global_default_fnek_sig, - ECRYPTFS_AUTH_TOK_FNEK); - if (rc) { - printk(KERN_ERR "Error attempting to register " - "global fnek sig [%s]; rc = [%d]\n", - mount_crypt_stat->global_default_fnek_sig, - rc); - goto out; - } - mount_crypt_stat->flags |= - (ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES - | ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK); - break; - case ecryptfs_opt_fn_cipher: - fn_cipher_name_src = args[0].from; - fn_cipher_name_dst = - mount_crypt_stat->global_default_fn_cipher_name; - strncpy(fn_cipher_name_dst, fn_cipher_name_src, - ECRYPTFS_MAX_CIPHER_NAME_SIZE); - mount_crypt_stat->global_default_fn_cipher_name[ - ECRYPTFS_MAX_CIPHER_NAME_SIZE] = '\0'; - fn_cipher_name_set = 1; - break; - case ecryptfs_opt_fn_cipher_key_bytes: - fn_cipher_key_bytes_src = args[0].from; - fn_cipher_key_bytes = - (int)simple_strtol(fn_cipher_key_bytes_src, - &fn_cipher_key_bytes_src, 0); - mount_crypt_stat->global_default_fn_cipher_key_bytes = - fn_cipher_key_bytes; - fn_cipher_key_bytes_set = 1; - break; - case ecryptfs_opt_unlink_sigs: - mount_crypt_stat->flags |= ECRYPTFS_UNLINK_SIGS; - break; - case ecryptfs_opt_mount_auth_tok_only: - mount_crypt_stat->flags |= - ECRYPTFS_GLOBAL_MOUNT_AUTH_TOK_ONLY; - break; - case ecryptfs_opt_check_dev_ruid: - *check_ruid = 1; - break; - case ecryptfs_opt_err: - default: - printk(KERN_WARNING - "%s: eCryptfs: unrecognized option [%s]\n", - __func__, p); + switch (opt) { + case Opt_sig: + case Opt_ecryptfs_sig: + rc = ecryptfs_add_global_auth_tok(mount_crypt_stat, + param->string, 0); + if (rc) { + printk(KERN_ERR "Error attempting to register " + "global sig; rc = [%d]\n", rc); + return rc; + } + ctx->sig_set = 1; + break; + case Opt_cipher: + case Opt_ecryptfs_cipher: + strscpy(mount_crypt_stat->global_default_cipher_name, + param->string); + ctx->cipher_name_set = 1; + break; + case Opt_ecryptfs_key_bytes: + mount_crypt_stat->global_default_cipher_key_size = + result.uint_32; + ctx->cipher_key_bytes_set = 1; + break; + case Opt_passthrough: + mount_crypt_stat->flags |= + ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED; + break; + case Opt_xattr_metadata: + mount_crypt_stat->flags |= ECRYPTFS_XATTR_METADATA_ENABLED; + break; + case Opt_encrypted_view: + mount_crypt_stat->flags |= ECRYPTFS_XATTR_METADATA_ENABLED; + mount_crypt_stat->flags |= ECRYPTFS_ENCRYPTED_VIEW_ENABLED; + break; + case Opt_fnek_sig: + strscpy(mount_crypt_stat->global_default_fnek_sig, + param->string); + rc = ecryptfs_add_global_auth_tok( + mount_crypt_stat, + mount_crypt_stat->global_default_fnek_sig, + ECRYPTFS_AUTH_TOK_FNEK); + if (rc) { + printk(KERN_ERR "Error attempting to register " + "global fnek sig [%s]; rc = [%d]\n", + mount_crypt_stat->global_default_fnek_sig, rc); + return rc; } + mount_crypt_stat->flags |= + (ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES + | ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK); + break; + case Opt_fn_cipher: + strscpy(mount_crypt_stat->global_default_fn_cipher_name, + param->string); + ctx->fn_cipher_name_set = 1; + break; + case Opt_fn_cipher_key_bytes: + mount_crypt_stat->global_default_fn_cipher_key_bytes = + result.uint_32; + ctx->fn_cipher_key_bytes_set = 1; + break; + case Opt_unlink_sigs: + mount_crypt_stat->flags |= ECRYPTFS_UNLINK_SIGS; + break; + case Opt_mount_auth_tok_only: + mount_crypt_stat->flags |= ECRYPTFS_GLOBAL_MOUNT_AUTH_TOK_ONLY; + break; + case Opt_check_dev_ruid: + ctx->check_ruid = 1; + break; + default: + return -EINVAL; } - if (!sig_set) { + + return 0; +} + +static int ecryptfs_validate_options(struct fs_context *fc) +{ + int rc = 0; + u8 cipher_code; + struct ecryptfs_fs_context *ctx = fc->fs_private; + struct ecryptfs_sb_info *sbi = fc->s_fs_info; + struct ecryptfs_mount_crypt_stat *mount_crypt_stat; + + + mount_crypt_stat = &sbi->mount_crypt_stat; + + if (!ctx->sig_set) { rc = -EINVAL; ecryptfs_printk(KERN_ERR, "You must supply at least one valid " "auth tok signature as a mount " "parameter; see the eCryptfs README\n"); goto out; } - if (!cipher_name_set) { + if (!ctx->cipher_name_set) { int cipher_name_len = strlen(ECRYPTFS_DEFAULT_CIPHER); BUG_ON(cipher_name_len > ECRYPTFS_MAX_CIPHER_NAME_SIZE); @@ -397,13 +357,13 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options, ECRYPTFS_DEFAULT_CIPHER); } if ((mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) - && !fn_cipher_name_set) + && !ctx->fn_cipher_name_set) strcpy(mount_crypt_stat->global_default_fn_cipher_name, mount_crypt_stat->global_default_cipher_name); - if (!cipher_key_bytes_set) + if (!ctx->cipher_key_bytes_set) mount_crypt_stat->global_default_cipher_key_size = 0; if ((mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) - && !fn_cipher_key_bytes_set) + && !ctx->fn_cipher_key_bytes_set) mount_crypt_stat->global_default_fn_cipher_key_bytes = mount_crypt_stat->global_default_cipher_key_size; @@ -467,45 +427,35 @@ struct kmem_cache *ecryptfs_sb_info_cache; static struct file_system_type ecryptfs_fs_type; /* - * ecryptfs_mount - * @fs_type: The filesystem type that the superblock should belong to - * @flags: The flags associated with the mount - * @dev_name: The path to mount over - * @raw_data: The options passed into the kernel + * ecryptfs_get_tree + * @fc: The filesystem context */ -static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags, - const char *dev_name, void *raw_data) +static int ecryptfs_get_tree(struct fs_context *fc) { struct super_block *s; - struct ecryptfs_sb_info *sbi; + struct ecryptfs_fs_context *ctx = fc->fs_private; + struct ecryptfs_sb_info *sbi = fc->s_fs_info; struct ecryptfs_mount_crypt_stat *mount_crypt_stat; struct ecryptfs_dentry_info *root_info; const char *err = "Getting sb failed"; struct inode *inode; struct path path; - uid_t check_ruid; int rc; - sbi = kmem_cache_zalloc(ecryptfs_sb_info_cache, GFP_KERNEL); - if (!sbi) { - rc = -ENOMEM; - goto out; - } - - if (!dev_name) { + if (!fc->source) { rc = -EINVAL; err = "Device name cannot be null"; goto out; } - rc = ecryptfs_parse_options(sbi, raw_data, &check_ruid); + mount_crypt_stat = &sbi->mount_crypt_stat; + rc = ecryptfs_validate_options(fc); if (rc) { - err = "Error parsing options"; + err = "Error validating options"; goto out; } - mount_crypt_stat = &sbi->mount_crypt_stat; - s = sget(fs_type, NULL, set_anon_super, flags, NULL); + s = sget_fc(fc, NULL, set_anon_super_fc); if (IS_ERR(s)) { rc = PTR_ERR(s); goto out; @@ -524,7 +474,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags s->s_d_op = &ecryptfs_dops; err = "Reading sb failed"; - rc = kern_path(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path); + rc = kern_path(fc->source, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path); if (rc) { ecryptfs_printk(KERN_WARNING, "kern_path() failed\n"); goto out1; @@ -543,7 +493,8 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags goto out_free; } - if (check_ruid && !uid_eq(d_inode(path.dentry)->i_uid, current_uid())) { + if (ctx->check_ruid && + !uid_eq(d_inode(path.dentry)->i_uid, current_uid())) { rc = -EPERM; printk(KERN_ERR "Mount of device (uid: %d) not owned by " "requested user (uid: %d)\n", @@ -558,7 +509,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags * Set the POSIX ACL flag based on whether they're enabled in the lower * mount. */ - s->s_flags = flags & ~SB_POSIXACL; + s->s_flags = fc->sb_flags & ~SB_POSIXACL; s->s_flags |= path.dentry->d_sb->s_flags & SB_POSIXACL; /** @@ -601,19 +552,19 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags root_info->lower_path = path; s->s_flags |= SB_ACTIVE; - return dget(s->s_root); + fc->root = dget(s->s_root); + return 0; out_free: path_put(&path); out1: deactivate_locked_super(s); out: - if (sbi) { + if (sbi) ecryptfs_destroy_mount_crypt_stat(&sbi->mount_crypt_stat); - kmem_cache_free(ecryptfs_sb_info_cache, sbi); - } + printk(KERN_ERR "%s; rc = [%d]\n", err, rc); - return ERR_PTR(rc); + return rc; } /** @@ -632,10 +583,54 @@ static void ecryptfs_kill_block_super(struct super_block *sb) kmem_cache_free(ecryptfs_sb_info_cache, sb_info); } +static void ecryptfs_free_fc(struct fs_context *fc) +{ + struct ecryptfs_fs_context *ctx = fc->fs_private; + struct ecryptfs_sb_info *sbi = fc->s_fs_info; + + kfree(ctx); + + if (sbi) { + ecryptfs_destroy_mount_crypt_stat(&sbi->mount_crypt_stat); + kmem_cache_free(ecryptfs_sb_info_cache, sbi); + } +} + +static const struct fs_context_operations ecryptfs_context_ops = { + .free = ecryptfs_free_fc, + .parse_param = ecryptfs_parse_param, + .get_tree = ecryptfs_get_tree, + .reconfigure = NULL, +}; + +static int ecryptfs_init_fs_context(struct fs_context *fc) +{ + struct ecryptfs_fs_context *ctx; + struct ecryptfs_sb_info *sbi = NULL; + + ctx = kzalloc(sizeof(struct ecryptfs_fs_context), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + sbi = kmem_cache_zalloc(ecryptfs_sb_info_cache, GFP_KERNEL); + if (!sbi) { + kfree(ctx); + ctx = NULL; + return -ENOMEM; + } + + ecryptfs_init_mount_crypt_stat(&sbi->mount_crypt_stat); + + fc->fs_private = ctx; + fc->s_fs_info = sbi; + fc->ops = &ecryptfs_context_ops; + return 0; +} + static struct file_system_type ecryptfs_fs_type = { .owner = THIS_MODULE, .name = "ecryptfs", - .mount = ecryptfs_mount, + .init_fs_context = ecryptfs_init_fs_context, + .parameters = ecryptfs_fs_param_spec, .kill_sb = ecryptfs_kill_block_super, .fs_flags = 0 }; diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index e2483acc4366..60f0ac8744b5 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -19,51 +19,33 @@ #include <linux/scatterlist.h> #include <linux/slab.h> #include <linux/xattr.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include "ecryptfs_kernel.h" /* - * ecryptfs_get_locked_page - * - * Get one page from cache or lower f/s, return error otherwise. - * - * Returns locked and up-to-date page (if ok), with increased - * refcnt. - */ -struct page *ecryptfs_get_locked_page(struct inode *inode, loff_t index) -{ - struct page *page = read_mapping_page(inode->i_mapping, index, NULL); - if (!IS_ERR(page)) - lock_page(page); - return page; -} - -/** - * ecryptfs_writepage - * @page: Page that is locked before this call is made - * @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 * the lower filesystem. In OpenPGP-compatible mode, we operate on * 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; - - rc = ecryptfs_encrypt_page(page); - if (rc) { - ecryptfs_printk(KERN_WARNING, "Error encrypting " - "page (upper index [0x%.16lx])\n", page->index); - ClearPageUptodate(page); - goto out; + struct folio *folio = NULL; + int error; + + while ((folio = writeback_iter(mapping, wbc, folio, &error))) { + error = ecryptfs_encrypt_page(folio); + if (error) { + ecryptfs_printk(KERN_WARNING, + "Error encrypting folio (index [0x%.16lx])\n", + folio->index); + folio_clear_uptodate(folio); + mapping_set_error(mapping, error); + } + folio_unlock(folio); } - SetPageUptodate(page); -out: - unlock_page(page); - return rc; + + return error; } 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 - * @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 * the header. This is locked. * @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. */ 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) { loff_t extent_num_in_page = 0; @@ -115,9 +97,9 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page, int rc = 0; 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) - + extent_num_in_page); + + extent_num_in_page; size_t num_header_extents_at_front = (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 */ char *page_virt; - page_virt = kmap_local_page(page); + page_virt = kmap_local_folio(folio, 0); memset(page_virt, 0, PAGE_SIZE); /* TODO: Support more than one header extent */ if (view_extent_num == 0) { size_t written; rc = ecryptfs_read_xattr_region( - page_virt, page->mapping->host); + page_virt, folio->mapping->host); strip_xattr_flag(page_virt + 16, crypt_stat); ecryptfs_write_header_metadata(page_virt + 20, crypt_stat, &written); } kunmap_local(page_virt); - flush_dcache_page(page); + flush_dcache_folio(folio); if (rc) { printk(KERN_ERR "%s: Error reading xattr " "region; rc = [%d]\n", __func__, rc); @@ -152,9 +134,9 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page, - crypt_stat->metadata_size); rc = ecryptfs_read_lower_page_segment( - page, (lower_offset >> PAGE_SHIFT), + folio, (lower_offset >> PAGE_SHIFT), (lower_offset & ~PAGE_MASK), - crypt_stat->extent_size, page->mapping->host); + crypt_stat->extent_size, folio->mapping->host); if (rc) { printk(KERN_ERR "%s: Error attempting to read " "extent at offset [%lld] in the lower " @@ -180,71 +162,66 @@ out: */ 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 = - &ecryptfs_inode_to_private(page->mapping->host)->crypt_stat; - int rc = 0; + &ecryptfs_inode_to_private(inode)->crypt_stat; + int err = 0; if (!crypt_stat || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { - rc = ecryptfs_read_lower_page_segment(page, page->index, 0, - PAGE_SIZE, - page->mapping->host); + err = ecryptfs_read_lower_page_segment(folio, folio->index, 0, + folio_size(folio), inode); } else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) { if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) { - rc = ecryptfs_copy_up_encrypted_with_header(page, - crypt_stat); - if (rc) { + err = ecryptfs_copy_up_encrypted_with_header(folio, + crypt_stat); + if (err) { printk(KERN_ERR "%s: Error attempting to copy " "the encrypted content from the lower " "file whilst inserting the metadata " - "from the xattr into the header; rc = " - "[%d]\n", __func__, rc); + "from the xattr into the header; err = " + "[%d]\n", __func__, err); goto out; } } else { - rc = ecryptfs_read_lower_page_segment( - page, page->index, 0, PAGE_SIZE, - page->mapping->host); - if (rc) { - printk(KERN_ERR "Error reading page; rc = " - "[%d]\n", rc); + err = ecryptfs_read_lower_page_segment(folio, + folio->index, 0, folio_size(folio), + inode); + if (err) { + printk(KERN_ERR "Error reading page; err = " + "[%d]\n", err); goto out; } } } else { - rc = ecryptfs_decrypt_page(page); - if (rc) { + err = ecryptfs_decrypt_page(folio); + if (err) { ecryptfs_printk(KERN_ERR, "Error decrypting page; " - "rc = [%d]\n", rc); + "err = [%d]\n", err); goto out; } } out: - if (rc) - ClearPageUptodate(page); - else - SetPageUptodate(page); - ecryptfs_printk(KERN_DEBUG, "Unlocking page with index = [0x%.16lx]\n", - page->index); - unlock_page(page); - return rc; + ecryptfs_printk(KERN_DEBUG, "Unlocking folio with index = [0x%.16lx]\n", + folio->index); + folio_end_read(folio, err == 0); + return err; } /* * Called with lower inode mutex held. */ -static int fill_zeros_to_end_of_page(struct page *page, unsigned int to) +static int fill_zeros_to_end_of_page(struct folio *folio, unsigned int to) { - struct inode *inode = page->mapping->host; + struct inode *inode = folio->mapping->host; int end_byte_in_page; - if ((i_size_read(inode) / PAGE_SIZE) != page->index) + if ((i_size_read(inode) / PAGE_SIZE) != folio->index) goto out; end_byte_in_page = i_size_read(inode) % PAGE_SIZE; if (to > end_byte_in_page) end_byte_in_page = to; - zero_user_segment(page, end_byte_in_page, PAGE_SIZE); + folio_zero_segment(folio, end_byte_in_page, PAGE_SIZE); out: return 0; } @@ -255,7 +232,7 @@ out: * @mapping: The eCryptfs object * @pos: The file offset at which to start writing * @len: Length of the write - * @pagep: Pointer to return the page + * @foliop: Pointer to return the folio * @fsdata: Pointer to return fs data (unused) * * This function must zero any hole we create @@ -265,38 +242,39 @@ out: static int ecryptfs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, - struct page **pagep, void **fsdata) + struct folio **foliop, void **fsdata) { pgoff_t index = pos >> PAGE_SHIFT; - struct page *page; + struct folio *folio; loff_t prev_page_end_size; int rc = 0; - page = grab_cache_page_write_begin(mapping, index); - if (!page) - return -ENOMEM; - *pagep = page; + folio = __filemap_get_folio(mapping, index, FGP_WRITEBEGIN, + mapping_gfp_mask(mapping)); + if (IS_ERR(folio)) + return PTR_ERR(folio); + *foliop = folio; prev_page_end_size = ((loff_t)index << PAGE_SHIFT); - if (!PageUptodate(page)) { + if (!folio_test_uptodate(folio)) { struct ecryptfs_crypt_stat *crypt_stat = &ecryptfs_inode_to_private(mapping->host)->crypt_stat; if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { rc = ecryptfs_read_lower_page_segment( - page, index, 0, PAGE_SIZE, mapping->host); + folio, index, 0, PAGE_SIZE, mapping->host); if (rc) { printk(KERN_ERR "%s: Error attempting to read " "lower page segment; rc = [%d]\n", __func__, rc); - ClearPageUptodate(page); + folio_clear_uptodate(folio); goto out; } else - SetPageUptodate(page); + folio_mark_uptodate(folio); } else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) { if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) { rc = ecryptfs_copy_up_encrypted_with_header( - page, crypt_stat); + folio, crypt_stat); if (rc) { printk(KERN_ERR "%s: Error attempting " "to copy the encrypted content " @@ -304,46 +282,46 @@ static int ecryptfs_write_begin(struct file *file, "inserting the metadata from " "the xattr into the header; rc " "= [%d]\n", __func__, rc); - ClearPageUptodate(page); + folio_clear_uptodate(folio); goto out; } - SetPageUptodate(page); + folio_mark_uptodate(folio); } else { rc = ecryptfs_read_lower_page_segment( - page, index, 0, PAGE_SIZE, + folio, index, 0, PAGE_SIZE, mapping->host); if (rc) { printk(KERN_ERR "%s: Error reading " "page; rc = [%d]\n", __func__, rc); - ClearPageUptodate(page); + folio_clear_uptodate(folio); goto out; } - SetPageUptodate(page); + folio_mark_uptodate(folio); } } else { if (prev_page_end_size - >= i_size_read(page->mapping->host)) { - zero_user(page, 0, PAGE_SIZE); - SetPageUptodate(page); + >= i_size_read(mapping->host)) { + folio_zero_range(folio, 0, PAGE_SIZE); + folio_mark_uptodate(folio); } else if (len < PAGE_SIZE) { - rc = ecryptfs_decrypt_page(page); + rc = ecryptfs_decrypt_page(folio); if (rc) { printk(KERN_ERR "%s: Error decrypting " "page at index [%ld]; " "rc = [%d]\n", - __func__, page->index, rc); - ClearPageUptodate(page); + __func__, folio->index, rc); + folio_clear_uptodate(folio); goto out; } - SetPageUptodate(page); + folio_mark_uptodate(folio); } } } /* If creating a page or more of holes, zero them out via truncate. * Note, this will increase i_size. */ if (index != 0) { - if (prev_page_end_size > i_size_read(page->mapping->host)) { + if (prev_page_end_size > i_size_read(mapping->host)) { rc = ecryptfs_truncate(file->f_path.dentry, prev_page_end_size); if (rc) { @@ -359,12 +337,11 @@ static int ecryptfs_write_begin(struct file *file, * of page? Zero it out. */ if ((i_size_read(mapping->host) == prev_page_end_size) && (pos != 0)) - zero_user(page, 0, PAGE_SIZE); + folio_zero_range(folio, 0, PAGE_SIZE); out: if (unlikely(rc)) { - unlock_page(page); - put_page(page); - *pagep = NULL; + folio_unlock(folio); + folio_put(folio); } return rc; } @@ -457,13 +434,13 @@ int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode) * @pos: The file position * @len: The length of the data (unused) * @copied: The amount of data copied - * @page: The eCryptfs page + * @folio: The eCryptfs folio * @fsdata: The fsdata (unused) */ static int ecryptfs_write_end(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned copied, - struct page *page, void *fsdata) + struct folio *folio, void *fsdata) { pgoff_t index = pos >> PAGE_SHIFT; unsigned from = pos & (PAGE_SIZE - 1); @@ -476,8 +453,8 @@ static int ecryptfs_write_end(struct file *file, ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page" "(page w/ index = [0x%.16lx], to = [%d])\n", index, to); if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { - rc = ecryptfs_write_lower_page_segment(ecryptfs_inode, page, 0, - to); + rc = ecryptfs_write_lower_page_segment(ecryptfs_inode, + folio, 0, to); if (!rc) { rc = copied; fsstack_copy_inode_size(ecryptfs_inode, @@ -485,21 +462,21 @@ static int ecryptfs_write_end(struct file *file, } goto out; } - if (!PageUptodate(page)) { + if (!folio_test_uptodate(folio)) { if (copied < PAGE_SIZE) { rc = 0; goto out; } - SetPageUptodate(page); + folio_mark_uptodate(folio); } /* Fills in zeros if 'to' goes beyond inode size */ - rc = fill_zeros_to_end_of_page(page, to); + rc = fill_zeros_to_end_of_page(folio, to); if (rc) { ecryptfs_printk(KERN_WARNING, "Error attempting to fill " "zeros in page with index = [0x%.16lx]\n", index); goto out; } - rc = ecryptfs_encrypt_page(page); + rc = ecryptfs_encrypt_page(folio); if (rc) { ecryptfs_printk(KERN_WARNING, "Error encrypting page (upper " "index [0x%.16lx])\n", index); @@ -518,8 +495,8 @@ static int ecryptfs_write_end(struct file *file, else rc = copied; out: - unlock_page(page); - put_page(page); + folio_unlock(folio); + folio_put(folio); return rc; } @@ -548,9 +525,10 @@ const struct address_space_operations ecryptfs_aops = { .dirty_folio = block_dirty_folio, .invalidate_folio = block_invalidate_folio, #endif - .writepage = ecryptfs_writepage, + .writepages = ecryptfs_writepages, .read_folio = ecryptfs_read_folio, .write_begin = ecryptfs_write_begin, .write_end = ecryptfs_write_end, + .migrate_folio = filemap_migrate_folio, .bmap = ecryptfs_bmap, }; diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c index 3458f153a588..b3b451c2b941 100644 --- a/fs/ecryptfs/read_write.c +++ b/fs/ecryptfs/read_write.c @@ -41,30 +41,29 @@ int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data, /** * ecryptfs_write_lower_page_segment * @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 - * @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 - * @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 * * Determines the byte offset in the file for the given page and * offset within the page, maps the page, and makes the call to write - * the contents of @page_for_lower to the lower inode. + * the contents of @folio_for_lower to the lower inode. * * Returns zero on success; non-zero otherwise */ int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode, - struct page *page_for_lower, + struct folio *folio_for_lower, size_t offset_in_page, size_t size) { char *virt; loff_t offset; int rc; - offset = ((((loff_t)page_for_lower->index) << PAGE_SHIFT) - + offset_in_page); - virt = kmap_local_page(page_for_lower); + offset = (loff_t)folio_for_lower->index * PAGE_SIZE + offset_in_page; + virt = kmap_local_folio(folio_for_lower, 0); rc = ecryptfs_write_lower(ecryptfs_inode, virt, offset, size); if (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, size_t size) { - struct page *ecryptfs_page; struct ecryptfs_crypt_stat *crypt_stat; char *ecryptfs_page_virt; loff_t ecryptfs_file_size = i_size_read(ecryptfs_inode); @@ -111,6 +109,7 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset, else pos = offset; while (pos < (offset + size)) { + struct folio *ecryptfs_folio; pgoff_t ecryptfs_page_idx = (pos >> PAGE_SHIFT); size_t start_offset_in_page = (pos & ~PAGE_MASK); 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) num_bytes = total_remaining_zeros; } - ecryptfs_page = ecryptfs_get_locked_page(ecryptfs_inode, - ecryptfs_page_idx); - if (IS_ERR(ecryptfs_page)) { - rc = PTR_ERR(ecryptfs_page); + ecryptfs_folio = read_mapping_folio(ecryptfs_inode->i_mapping, + ecryptfs_page_idx, NULL); + if (IS_ERR(ecryptfs_folio)) { + rc = PTR_ERR(ecryptfs_folio); 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_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 @@ -164,17 +164,17 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset, data_offset += num_bytes; } kunmap_local(ecryptfs_page_virt); - flush_dcache_page(ecryptfs_page); - SetPageUptodate(ecryptfs_page); - unlock_page(ecryptfs_page); + flush_dcache_folio(ecryptfs_folio); + folio_mark_uptodate(ecryptfs_folio); + folio_unlock(ecryptfs_folio); if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) - rc = ecryptfs_encrypt_page(ecryptfs_page); + rc = ecryptfs_encrypt_page(ecryptfs_folio); else rc = ecryptfs_write_lower_page_segment(ecryptfs_inode, - ecryptfs_page, + ecryptfs_folio, start_offset_in_page, data_offset); - put_page(ecryptfs_page); + folio_put(ecryptfs_folio); if (rc) { printk(KERN_ERR "%s: Error encrypting " "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 - * @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 * @page_index: Page index in @page_for_ecryptfs from which to start * writing @@ -243,7 +243,7 @@ int ecryptfs_read_lower(char *data, loff_t offset, size_t size, * * 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, size_t offset_in_page, size_t size, struct inode *ecryptfs_inode) @@ -252,12 +252,12 @@ int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs, loff_t offset; int rc; - offset = ((((loff_t)page_index) << PAGE_SHIFT) + offset_in_page); - virt = kmap_local_page(page_for_ecryptfs); + offset = (loff_t)page_index * PAGE_SIZE + offset_in_page; + virt = kmap_local_folio(folio_for_ecryptfs, 0); rc = ecryptfs_read_lower(virt, offset, size, ecryptfs_inode); if (rc > 0) rc = 0; kunmap_local(virt); - flush_dcache_page(page_for_ecryptfs); + flush_dcache_folio(folio_for_ecryptfs); return rc; } diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c index 0b1c878317ab..e7b7f426fecf 100644 --- a/fs/ecryptfs/super.c +++ b/fs/ecryptfs/super.c @@ -172,7 +172,6 @@ const struct super_operations ecryptfs_sops = { .destroy_inode = ecryptfs_destroy_inode, .free_inode = ecryptfs_free_inode, .statfs = ecryptfs_statfs, - .remount_fs = NULL, .evict_inode = ecryptfs_evict_inode, .show_options = ecryptfs_show_options }; |