Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 
0003 #include <linux/quotaops.h>
0004 #include <linux/uuid.h>
0005 
0006 #include "ext4.h"
0007 #include "xattr.h"
0008 #include "ext4_jbd2.h"
0009 
0010 static void ext4_fname_from_fscrypt_name(struct ext4_filename *dst,
0011                      const struct fscrypt_name *src)
0012 {
0013     memset(dst, 0, sizeof(*dst));
0014 
0015     dst->usr_fname = src->usr_fname;
0016     dst->disk_name = src->disk_name;
0017     dst->hinfo.hash = src->hash;
0018     dst->hinfo.minor_hash = src->minor_hash;
0019     dst->crypto_buf = src->crypto_buf;
0020 }
0021 
0022 int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname,
0023                   int lookup, struct ext4_filename *fname)
0024 {
0025     struct fscrypt_name name;
0026     int err;
0027 
0028     err = fscrypt_setup_filename(dir, iname, lookup, &name);
0029     if (err)
0030         return err;
0031 
0032     ext4_fname_from_fscrypt_name(fname, &name);
0033 
0034 #if IS_ENABLED(CONFIG_UNICODE)
0035     err = ext4_fname_setup_ci_filename(dir, iname, fname);
0036 #endif
0037     return err;
0038 }
0039 
0040 int ext4_fname_prepare_lookup(struct inode *dir, struct dentry *dentry,
0041                   struct ext4_filename *fname)
0042 {
0043     struct fscrypt_name name;
0044     int err;
0045 
0046     err = fscrypt_prepare_lookup(dir, dentry, &name);
0047     if (err)
0048         return err;
0049 
0050     ext4_fname_from_fscrypt_name(fname, &name);
0051 
0052 #if IS_ENABLED(CONFIG_UNICODE)
0053     err = ext4_fname_setup_ci_filename(dir, &dentry->d_name, fname);
0054 #endif
0055     return err;
0056 }
0057 
0058 void ext4_fname_free_filename(struct ext4_filename *fname)
0059 {
0060     struct fscrypt_name name;
0061 
0062     name.crypto_buf = fname->crypto_buf;
0063     fscrypt_free_filename(&name);
0064 
0065     fname->crypto_buf.name = NULL;
0066     fname->usr_fname = NULL;
0067     fname->disk_name.name = NULL;
0068 
0069 #if IS_ENABLED(CONFIG_UNICODE)
0070     kfree(fname->cf_name.name);
0071     fname->cf_name.name = NULL;
0072 #endif
0073 }
0074 
0075 static bool uuid_is_zero(__u8 u[16])
0076 {
0077     int i;
0078 
0079     for (i = 0; i < 16; i++)
0080         if (u[i])
0081             return false;
0082     return true;
0083 }
0084 
0085 int ext4_ioctl_get_encryption_pwsalt(struct file *filp, void __user *arg)
0086 {
0087     struct super_block *sb = file_inode(filp)->i_sb;
0088     struct ext4_sb_info *sbi = EXT4_SB(sb);
0089     int err, err2;
0090     handle_t *handle;
0091 
0092     if (!ext4_has_feature_encrypt(sb))
0093         return -EOPNOTSUPP;
0094 
0095     if (uuid_is_zero(sbi->s_es->s_encrypt_pw_salt)) {
0096         err = mnt_want_write_file(filp);
0097         if (err)
0098             return err;
0099         handle = ext4_journal_start_sb(sb, EXT4_HT_MISC, 1);
0100         if (IS_ERR(handle)) {
0101             err = PTR_ERR(handle);
0102             goto pwsalt_err_exit;
0103         }
0104         err = ext4_journal_get_write_access(handle, sb, sbi->s_sbh,
0105                             EXT4_JTR_NONE);
0106         if (err)
0107             goto pwsalt_err_journal;
0108         lock_buffer(sbi->s_sbh);
0109         generate_random_uuid(sbi->s_es->s_encrypt_pw_salt);
0110         ext4_superblock_csum_set(sb);
0111         unlock_buffer(sbi->s_sbh);
0112         err = ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
0113 pwsalt_err_journal:
0114         err2 = ext4_journal_stop(handle);
0115         if (err2 && !err)
0116             err = err2;
0117 pwsalt_err_exit:
0118         mnt_drop_write_file(filp);
0119         if (err)
0120             return err;
0121     }
0122 
0123     if (copy_to_user(arg, sbi->s_es->s_encrypt_pw_salt, 16))
0124         return -EFAULT;
0125     return 0;
0126 }
0127 
0128 static int ext4_get_context(struct inode *inode, void *ctx, size_t len)
0129 {
0130     return ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION,
0131                  EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, ctx, len);
0132 }
0133 
0134 static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
0135                             void *fs_data)
0136 {
0137     handle_t *handle = fs_data;
0138     int res, res2, credits, retries = 0;
0139 
0140     /*
0141      * Encrypting the root directory is not allowed because e2fsck expects
0142      * lost+found to exist and be unencrypted, and encrypting the root
0143      * directory would imply encrypting the lost+found directory as well as
0144      * the filename "lost+found" itself.
0145      */
0146     if (inode->i_ino == EXT4_ROOT_INO)
0147         return -EPERM;
0148 
0149     if (WARN_ON_ONCE(IS_DAX(inode) && i_size_read(inode)))
0150         return -EINVAL;
0151 
0152     if (ext4_test_inode_flag(inode, EXT4_INODE_DAX))
0153         return -EOPNOTSUPP;
0154 
0155     res = ext4_convert_inline_data(inode);
0156     if (res)
0157         return res;
0158 
0159     /*
0160      * If a journal handle was specified, then the encryption context is
0161      * being set on a new inode via inheritance and is part of a larger
0162      * transaction to create the inode.  Otherwise the encryption context is
0163      * being set on an existing inode in its own transaction.  Only in the
0164      * latter case should the "retry on ENOSPC" logic be used.
0165      */
0166 
0167     if (handle) {
0168         res = ext4_xattr_set_handle(handle, inode,
0169                         EXT4_XATTR_INDEX_ENCRYPTION,
0170                         EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
0171                         ctx, len, 0);
0172         if (!res) {
0173             ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
0174             ext4_clear_inode_state(inode,
0175                     EXT4_STATE_MAY_INLINE_DATA);
0176             /*
0177              * Update inode->i_flags - S_ENCRYPTED will be enabled,
0178              * S_DAX may be disabled
0179              */
0180             ext4_set_inode_flags(inode, false);
0181         }
0182         return res;
0183     }
0184 
0185     res = dquot_initialize(inode);
0186     if (res)
0187         return res;
0188 retry:
0189     res = ext4_xattr_set_credits(inode, len, false /* is_create */,
0190                      &credits);
0191     if (res)
0192         return res;
0193 
0194     handle = ext4_journal_start(inode, EXT4_HT_MISC, credits);
0195     if (IS_ERR(handle))
0196         return PTR_ERR(handle);
0197 
0198     res = ext4_xattr_set_handle(handle, inode, EXT4_XATTR_INDEX_ENCRYPTION,
0199                     EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
0200                     ctx, len, 0);
0201     if (!res) {
0202         ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
0203         /*
0204          * Update inode->i_flags - S_ENCRYPTED will be enabled,
0205          * S_DAX may be disabled
0206          */
0207         ext4_set_inode_flags(inode, false);
0208         res = ext4_mark_inode_dirty(handle, inode);
0209         if (res)
0210             EXT4_ERROR_INODE(inode, "Failed to mark inode dirty");
0211     }
0212     res2 = ext4_journal_stop(handle);
0213 
0214     if (res == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
0215         goto retry;
0216     if (!res)
0217         res = res2;
0218     return res;
0219 }
0220 
0221 static const union fscrypt_policy *ext4_get_dummy_policy(struct super_block *sb)
0222 {
0223     return EXT4_SB(sb)->s_dummy_enc_policy.policy;
0224 }
0225 
0226 static bool ext4_has_stable_inodes(struct super_block *sb)
0227 {
0228     return ext4_has_feature_stable_inodes(sb);
0229 }
0230 
0231 static void ext4_get_ino_and_lblk_bits(struct super_block *sb,
0232                        int *ino_bits_ret, int *lblk_bits_ret)
0233 {
0234     *ino_bits_ret = 8 * sizeof(EXT4_SB(sb)->s_es->s_inodes_count);
0235     *lblk_bits_ret = 8 * sizeof(ext4_lblk_t);
0236 }
0237 
0238 const struct fscrypt_operations ext4_cryptops = {
0239     .key_prefix     = "ext4:",
0240     .get_context        = ext4_get_context,
0241     .set_context        = ext4_set_context,
0242     .get_dummy_policy   = ext4_get_dummy_policy,
0243     .empty_dir      = ext4_empty_dir,
0244     .has_stable_inodes  = ext4_has_stable_inodes,
0245     .get_ino_and_lblk_bits  = ext4_get_ino_and_lblk_bits,
0246 };