fscrypt updates for 5.10

This release, we rework the implementation of creating new encrypted
 files in order to fix some deadlocks and prepare for adding fscrypt
 support to CephFS, which Jeff Layton is working on.
 
 We also export a symbol in preparation for the above-mentioned CephFS
 support and also for ext4/f2fs encrypt+casefold support.
 
 Finally, there are a few other small cleanups.
 
 As usual, all these patches have been in linux-next with no reported
 issues, and I've tested them with xfstests.
 -----BEGIN PGP SIGNATURE-----
 
 iIoEABYIADIWIQSacvsUNc7UX4ntmEPzXCl4vpKOKwUCX4SD7xQcZWJpZ2dlcnNA
 Z29vZ2xlLmNvbQAKCRDzXCl4vpKOKy/AAP92oOybTcuahmvAtHqZP9jAFPJrbI3r
 6QLpMFtWznJoOQEAogaWsavtOIBx9afdOfRNj0zdoBIjpXgyMuzR10Ou2gE=
 =B/Mj
 -----END PGP SIGNATURE-----

Merge tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt

Pull fscrypt updates from Eric Biggers:
 "This release, we rework the implementation of creating new encrypted
  files in order to fix some deadlocks and prepare for adding fscrypt
  support to CephFS, which Jeff Layton is working on.

  We also export a symbol in preparation for the above-mentioned CephFS
  support and also for ext4/f2fs encrypt+casefold support.

  Finally, there are a few other small cleanups.

  As usual, all these patches have been in linux-next with no reported
  issues, and I've tested them with xfstests"

* tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt:
  fscrypt: export fscrypt_d_revalidate()
  fscrypt: rename DCACHE_ENCRYPTED_NAME to DCACHE_NOKEY_NAME
  fscrypt: don't call no-key names "ciphertext names"
  fscrypt: use sha256() instead of open coding
  fscrypt: make fscrypt_set_test_dummy_encryption() take a 'const char *'
  fscrypt: handle test_dummy_encryption in more logical way
  fscrypt: move fscrypt_prepare_symlink() out-of-line
  fscrypt: make "#define fscrypt_policy" user-only
  fscrypt: stop pretending that key setup is nofs-safe
  fscrypt: require that fscrypt_encrypt_symlink() already has key
  fscrypt: remove fscrypt_inherit_context()
  fscrypt: adjust logging for in-creation inodes
  ubifs: use fscrypt_prepare_new_inode() and fscrypt_set_context()
  f2fs: use fscrypt_prepare_new_inode() and fscrypt_set_context()
  ext4: use fscrypt_prepare_new_inode() and fscrypt_set_context()
  ext4: factor out ext4_xattr_credits_for_new_inode()
  fscrypt: add fscrypt_prepare_new_inode() and fscrypt_set_context()
  fscrypt: restrict IV_INO_LBLK_32 to ino_bits <= 32
  fscrypt: drop unused inode argument from fscrypt_fname_alloc_buffer
This commit is contained in:
Linus Torvalds 2020-10-13 08:54:00 -07:00
commit 6f5032a852
22 changed files with 536 additions and 445 deletions

View File

@ -343,9 +343,11 @@ void fscrypt_msg(const struct inode *inode, const char *level,
va_start(args, fmt); va_start(args, fmt);
vaf.fmt = fmt; vaf.fmt = fmt;
vaf.va = &args; vaf.va = &args;
if (inode) if (inode && inode->i_ino)
printk("%sfscrypt (%s, inode %lu): %pV\n", printk("%sfscrypt (%s, inode %lu): %pV\n",
level, inode->i_sb->s_id, inode->i_ino, &vaf); level, inode->i_sb->s_id, inode->i_ino, &vaf);
else if (inode)
printk("%sfscrypt (%s): %pV\n", level, inode->i_sb->s_id, &vaf);
else else
printk("%sfscrypt: %pV\n", level, &vaf); printk("%sfscrypt: %pV\n", level, &vaf);
va_end(args); va_end(args);

View File

@ -61,15 +61,6 @@ struct fscrypt_nokey_name {
*/ */
#define FSCRYPT_NOKEY_NAME_MAX offsetofend(struct fscrypt_nokey_name, sha256) #define FSCRYPT_NOKEY_NAME_MAX offsetofend(struct fscrypt_nokey_name, sha256)
static void fscrypt_do_sha256(const u8 *data, unsigned int data_len, u8 *result)
{
struct sha256_state sctx;
sha256_init(&sctx);
sha256_update(&sctx, data, data_len);
sha256_final(&sctx, result);
}
static inline bool fscrypt_is_dot_dotdot(const struct qstr *str) static inline bool fscrypt_is_dot_dotdot(const struct qstr *str)
{ {
if (str->len == 1 && str->name[0] == '.') if (str->len == 1 && str->name[0] == '.')
@ -242,11 +233,11 @@ static int base64_decode(const char *src, int len, u8 *dst)
return cp - dst; return cp - dst;
} }
bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len, bool fscrypt_fname_encrypted_size(const union fscrypt_policy *policy,
u32 max_len, u32 *encrypted_len_ret) u32 orig_len, u32 max_len,
u32 *encrypted_len_ret)
{ {
const struct fscrypt_info *ci = inode->i_crypt_info; int padding = 4 << (fscrypt_policy_flags(policy) &
int padding = 4 << (fscrypt_policy_flags(&ci->ci_policy) &
FSCRYPT_POLICY_FLAGS_PAD_MASK); FSCRYPT_POLICY_FLAGS_PAD_MASK);
u32 encrypted_len; u32 encrypted_len;
@ -260,8 +251,6 @@ bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len,
/** /**
* fscrypt_fname_alloc_buffer() - allocate a buffer for presented filenames * fscrypt_fname_alloc_buffer() - allocate a buffer for presented filenames
* @inode: inode of the parent directory (for regular filenames)
* or of the symlink (for symlink targets)
* @max_encrypted_len: maximum length of encrypted filenames the buffer will be * @max_encrypted_len: maximum length of encrypted filenames the buffer will be
* used to present * used to present
* @crypto_str: (output) buffer to allocate * @crypto_str: (output) buffer to allocate
@ -271,8 +260,7 @@ bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len,
* *
* Return: 0 on success, -errno on failure * Return: 0 on success, -errno on failure
*/ */
int fscrypt_fname_alloc_buffer(const struct inode *inode, int fscrypt_fname_alloc_buffer(u32 max_encrypted_len,
u32 max_encrypted_len,
struct fscrypt_str *crypto_str) struct fscrypt_str *crypto_str)
{ {
const u32 max_encoded_len = BASE64_CHARS(FSCRYPT_NOKEY_NAME_MAX); const u32 max_encoded_len = BASE64_CHARS(FSCRYPT_NOKEY_NAME_MAX);
@ -369,7 +357,7 @@ int fscrypt_fname_disk_to_usr(const struct inode *inode,
} else { } else {
memcpy(nokey_name.bytes, iname->name, sizeof(nokey_name.bytes)); memcpy(nokey_name.bytes, iname->name, sizeof(nokey_name.bytes));
/* Compute strong hash of remaining part of name. */ /* Compute strong hash of remaining part of name. */
fscrypt_do_sha256(&iname->name[sizeof(nokey_name.bytes)], sha256(&iname->name[sizeof(nokey_name.bytes)],
iname->len - sizeof(nokey_name.bytes), iname->len - sizeof(nokey_name.bytes),
nokey_name.sha256); nokey_name.sha256);
size = FSCRYPT_NOKEY_NAME_MAX; size = FSCRYPT_NOKEY_NAME_MAX;
@ -394,9 +382,9 @@ EXPORT_SYMBOL(fscrypt_fname_disk_to_usr);
* directory's encryption key, then @iname is the plaintext, so we encrypt it to * directory's encryption key, then @iname is the plaintext, so we encrypt it to
* get the disk_name. * get the disk_name.
* *
* Else, for keyless @lookup operations, @iname is the presented ciphertext, so * Else, for keyless @lookup operations, @iname should be a no-key name, so we
* we decode it to get the fscrypt_nokey_name. Non-@lookup operations will be * decode it to get the struct fscrypt_nokey_name. Non-@lookup operations will
* impossible in this case, so we fail them with ENOKEY. * be impossible in this case, so we fail them with ENOKEY.
* *
* If successful, fscrypt_free_filename() must be called later to clean up. * If successful, fscrypt_free_filename() must be called later to clean up.
* *
@ -421,7 +409,8 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,
return ret; return ret;
if (fscrypt_has_encryption_key(dir)) { if (fscrypt_has_encryption_key(dir)) {
if (!fscrypt_fname_encrypted_size(dir, iname->len, if (!fscrypt_fname_encrypted_size(&dir->i_crypt_info->ci_policy,
iname->len,
dir->i_sb->s_cop->max_namelen, dir->i_sb->s_cop->max_namelen,
&fname->crypto_buf.len)) &fname->crypto_buf.len))
return -ENAMETOOLONG; return -ENAMETOOLONG;
@ -440,7 +429,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,
} }
if (!lookup) if (!lookup)
return -ENOKEY; return -ENOKEY;
fname->is_ciphertext_name = true; fname->is_nokey_name = true;
/* /*
* We don't have the key and we are doing a lookup; decode the * We don't have the key and we are doing a lookup; decode the
@ -499,7 +488,7 @@ bool fscrypt_match_name(const struct fscrypt_name *fname,
{ {
const struct fscrypt_nokey_name *nokey_name = const struct fscrypt_nokey_name *nokey_name =
(const void *)fname->crypto_buf.name; (const void *)fname->crypto_buf.name;
u8 sha256[SHA256_DIGEST_SIZE]; u8 digest[SHA256_DIGEST_SIZE];
if (likely(fname->disk_name.name)) { if (likely(fname->disk_name.name)) {
if (de_name_len != fname->disk_name.len) if (de_name_len != fname->disk_name.len)
@ -510,9 +499,9 @@ bool fscrypt_match_name(const struct fscrypt_name *fname,
return false; return false;
if (memcmp(de_name, nokey_name->bytes, sizeof(nokey_name->bytes))) if (memcmp(de_name, nokey_name->bytes, sizeof(nokey_name->bytes)))
return false; return false;
fscrypt_do_sha256(&de_name[sizeof(nokey_name->bytes)], sha256(&de_name[sizeof(nokey_name->bytes)],
de_name_len - sizeof(nokey_name->bytes), sha256); de_name_len - sizeof(nokey_name->bytes), digest);
return !memcmp(sha256, nokey_name->sha256, sizeof(sha256)); return !memcmp(digest, nokey_name->sha256, sizeof(digest));
} }
EXPORT_SYMBOL_GPL(fscrypt_match_name); EXPORT_SYMBOL_GPL(fscrypt_match_name);
@ -541,7 +530,7 @@ EXPORT_SYMBOL_GPL(fscrypt_fname_siphash);
* Validate dentries in encrypted directories to make sure we aren't potentially * Validate dentries in encrypted directories to make sure we aren't potentially
* caching stale dentries after a key has been added. * caching stale dentries after a key has been added.
*/ */
static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags) int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags)
{ {
struct dentry *dir; struct dentry *dir;
int err; int err;
@ -549,17 +538,17 @@ static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags)
/* /*
* Plaintext names are always valid, since fscrypt doesn't support * Plaintext names are always valid, since fscrypt doesn't support
* reverting to ciphertext names without evicting the directory's inode * reverting to no-key names without evicting the directory's inode
* -- which implies eviction of the dentries in the directory. * -- which implies eviction of the dentries in the directory.
*/ */
if (!(dentry->d_flags & DCACHE_ENCRYPTED_NAME)) if (!(dentry->d_flags & DCACHE_NOKEY_NAME))
return 1; return 1;
/* /*
* Ciphertext name; valid if the directory's key is still unavailable. * No-key name; valid if the directory's key is still unavailable.
* *
* Although fscrypt forbids rename() on ciphertext names, we still must * Although fscrypt forbids rename() on no-key names, we still must use
* use dget_parent() here rather than use ->d_parent directly. That's * dget_parent() here rather than use ->d_parent directly. That's
* because a corrupted fs image may contain directory hard links, which * because a corrupted fs image may contain directory hard links, which
* the VFS handles by moving the directory's dentry tree in the dcache * the VFS handles by moving the directory's dentry tree in the dcache
* each time ->lookup() finds the directory and it already has a dentry * each time ->lookup() finds the directory and it already has a dentry
@ -580,6 +569,7 @@ static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags)
return valid; return valid;
} }
EXPORT_SYMBOL_GPL(fscrypt_d_revalidate);
const struct dentry_operations fscrypt_d_ops = { const struct dentry_operations fscrypt_d_ops = {
.d_revalidate = fscrypt_d_revalidate, .d_revalidate = fscrypt_d_revalidate,

View File

@ -97,7 +97,6 @@ static inline const u8 *fscrypt_context_nonce(const union fscrypt_context *ctx)
return NULL; return NULL;
} }
#undef fscrypt_policy
union fscrypt_policy { union fscrypt_policy {
u8 version; u8 version;
struct fscrypt_policy_v1 v1; struct fscrypt_policy_v1 v1;
@ -292,8 +291,9 @@ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num,
/* fname.c */ /* fname.c */
int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname, int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
u8 *out, unsigned int olen); u8 *out, unsigned int olen);
bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len, bool fscrypt_fname_encrypted_size(const union fscrypt_policy *policy,
u32 max_len, u32 *encrypted_len_ret); u32 orig_len, u32 max_len,
u32 *encrypted_len_ret);
extern const struct dentry_operations fscrypt_d_ops; extern const struct dentry_operations fscrypt_d_ops;
/* hkdf.c */ /* hkdf.c */
@ -572,6 +572,9 @@ int fscrypt_set_per_file_enc_key(struct fscrypt_info *ci, const u8 *raw_key);
int fscrypt_derive_dirhash_key(struct fscrypt_info *ci, int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
const struct fscrypt_master_key *mk); const struct fscrypt_master_key *mk);
void fscrypt_hash_inode_number(struct fscrypt_info *ci,
const struct fscrypt_master_key *mk);
/* keysetup_v1.c */ /* keysetup_v1.c */
void fscrypt_put_direct_key(struct fscrypt_direct_key *dk); void fscrypt_put_direct_key(struct fscrypt_direct_key *dk);
@ -590,5 +593,6 @@ bool fscrypt_supported_policy(const union fscrypt_policy *policy_u,
int fscrypt_policy_from_context(union fscrypt_policy *policy_u, int fscrypt_policy_from_context(union fscrypt_policy *policy_u,
const union fscrypt_context *ctx_u, const union fscrypt_context *ctx_u,
int ctx_size); int ctx_size);
const union fscrypt_policy *fscrypt_policy_to_inherit(struct inode *dir);
#endif /* _FSCRYPT_PRIVATE_H */ #endif /* _FSCRYPT_PRIVATE_H */

View File

@ -60,8 +60,8 @@ int __fscrypt_prepare_link(struct inode *inode, struct inode *dir,
if (err) if (err)
return err; return err;
/* ... in case we looked up ciphertext name before key was added */ /* ... in case we looked up no-key name before key was added */
if (dentry->d_flags & DCACHE_ENCRYPTED_NAME) if (dentry->d_flags & DCACHE_NOKEY_NAME)
return -ENOKEY; return -ENOKEY;
if (!fscrypt_has_permitted_context(dir, inode)) if (!fscrypt_has_permitted_context(dir, inode))
@ -85,9 +85,8 @@ int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry,
if (err) if (err)
return err; return err;
/* ... in case we looked up ciphertext name(s) before key was added */ /* ... in case we looked up no-key name(s) before key was added */
if ((old_dentry->d_flags | new_dentry->d_flags) & if ((old_dentry->d_flags | new_dentry->d_flags) & DCACHE_NOKEY_NAME)
DCACHE_ENCRYPTED_NAME)
return -ENOKEY; return -ENOKEY;
if (old_dir != new_dir) { if (old_dir != new_dir) {
@ -114,9 +113,9 @@ int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry,
if (err && err != -ENOENT) if (err && err != -ENOENT)
return err; return err;
if (fname->is_ciphertext_name) { if (fname->is_nokey_name) {
spin_lock(&dentry->d_lock); spin_lock(&dentry->d_lock);
dentry->d_flags |= DCACHE_ENCRYPTED_NAME; dentry->d_flags |= DCACHE_NOKEY_NAME;
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
d_set_d_op(dentry, &fscrypt_d_ops); d_set_d_op(dentry, &fscrypt_d_ops);
} }
@ -166,26 +165,51 @@ int fscrypt_prepare_setflags(struct inode *inode,
return 0; return 0;
} }
int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len, /**
unsigned int max_len, * fscrypt_prepare_symlink() - prepare to create a possibly-encrypted symlink
* @dir: directory in which the symlink is being created
* @target: plaintext symlink target
* @len: length of @target excluding null terminator
* @max_len: space the filesystem has available to store the symlink target
* @disk_link: (out) the on-disk symlink target being prepared
*
* This function computes the size the symlink target will require on-disk,
* stores it in @disk_link->len, and validates it against @max_len. An
* encrypted symlink may be longer than the original.
*
* Additionally, @disk_link->name is set to @target if the symlink will be
* unencrypted, but left NULL if the symlink will be encrypted. For encrypted
* symlinks, the filesystem must call fscrypt_encrypt_symlink() to create the
* on-disk target later. (The reason for the two-step process is that some
* filesystems need to know the size of the symlink target before creating the
* inode, e.g. to determine whether it will be a "fast" or "slow" symlink.)
*
* Return: 0 on success, -ENAMETOOLONG if the symlink target is too long,
* -ENOKEY if the encryption key is missing, or another -errno code if a problem
* occurred while setting up the encryption key.
*/
int fscrypt_prepare_symlink(struct inode *dir, const char *target,
unsigned int len, unsigned int max_len,
struct fscrypt_str *disk_link) struct fscrypt_str *disk_link)
{ {
int err; const union fscrypt_policy *policy;
/* /*
* To calculate the size of the encrypted symlink target we need to know * To calculate the size of the encrypted symlink target we need to know
* the amount of NUL padding, which is determined by the flags set in * the amount of NUL padding, which is determined by the flags set in
* the encryption policy which will be inherited from the directory. * the encryption policy which will be inherited from the directory.
* The easiest way to get access to this is to just load the directory's
* fscrypt_info, since we'll need it to create the dir_entry anyway.
*
* Note: in test_dummy_encryption mode, @dir may be unencrypted.
*/ */
err = fscrypt_get_encryption_info(dir); policy = fscrypt_policy_to_inherit(dir);
if (err) if (policy == NULL) {
return err; /* Not encrypted */
if (!fscrypt_has_encryption_key(dir)) disk_link->name = (unsigned char *)target;
return -ENOKEY; disk_link->len = len + 1;
if (disk_link->len > max_len)
return -ENAMETOOLONG;
return 0;
}
if (IS_ERR(policy))
return PTR_ERR(policy);
/* /*
* Calculate the size of the encrypted symlink and verify it won't * Calculate the size of the encrypted symlink and verify it won't
@ -198,7 +222,7 @@ int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len,
* counting it (even though it is meaningless for ciphertext) is simpler * counting it (even though it is meaningless for ciphertext) is simpler
* for now since filesystems will assume it is there and subtract it. * for now since filesystems will assume it is there and subtract it.
*/ */
if (!fscrypt_fname_encrypted_size(dir, len, if (!fscrypt_fname_encrypted_size(policy, len,
max_len - sizeof(struct fscrypt_symlink_data), max_len - sizeof(struct fscrypt_symlink_data),
&disk_link->len)) &disk_link->len))
return -ENAMETOOLONG; return -ENAMETOOLONG;
@ -207,7 +231,7 @@ int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len,
disk_link->name = NULL; disk_link->name = NULL;
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(__fscrypt_prepare_symlink); EXPORT_SYMBOL_GPL(fscrypt_prepare_symlink);
int __fscrypt_encrypt_symlink(struct inode *inode, const char *target, int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
unsigned int len, struct fscrypt_str *disk_link) unsigned int len, struct fscrypt_str *disk_link)
@ -217,9 +241,13 @@ int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
struct fscrypt_symlink_data *sd; struct fscrypt_symlink_data *sd;
unsigned int ciphertext_len; unsigned int ciphertext_len;
err = fscrypt_require_key(inode); /*
if (err) * fscrypt_prepare_new_inode() should have already set up the new
return err; * symlink inode's encryption key. We don't wait until now to do it,
* since we may be in a filesystem transaction now.
*/
if (WARN_ON_ONCE(!fscrypt_has_encryption_key(inode)))
return -ENOKEY;
if (disk_link->name) { if (disk_link->name) {
/* filesystem-provided buffer */ /* filesystem-provided buffer */
@ -319,7 +347,7 @@ const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
if (cstr.len + sizeof(*sd) - 1 > max_size) if (cstr.len + sizeof(*sd) - 1 > max_size)
return ERR_PTR(-EUCLEAN); return ERR_PTR(-EUCLEAN);
err = fscrypt_fname_alloc_buffer(inode, cstr.len, &pstr); err = fscrypt_fname_alloc_buffer(cstr.len, &pstr);
if (err) if (err)
return ERR_PTR(err); return ERR_PTR(err);

View File

@ -106,7 +106,7 @@ int fscrypt_select_encryption_impl(struct fscrypt_info *ci)
crypto_cfg.data_unit_size = sb->s_blocksize; crypto_cfg.data_unit_size = sb->s_blocksize;
crypto_cfg.dun_bytes = fscrypt_get_dun_bytes(ci); crypto_cfg.dun_bytes = fscrypt_get_dun_bytes(ci);
num_devs = fscrypt_get_num_devices(sb); num_devs = fscrypt_get_num_devices(sb);
devs = kmalloc_array(num_devs, sizeof(*devs), GFP_NOFS); devs = kmalloc_array(num_devs, sizeof(*devs), GFP_KERNEL);
if (!devs) if (!devs)
return -ENOMEM; return -ENOMEM;
fscrypt_get_devices(sb, num_devs, devs); fscrypt_get_devices(sb, num_devs, devs);
@ -135,9 +135,8 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
struct fscrypt_blk_crypto_key *blk_key; struct fscrypt_blk_crypto_key *blk_key;
int err; int err;
int i; int i;
unsigned int flags;
blk_key = kzalloc(struct_size(blk_key, devs, num_devs), GFP_NOFS); blk_key = kzalloc(struct_size(blk_key, devs, num_devs), GFP_KERNEL);
if (!blk_key) if (!blk_key)
return -ENOMEM; return -ENOMEM;
@ -166,10 +165,8 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
} }
queue_refs++; queue_refs++;
flags = memalloc_nofs_save();
err = blk_crypto_start_using_key(&blk_key->base, err = blk_crypto_start_using_key(&blk_key->base,
blk_key->devs[i]); blk_key->devs[i]);
memalloc_nofs_restore(flags);
if (err) { if (err) {
fscrypt_err(inode, fscrypt_err(inode,
"error %d starting to use blk-crypto", err); "error %d starting to use blk-crypto", err);

View File

@ -817,6 +817,7 @@ static int check_for_busy_inodes(struct super_block *sb,
struct list_head *pos; struct list_head *pos;
size_t busy_count = 0; size_t busy_count = 0;
unsigned long ino; unsigned long ino;
char ino_str[50] = "";
spin_lock(&mk->mk_decrypted_inodes_lock); spin_lock(&mk->mk_decrypted_inodes_lock);
@ -838,11 +839,15 @@ static int check_for_busy_inodes(struct super_block *sb,
} }
spin_unlock(&mk->mk_decrypted_inodes_lock); spin_unlock(&mk->mk_decrypted_inodes_lock);
/* If the inode is currently being created, ino may still be 0. */
if (ino)
snprintf(ino_str, sizeof(ino_str), ", including ino %lu", ino);
fscrypt_warn(NULL, fscrypt_warn(NULL,
"%s: %zu inode(s) still busy after removing key with %s %*phN, including ino %lu", "%s: %zu inode(s) still busy after removing key with %s %*phN%s",
sb->s_id, busy_count, master_key_spec_type(&mk->mk_spec), sb->s_id, busy_count, master_key_spec_type(&mk->mk_spec),
master_key_spec_len(&mk->mk_spec), (u8 *)&mk->mk_spec.u, master_key_spec_len(&mk->mk_spec), (u8 *)&mk->mk_spec.u,
ino); ino_str);
return -EBUSY; return -EBUSY;
} }

View File

@ -10,6 +10,7 @@
#include <crypto/skcipher.h> #include <crypto/skcipher.h>
#include <linux/key.h> #include <linux/key.h>
#include <linux/random.h>
#include "fscrypt_private.h" #include "fscrypt_private.h"
@ -222,6 +223,16 @@ int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
return 0; return 0;
} }
void fscrypt_hash_inode_number(struct fscrypt_info *ci,
const struct fscrypt_master_key *mk)
{
WARN_ON(ci->ci_inode->i_ino == 0);
WARN_ON(!mk->mk_ino_hash_key_initialized);
ci->ci_hashed_ino = (u32)siphash_1u64(ci->ci_inode->i_ino,
&mk->mk_ino_hash_key);
}
static int fscrypt_setup_iv_ino_lblk_32_key(struct fscrypt_info *ci, static int fscrypt_setup_iv_ino_lblk_32_key(struct fscrypt_info *ci,
struct fscrypt_master_key *mk) struct fscrypt_master_key *mk)
{ {
@ -254,13 +265,20 @@ unlock:
return err; return err;
} }
ci->ci_hashed_ino = (u32)siphash_1u64(ci->ci_inode->i_ino, /*
&mk->mk_ino_hash_key); * New inodes may not have an inode number assigned yet.
* Hashing their inode number is delayed until later.
*/
if (ci->ci_inode->i_ino == 0)
WARN_ON(!(ci->ci_inode->i_state & I_CREATING));
else
fscrypt_hash_inode_number(ci, mk);
return 0; return 0;
} }
static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci, static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci,
struct fscrypt_master_key *mk) struct fscrypt_master_key *mk,
bool need_dirhash_key)
{ {
int err; int err;
@ -306,7 +324,7 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci,
return err; return err;
/* Derive a secret dirhash key for directories that need it. */ /* Derive a secret dirhash key for directories that need it. */
if (S_ISDIR(ci->ci_inode->i_mode) && IS_CASEFOLDED(ci->ci_inode)) { if (need_dirhash_key) {
err = fscrypt_derive_dirhash_key(ci, mk); err = fscrypt_derive_dirhash_key(ci, mk);
if (err) if (err)
return err; return err;
@ -326,6 +344,7 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci,
* key being removed with a new inode starting to use it. * key being removed with a new inode starting to use it.
*/ */
static int setup_file_encryption_key(struct fscrypt_info *ci, static int setup_file_encryption_key(struct fscrypt_info *ci,
bool need_dirhash_key,
struct key **master_key_ret) struct key **master_key_ret)
{ {
struct key *key; struct key *key;
@ -400,7 +419,7 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
err = fscrypt_setup_v1_file_key(ci, mk->mk_secret.raw); err = fscrypt_setup_v1_file_key(ci, mk->mk_secret.raw);
break; break;
case FSCRYPT_POLICY_V2: case FSCRYPT_POLICY_V2:
err = fscrypt_setup_v2_file_key(ci, mk); err = fscrypt_setup_v2_file_key(ci, mk, need_dirhash_key);
break; break;
default: default:
WARN_ON(1); WARN_ON(1);
@ -454,57 +473,28 @@ static void put_crypt_info(struct fscrypt_info *ci)
kmem_cache_free(fscrypt_info_cachep, ci); kmem_cache_free(fscrypt_info_cachep, ci);
} }
int fscrypt_get_encryption_info(struct inode *inode) static int
fscrypt_setup_encryption_info(struct inode *inode,
const union fscrypt_policy *policy,
const u8 nonce[FSCRYPT_FILE_NONCE_SIZE],
bool need_dirhash_key)
{ {
struct fscrypt_info *crypt_info; struct fscrypt_info *crypt_info;
union fscrypt_context ctx;
struct fscrypt_mode *mode; struct fscrypt_mode *mode;
struct key *master_key = NULL; struct key *master_key = NULL;
int res; int res;
if (fscrypt_has_encryption_key(inode))
return 0;
res = fscrypt_initialize(inode->i_sb->s_cop->flags); res = fscrypt_initialize(inode->i_sb->s_cop->flags);
if (res) if (res)
return res; return res;
res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); crypt_info = kmem_cache_zalloc(fscrypt_info_cachep, GFP_KERNEL);
if (res < 0) {
const union fscrypt_context *dummy_ctx =
fscrypt_get_dummy_context(inode->i_sb);
if (IS_ENCRYPTED(inode) || !dummy_ctx) {
fscrypt_warn(inode,
"Error %d getting encryption context",
res);
return res;
}
/* Fake up a context for an unencrypted directory */
res = fscrypt_context_size(dummy_ctx);
memcpy(&ctx, dummy_ctx, res);
}
crypt_info = kmem_cache_zalloc(fscrypt_info_cachep, GFP_NOFS);
if (!crypt_info) if (!crypt_info)
return -ENOMEM; return -ENOMEM;
crypt_info->ci_inode = inode; crypt_info->ci_inode = inode;
crypt_info->ci_policy = *policy;
res = fscrypt_policy_from_context(&crypt_info->ci_policy, &ctx, res); memcpy(crypt_info->ci_nonce, nonce, FSCRYPT_FILE_NONCE_SIZE);
if (res) {
fscrypt_warn(inode,
"Unrecognized or corrupt encryption context");
goto out;
}
memcpy(crypt_info->ci_nonce, fscrypt_context_nonce(&ctx),
FSCRYPT_FILE_NONCE_SIZE);
if (!fscrypt_supported_policy(&crypt_info->ci_policy, inode)) {
res = -EINVAL;
goto out;
}
mode = select_encryption_mode(&crypt_info->ci_policy, inode); mode = select_encryption_mode(&crypt_info->ci_policy, inode);
if (IS_ERR(mode)) { if (IS_ERR(mode)) {
@ -514,13 +504,14 @@ int fscrypt_get_encryption_info(struct inode *inode)
WARN_ON(mode->ivsize > FSCRYPT_MAX_IV_SIZE); WARN_ON(mode->ivsize > FSCRYPT_MAX_IV_SIZE);
crypt_info->ci_mode = mode; crypt_info->ci_mode = mode;
res = setup_file_encryption_key(crypt_info, &master_key); res = setup_file_encryption_key(crypt_info, need_dirhash_key,
&master_key);
if (res) if (res)
goto out; goto out;
/* /*
* Multiple tasks may race to set ->i_crypt_info, so use * For existing inodes, multiple tasks may race to set ->i_crypt_info.
* cmpxchg_release(). This pairs with the smp_load_acquire() in * So use cmpxchg_release(). This pairs with the smp_load_acquire() in
* fscrypt_get_info(). I.e., here we publish ->i_crypt_info with a * fscrypt_get_info(). I.e., here we publish ->i_crypt_info with a
* RELEASE barrier so that other tasks can ACQUIRE it. * RELEASE barrier so that other tasks can ACQUIRE it.
*/ */
@ -550,13 +541,112 @@ out:
up_read(&mk->mk_secret_sem); up_read(&mk->mk_secret_sem);
key_put(master_key); key_put(master_key);
} }
if (res == -ENOKEY)
res = 0;
put_crypt_info(crypt_info); put_crypt_info(crypt_info);
return res; return res;
} }
/**
* fscrypt_get_encryption_info() - set up an inode's encryption key
* @inode: the inode to set up the key for. Must be encrypted.
*
* Set up ->i_crypt_info, if it hasn't already been done.
*
* Note: unless ->i_crypt_info is already set, this isn't %GFP_NOFS-safe. So
* generally this shouldn't be called from within a filesystem transaction.
*
* Return: 0 if ->i_crypt_info was set or was already set, *or* if the
* encryption key is unavailable. (Use fscrypt_has_encryption_key() to
* distinguish these cases.) Also can return another -errno code.
*/
int fscrypt_get_encryption_info(struct inode *inode)
{
int res;
union fscrypt_context ctx;
union fscrypt_policy policy;
if (fscrypt_has_encryption_key(inode))
return 0;
res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx));
if (res < 0) {
fscrypt_warn(inode, "Error %d getting encryption context", res);
return res;
}
res = fscrypt_policy_from_context(&policy, &ctx, res);
if (res) {
fscrypt_warn(inode,
"Unrecognized or corrupt encryption context");
return res;
}
if (!fscrypt_supported_policy(&policy, inode))
return -EINVAL;
res = fscrypt_setup_encryption_info(inode, &policy,
fscrypt_context_nonce(&ctx),
IS_CASEFOLDED(inode) &&
S_ISDIR(inode->i_mode));
if (res == -ENOKEY)
res = 0;
return res;
}
EXPORT_SYMBOL(fscrypt_get_encryption_info); EXPORT_SYMBOL(fscrypt_get_encryption_info);
/**
* fscrypt_prepare_new_inode() - prepare to create a new inode in a directory
* @dir: a possibly-encrypted directory
* @inode: the new inode. ->i_mode must be set already.
* ->i_ino doesn't need to be set yet.
* @encrypt_ret: (output) set to %true if the new inode will be encrypted
*
* If the directory is encrypted, set up its ->i_crypt_info in preparation for
* encrypting the name of the new file. Also, if the new inode will be
* encrypted, set up its ->i_crypt_info and set *encrypt_ret=true.
*
* This isn't %GFP_NOFS-safe, and therefore it should be called before starting
* any filesystem transaction to create the inode. For this reason, ->i_ino
* isn't required to be set yet, as the filesystem may not have set it yet.
*
* This doesn't persist the new inode's encryption context. That still needs to
* be done later by calling fscrypt_set_context().
*
* Return: 0 on success, -ENOKEY if the encryption key is missing, or another
* -errno code
*/
int fscrypt_prepare_new_inode(struct inode *dir, struct inode *inode,
bool *encrypt_ret)
{
const union fscrypt_policy *policy;
u8 nonce[FSCRYPT_FILE_NONCE_SIZE];
policy = fscrypt_policy_to_inherit(dir);
if (policy == NULL)
return 0;
if (IS_ERR(policy))
return PTR_ERR(policy);
if (WARN_ON_ONCE(inode->i_mode == 0))
return -EINVAL;
/*
* Only regular files, directories, and symlinks are encrypted.
* Special files like device nodes and named pipes aren't.
*/
if (!S_ISREG(inode->i_mode) &&
!S_ISDIR(inode->i_mode) &&
!S_ISLNK(inode->i_mode))
return 0;
*encrypt_ret = true;
get_random_bytes(nonce, FSCRYPT_FILE_NONCE_SIZE);
return fscrypt_setup_encryption_info(inode, policy, nonce,
IS_CASEFOLDED(dir) &&
S_ISDIR(inode->i_mode));
}
EXPORT_SYMBOL_GPL(fscrypt_prepare_new_inode);
/** /**
* fscrypt_put_encryption_info() - free most of an inode's fscrypt data * fscrypt_put_encryption_info() - free most of an inode's fscrypt data
* @inode: an inode being evicted * @inode: an inode being evicted

View File

@ -60,7 +60,7 @@ static int derive_key_aes(const u8 *master_key,
goto out; goto out;
} }
crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
req = skcipher_request_alloc(tfm, GFP_NOFS); req = skcipher_request_alloc(tfm, GFP_KERNEL);
if (!req) { if (!req) {
res = -ENOMEM; res = -ENOMEM;
goto out; goto out;
@ -99,7 +99,7 @@ find_and_lock_process_key(const char *prefix,
const struct user_key_payload *ukp; const struct user_key_payload *ukp;
const struct fscrypt_key *payload; const struct fscrypt_key *payload;
description = kasprintf(GFP_NOFS, "%s%*phN", prefix, description = kasprintf(GFP_KERNEL, "%s%*phN", prefix,
FSCRYPT_KEY_DESCRIPTOR_SIZE, descriptor); FSCRYPT_KEY_DESCRIPTOR_SIZE, descriptor);
if (!description) if (!description)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
@ -228,7 +228,7 @@ fscrypt_get_direct_key(const struct fscrypt_info *ci, const u8 *raw_key)
return dk; return dk;
/* Nope, allocate one. */ /* Nope, allocate one. */
dk = kzalloc(sizeof(*dk), GFP_NOFS); dk = kzalloc(sizeof(*dk), GFP_KERNEL);
if (!dk) if (!dk)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
refcount_set(&dk->dk_refcount, 1); refcount_set(&dk->dk_refcount, 1);
@ -272,7 +272,7 @@ static int setup_v1_file_key_derived(struct fscrypt_info *ci,
* This cannot be a stack buffer because it will be passed to the * This cannot be a stack buffer because it will be passed to the
* scatterlist crypto API during derive_key_aes(). * scatterlist crypto API during derive_key_aes().
*/ */
derived_key = kmalloc(ci->ci_mode->keysize, GFP_NOFS); derived_key = kmalloc(ci->ci_mode->keysize, GFP_KERNEL);
if (!derived_key) if (!derived_key)
return -ENOMEM; return -ENOMEM;

View File

@ -32,6 +32,14 @@ bool fscrypt_policies_equal(const union fscrypt_policy *policy1,
return !memcmp(policy1, policy2, fscrypt_policy_size(policy1)); return !memcmp(policy1, policy2, fscrypt_policy_size(policy1));
} }
static const union fscrypt_policy *
fscrypt_get_dummy_policy(struct super_block *sb)
{
if (!sb->s_cop->get_dummy_policy)
return NULL;
return sb->s_cop->get_dummy_policy(sb);
}
static bool fscrypt_valid_enc_modes(u32 contents_mode, u32 filenames_mode) static bool fscrypt_valid_enc_modes(u32 contents_mode, u32 filenames_mode)
{ {
if (contents_mode == FSCRYPT_MODE_AES_256_XTS && if (contents_mode == FSCRYPT_MODE_AES_256_XTS &&
@ -192,10 +200,15 @@ static bool fscrypt_supported_v2_policy(const struct fscrypt_policy_v2 *policy,
32, 32)) 32, 32))
return false; return false;
/*
* IV_INO_LBLK_32 hashes the inode number, so in principle it can
* support any ino_bits. However, currently the inode number is gotten
* from inode::i_ino which is 'unsigned long'. So for now the
* implementation limit is 32 bits.
*/
if ((policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) && if ((policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) &&
/* This uses hashed inode numbers, so ino_bits doesn't matter. */
!supported_iv_ino_lblk_policy(policy, inode, "IV_INO_LBLK_32", !supported_iv_ino_lblk_policy(policy, inode, "IV_INO_LBLK_32",
INT_MAX, 32)) 32, 32))
return false; return false;
if (memchr_inv(policy->__reserved, 0, sizeof(policy->__reserved))) { if (memchr_inv(policy->__reserved, 0, sizeof(policy->__reserved))) {
@ -231,18 +244,19 @@ bool fscrypt_supported_policy(const union fscrypt_policy *policy_u,
} }
/** /**
* fscrypt_new_context_from_policy() - create a new fscrypt_context from * fscrypt_new_context() - create a new fscrypt_context
* an fscrypt_policy
* @ctx_u: output context * @ctx_u: output context
* @policy_u: input policy * @policy_u: input policy
* @nonce: nonce to use
* *
* Create an fscrypt_context for an inode that is being assigned the given * Create an fscrypt_context for an inode that is being assigned the given
* encryption policy. A new nonce is randomly generated. * encryption policy. @nonce must be a new random nonce.
* *
* Return: the size of the new context in bytes. * Return: the size of the new context in bytes.
*/ */
static int fscrypt_new_context_from_policy(union fscrypt_context *ctx_u, static int fscrypt_new_context(union fscrypt_context *ctx_u,
const union fscrypt_policy *policy_u) const union fscrypt_policy *policy_u,
const u8 nonce[FSCRYPT_FILE_NONCE_SIZE])
{ {
memset(ctx_u, 0, sizeof(*ctx_u)); memset(ctx_u, 0, sizeof(*ctx_u));
@ -260,7 +274,7 @@ static int fscrypt_new_context_from_policy(union fscrypt_context *ctx_u,
memcpy(ctx->master_key_descriptor, memcpy(ctx->master_key_descriptor,
policy->master_key_descriptor, policy->master_key_descriptor,
sizeof(ctx->master_key_descriptor)); sizeof(ctx->master_key_descriptor));
get_random_bytes(ctx->nonce, sizeof(ctx->nonce)); memcpy(ctx->nonce, nonce, FSCRYPT_FILE_NONCE_SIZE);
return sizeof(*ctx); return sizeof(*ctx);
} }
case FSCRYPT_POLICY_V2: { case FSCRYPT_POLICY_V2: {
@ -276,7 +290,7 @@ static int fscrypt_new_context_from_policy(union fscrypt_context *ctx_u,
memcpy(ctx->master_key_identifier, memcpy(ctx->master_key_identifier,
policy->master_key_identifier, policy->master_key_identifier,
sizeof(ctx->master_key_identifier)); sizeof(ctx->master_key_identifier));
get_random_bytes(ctx->nonce, sizeof(ctx->nonce)); memcpy(ctx->nonce, nonce, FSCRYPT_FILE_NONCE_SIZE);
return sizeof(*ctx); return sizeof(*ctx);
} }
} }
@ -372,6 +386,7 @@ static int fscrypt_get_policy(struct inode *inode, union fscrypt_policy *policy)
static int set_encryption_policy(struct inode *inode, static int set_encryption_policy(struct inode *inode,
const union fscrypt_policy *policy) const union fscrypt_policy *policy)
{ {
u8 nonce[FSCRYPT_FILE_NONCE_SIZE];
union fscrypt_context ctx; union fscrypt_context ctx;
int ctxsize; int ctxsize;
int err; int err;
@ -409,7 +424,8 @@ static int set_encryption_policy(struct inode *inode,
return -EINVAL; return -EINVAL;
} }
ctxsize = fscrypt_new_context_from_policy(&ctx, policy); get_random_bytes(nonce, FSCRYPT_FILE_NONCE_SIZE);
ctxsize = fscrypt_new_context(&ctx, policy, nonce);
return inode->i_sb->s_cop->set_context(inode, &ctx, ctxsize, NULL); return inode->i_sb->s_cop->set_context(inode, &ctx, ctxsize, NULL);
} }
@ -620,86 +636,99 @@ int fscrypt_has_permitted_context(struct inode *parent, struct inode *child)
} }
EXPORT_SYMBOL(fscrypt_has_permitted_context); EXPORT_SYMBOL(fscrypt_has_permitted_context);
/*
* Return the encryption policy that new files in the directory will inherit, or
* NULL if none, or an ERR_PTR() on error. If the directory is encrypted, also
* ensure that its key is set up, so that the new filename can be encrypted.
*/
const union fscrypt_policy *fscrypt_policy_to_inherit(struct inode *dir)
{
int err;
if (IS_ENCRYPTED(dir)) {
err = fscrypt_require_key(dir);
if (err)
return ERR_PTR(err);
return &dir->i_crypt_info->ci_policy;
}
return fscrypt_get_dummy_policy(dir->i_sb);
}
/** /**
* fscrypt_inherit_context() - Sets a child context from its parent * fscrypt_set_context() - Set the fscrypt context of a new inode
* @parent: Parent inode from which the context is inherited. * @inode: a new inode
* @child: Child inode that inherits the context from @parent. * @fs_data: private data given by FS and passed to ->set_context()
* @fs_data: private data given by FS. *
* @preload: preload child i_crypt_info if true * This should be called after fscrypt_prepare_new_inode(), generally during a
* filesystem transaction. Everything here must be %GFP_NOFS-safe.
* *
* Return: 0 on success, -errno on failure * Return: 0 on success, -errno on failure
*/ */
int fscrypt_inherit_context(struct inode *parent, struct inode *child, int fscrypt_set_context(struct inode *inode, void *fs_data)
void *fs_data, bool preload)
{ {
struct fscrypt_info *ci = inode->i_crypt_info;
union fscrypt_context ctx; union fscrypt_context ctx;
int ctxsize; int ctxsize;
struct fscrypt_info *ci;
int res;
res = fscrypt_get_encryption_info(parent); /* fscrypt_prepare_new_inode() should have set up the key already. */
if (res < 0) if (WARN_ON_ONCE(!ci))
return res;
ci = fscrypt_get_info(parent);
if (ci == NULL)
return -ENOKEY; return -ENOKEY;
ctxsize = fscrypt_new_context_from_policy(&ctx, &ci->ci_policy);
BUILD_BUG_ON(sizeof(ctx) != FSCRYPT_SET_CONTEXT_MAX_SIZE); BUILD_BUG_ON(sizeof(ctx) != FSCRYPT_SET_CONTEXT_MAX_SIZE);
res = parent->i_sb->s_cop->set_context(child, &ctx, ctxsize, fs_data); ctxsize = fscrypt_new_context(&ctx, &ci->ci_policy, ci->ci_nonce);
if (res)
return res; /*
return preload ? fscrypt_get_encryption_info(child): 0; * This may be the first time the inode number is available, so do any
* delayed key setup that requires the inode number.
*/
if (ci->ci_policy.version == FSCRYPT_POLICY_V2 &&
(ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) {
const struct fscrypt_master_key *mk =
ci->ci_master_key->payload.data[0];
fscrypt_hash_inode_number(ci, mk);
} }
EXPORT_SYMBOL(fscrypt_inherit_context);
return inode->i_sb->s_cop->set_context(inode, &ctx, ctxsize, fs_data);
}
EXPORT_SYMBOL_GPL(fscrypt_set_context);
/** /**
* fscrypt_set_test_dummy_encryption() - handle '-o test_dummy_encryption' * fscrypt_set_test_dummy_encryption() - handle '-o test_dummy_encryption'
* @sb: the filesystem on which test_dummy_encryption is being specified * @sb: the filesystem on which test_dummy_encryption is being specified
* @arg: the argument to the test_dummy_encryption option. * @arg: the argument to the test_dummy_encryption option. May be NULL.
* If no argument was specified, then @arg->from == NULL. * @dummy_policy: the filesystem's current dummy policy (input/output, see
* @dummy_ctx: the filesystem's current dummy context (input/output, see below) * below)
* *
* Handle the test_dummy_encryption mount option by creating a dummy encryption * Handle the test_dummy_encryption mount option by creating a dummy encryption
* context, saving it in @dummy_ctx, and adding the corresponding dummy * policy, saving it in @dummy_policy, and adding the corresponding dummy
* encryption key to the filesystem. If the @dummy_ctx is already set, then * encryption key to the filesystem. If the @dummy_policy is already set, then
* instead validate that it matches @arg. Don't support changing it via * instead validate that it matches @arg. Don't support changing it via
* remount, as that is difficult to do safely. * remount, as that is difficult to do safely.
* *
* The reason we use an fscrypt_context rather than an fscrypt_policy is because * Return: 0 on success (dummy policy set, or the same policy is already set);
* we mustn't generate a new nonce each time we access a dummy-encrypted * -EEXIST if a different dummy policy is already set;
* directory, as that would change the way filenames are encrypted.
*
* Return: 0 on success (dummy context set, or the same context is already set);
* -EEXIST if a different dummy context is already set;
* or another -errno value. * or another -errno value.
*/ */
int fscrypt_set_test_dummy_encryption(struct super_block *sb, int fscrypt_set_test_dummy_encryption(struct super_block *sb, const char *arg,
const substring_t *arg, struct fscrypt_dummy_policy *dummy_policy)
struct fscrypt_dummy_context *dummy_ctx)
{ {
const char *argstr = "v2";
const char *argstr_to_free = NULL;
struct fscrypt_key_specifier key_spec = { 0 }; struct fscrypt_key_specifier key_spec = { 0 };
int version; int version;
union fscrypt_context *ctx = NULL; union fscrypt_policy *policy = NULL;
int err; int err;
if (arg->from) { if (!arg)
argstr = argstr_to_free = match_strdup(arg); arg = "v2";
if (!argstr)
return -ENOMEM;
}
if (!strcmp(argstr, "v1")) { if (!strcmp(arg, "v1")) {
version = FSCRYPT_CONTEXT_V1; version = FSCRYPT_POLICY_V1;
key_spec.type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR; key_spec.type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR;
memset(key_spec.u.descriptor, 0x42, memset(key_spec.u.descriptor, 0x42,
FSCRYPT_KEY_DESCRIPTOR_SIZE); FSCRYPT_KEY_DESCRIPTOR_SIZE);
} else if (!strcmp(argstr, "v2")) { } else if (!strcmp(arg, "v2")) {
version = FSCRYPT_CONTEXT_V2; version = FSCRYPT_POLICY_V2;
key_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER; key_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
/* key_spec.u.identifier gets filled in when adding the key */ /* key_spec.u.identifier gets filled in when adding the key */
} else { } else {
@ -707,21 +736,8 @@ int fscrypt_set_test_dummy_encryption(struct super_block *sb,
goto out; goto out;
} }
if (dummy_ctx->ctx) { policy = kzalloc(sizeof(*policy), GFP_KERNEL);
/* if (!policy) {
* Note: if we ever make test_dummy_encryption support
* specifying other encryption settings, such as the encryption
* modes, we'll need to compare those settings here.
*/
if (dummy_ctx->ctx->version == version)
err = 0;
else
err = -EEXIST;
goto out;
}
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx) {
err = -ENOMEM; err = -ENOMEM;
goto out; goto out;
} }
@ -730,18 +746,18 @@ int fscrypt_set_test_dummy_encryption(struct super_block *sb,
if (err) if (err)
goto out; goto out;
ctx->version = version; policy->version = version;
switch (ctx->version) { switch (policy->version) {
case FSCRYPT_CONTEXT_V1: case FSCRYPT_POLICY_V1:
ctx->v1.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS; policy->v1.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS;
ctx->v1.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS; policy->v1.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS;
memcpy(ctx->v1.master_key_descriptor, key_spec.u.descriptor, memcpy(policy->v1.master_key_descriptor, key_spec.u.descriptor,
FSCRYPT_KEY_DESCRIPTOR_SIZE); FSCRYPT_KEY_DESCRIPTOR_SIZE);
break; break;
case FSCRYPT_CONTEXT_V2: case FSCRYPT_POLICY_V2:
ctx->v2.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS; policy->v2.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS;
ctx->v2.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS; policy->v2.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS;
memcpy(ctx->v2.master_key_identifier, key_spec.u.identifier, memcpy(policy->v2.master_key_identifier, key_spec.u.identifier,
FSCRYPT_KEY_IDENTIFIER_SIZE); FSCRYPT_KEY_IDENTIFIER_SIZE);
break; break;
default: default:
@ -749,12 +765,19 @@ int fscrypt_set_test_dummy_encryption(struct super_block *sb,
err = -EINVAL; err = -EINVAL;
goto out; goto out;
} }
dummy_ctx->ctx = ctx;
ctx = NULL; if (dummy_policy->policy) {
if (fscrypt_policies_equal(policy, dummy_policy->policy))
err = 0;
else
err = -EEXIST;
goto out;
}
dummy_policy->policy = policy;
policy = NULL;
err = 0; err = 0;
out: out:
kfree(ctx); kfree(policy);
kfree(argstr_to_free);
return err; return err;
} }
EXPORT_SYMBOL_GPL(fscrypt_set_test_dummy_encryption); EXPORT_SYMBOL_GPL(fscrypt_set_test_dummy_encryption);
@ -771,10 +794,16 @@ EXPORT_SYMBOL_GPL(fscrypt_set_test_dummy_encryption);
void fscrypt_show_test_dummy_encryption(struct seq_file *seq, char sep, void fscrypt_show_test_dummy_encryption(struct seq_file *seq, char sep,
struct super_block *sb) struct super_block *sb)
{ {
const union fscrypt_context *ctx = fscrypt_get_dummy_context(sb); const union fscrypt_policy *policy = fscrypt_get_dummy_policy(sb);
int vers;
if (!ctx) if (!policy)
return; return;
seq_printf(seq, "%ctest_dummy_encryption=v%d", sep, ctx->version);
vers = policy->version;
if (vers == FSCRYPT_POLICY_V1) /* Handle numbering quirk */
vers = 1;
seq_printf(seq, "%ctest_dummy_encryption=v%d", sep, vers);
} }
EXPORT_SYMBOL_GPL(fscrypt_show_test_dummy_encryption); EXPORT_SYMBOL_GPL(fscrypt_show_test_dummy_encryption);

View File

@ -148,7 +148,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
} }
if (IS_ENCRYPTED(inode)) { if (IS_ENCRYPTED(inode)) {
err = fscrypt_fname_alloc_buffer(inode, EXT4_NAME_LEN, &fstr); err = fscrypt_fname_alloc_buffer(EXT4_NAME_LEN, &fstr);
if (err < 0) if (err < 0)
return err; return err;
} }

View File

@ -1401,7 +1401,7 @@ struct ext4_super_block {
#define EXT4_MF_FS_ABORTED 0x0002 /* Fatal error detected */ #define EXT4_MF_FS_ABORTED 0x0002 /* Fatal error detected */
#ifdef CONFIG_FS_ENCRYPTION #ifdef CONFIG_FS_ENCRYPTION
#define DUMMY_ENCRYPTION_ENABLED(sbi) ((sbi)->s_dummy_enc_ctx.ctx != NULL) #define DUMMY_ENCRYPTION_ENABLED(sbi) ((sbi)->s_dummy_enc_policy.policy != NULL)
#else #else
#define DUMMY_ENCRYPTION_ENABLED(sbi) (0) #define DUMMY_ENCRYPTION_ENABLED(sbi) (0)
#endif #endif
@ -1596,8 +1596,8 @@ struct ext4_sb_info {
atomic_t s_warning_count; atomic_t s_warning_count;
atomic_t s_msg_count; atomic_t s_msg_count;
/* Encryption context for '-o test_dummy_encryption' */ /* Encryption policy for '-o test_dummy_encryption' */
struct fscrypt_dummy_context s_dummy_enc_ctx; struct fscrypt_dummy_policy s_dummy_enc_policy;
/* /*
* Barrier between writepages ops and changing any inode's JOURNAL_DATA * Barrier between writepages ops and changing any inode's JOURNAL_DATA

View File

@ -742,6 +742,53 @@ not_found:
return 1; return 1;
} }
static int ext4_xattr_credits_for_new_inode(struct inode *dir, mode_t mode,
bool encrypt)
{
struct super_block *sb = dir->i_sb;
int nblocks = 0;
#ifdef CONFIG_EXT4_FS_POSIX_ACL
struct posix_acl *p = get_acl(dir, ACL_TYPE_DEFAULT);
if (IS_ERR(p))
return PTR_ERR(p);
if (p) {
int acl_size = p->a_count * sizeof(ext4_acl_entry);
nblocks += (S_ISDIR(mode) ? 2 : 1) *
__ext4_xattr_set_credits(sb, NULL /* inode */,
NULL /* block_bh */, acl_size,
true /* is_create */);
posix_acl_release(p);
}
#endif
#ifdef CONFIG_SECURITY
{
int num_security_xattrs = 1;
#ifdef CONFIG_INTEGRITY
num_security_xattrs++;
#endif
/*
* We assume that security xattrs are never more than 1k.
* In practice they are under 128 bytes.
*/
nblocks += num_security_xattrs *
__ext4_xattr_set_credits(sb, NULL /* inode */,
NULL /* block_bh */, 1024,
true /* is_create */);
}
#endif
if (encrypt)
nblocks += __ext4_xattr_set_credits(sb,
NULL /* inode */,
NULL /* block_bh */,
FSCRYPT_SET_CONTEXT_MAX_SIZE,
true /* is_create */);
return nblocks;
}
/* /*
* There are two policies for allocating an inode. If the new inode is * There are two policies for allocating an inode. If the new inode is
* a directory, then a forward search is made for a block group with both * a directory, then a forward search is made for a block group with both
@ -772,7 +819,7 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
ext4_group_t i; ext4_group_t i;
ext4_group_t flex_group; ext4_group_t flex_group;
struct ext4_group_info *grp; struct ext4_group_info *grp;
int encrypt = 0; bool encrypt = false;
/* Cannot create files in a deleted directory */ /* Cannot create files in a deleted directory */
if (!dir || !dir->i_nlink) if (!dir || !dir->i_nlink)
@ -784,59 +831,6 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
if (unlikely(ext4_forced_shutdown(sbi))) if (unlikely(ext4_forced_shutdown(sbi)))
return ERR_PTR(-EIO); return ERR_PTR(-EIO);
if ((IS_ENCRYPTED(dir) || DUMMY_ENCRYPTION_ENABLED(sbi)) &&
(S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) &&
!(i_flags & EXT4_EA_INODE_FL)) {
err = fscrypt_get_encryption_info(dir);
if (err)
return ERR_PTR(err);
if (!fscrypt_has_encryption_key(dir))
return ERR_PTR(-ENOKEY);
encrypt = 1;
}
if (!handle && sbi->s_journal && !(i_flags & EXT4_EA_INODE_FL)) {
#ifdef CONFIG_EXT4_FS_POSIX_ACL
struct posix_acl *p = get_acl(dir, ACL_TYPE_DEFAULT);
if (IS_ERR(p))
return ERR_CAST(p);
if (p) {
int acl_size = p->a_count * sizeof(ext4_acl_entry);
nblocks += (S_ISDIR(mode) ? 2 : 1) *
__ext4_xattr_set_credits(sb, NULL /* inode */,
NULL /* block_bh */, acl_size,
true /* is_create */);
posix_acl_release(p);
}
#endif
#ifdef CONFIG_SECURITY
{
int num_security_xattrs = 1;
#ifdef CONFIG_INTEGRITY
num_security_xattrs++;
#endif
/*
* We assume that security xattrs are never
* more than 1k. In practice they are under
* 128 bytes.
*/
nblocks += num_security_xattrs *
__ext4_xattr_set_credits(sb, NULL /* inode */,
NULL /* block_bh */, 1024,
true /* is_create */);
}
#endif
if (encrypt)
nblocks += __ext4_xattr_set_credits(sb,
NULL /* inode */, NULL /* block_bh */,
FSCRYPT_SET_CONTEXT_MAX_SIZE,
true /* is_create */);
}
ngroups = ext4_get_groups_count(sb); ngroups = ext4_get_groups_count(sb);
trace_ext4_request_inode(dir, mode); trace_ext4_request_inode(dir, mode);
inode = new_inode(sb); inode = new_inode(sb);
@ -866,10 +860,25 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
else else
ei->i_projid = make_kprojid(&init_user_ns, EXT4_DEF_PROJID); ei->i_projid = make_kprojid(&init_user_ns, EXT4_DEF_PROJID);
if (!(i_flags & EXT4_EA_INODE_FL)) {
err = fscrypt_prepare_new_inode(dir, inode, &encrypt);
if (err)
goto out;
}
err = dquot_initialize(inode); err = dquot_initialize(inode);
if (err) if (err)
goto out; goto out;
if (!handle && sbi->s_journal && !(i_flags & EXT4_EA_INODE_FL)) {
ret2 = ext4_xattr_credits_for_new_inode(dir, mode, encrypt);
if (ret2 < 0) {
err = ret2;
goto out;
}
nblocks += ret2;
}
if (!goal) if (!goal)
goal = sbi->s_inode_goal; goal = sbi->s_inode_goal;
@ -1162,7 +1171,7 @@ got:
* prevent its deduplication. * prevent its deduplication.
*/ */
if (encrypt) { if (encrypt) {
err = fscrypt_inherit_context(dir, inode, handle, true); err = fscrypt_set_context(inode, handle);
if (err) if (err)
goto fail_free_drop; goto fail_free_drop;
} }

View File

@ -663,8 +663,7 @@ static struct stats dx_show_leaf(struct inode *dir,
/* Directory is encrypted */ /* Directory is encrypted */
res = fscrypt_fname_alloc_buffer( res = fscrypt_fname_alloc_buffer(
dir, len, len, &fname_crypto_str);
&fname_crypto_str);
if (res) if (res)
printk(KERN_WARNING "Error " printk(KERN_WARNING "Error "
"allocating crypto " "allocating crypto "
@ -1016,7 +1015,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
brelse(bh); brelse(bh);
return err; return err;
} }
err = fscrypt_fname_alloc_buffer(dir, EXT4_NAME_LEN, err = fscrypt_fname_alloc_buffer(EXT4_NAME_LEN,
&fname_crypto_str); &fname_crypto_str);
if (err < 0) { if (err < 0) {
brelse(bh); brelse(bh);

View File

@ -1104,7 +1104,7 @@ static void ext4_put_super(struct super_block *sb)
crypto_free_shash(sbi->s_chksum_driver); crypto_free_shash(sbi->s_chksum_driver);
kfree(sbi->s_blockgroup_lock); kfree(sbi->s_blockgroup_lock);
fs_put_dax(sbi->s_daxdev); fs_put_dax(sbi->s_daxdev);
fscrypt_free_dummy_context(&sbi->s_dummy_enc_ctx); fscrypt_free_dummy_policy(&sbi->s_dummy_enc_policy);
#ifdef CONFIG_UNICODE #ifdef CONFIG_UNICODE
utf8_unload(sbi->s_encoding); utf8_unload(sbi->s_encoding);
#endif #endif
@ -1392,10 +1392,9 @@ retry:
return res; return res;
} }
static const union fscrypt_context * static const union fscrypt_policy *ext4_get_dummy_policy(struct super_block *sb)
ext4_get_dummy_context(struct super_block *sb)
{ {
return EXT4_SB(sb)->s_dummy_enc_ctx.ctx; return EXT4_SB(sb)->s_dummy_enc_policy.policy;
} }
static bool ext4_has_stable_inodes(struct super_block *sb) static bool ext4_has_stable_inodes(struct super_block *sb)
@ -1414,7 +1413,7 @@ static const struct fscrypt_operations ext4_cryptops = {
.key_prefix = "ext4:", .key_prefix = "ext4:",
.get_context = ext4_get_context, .get_context = ext4_get_context,
.set_context = ext4_set_context, .set_context = ext4_set_context,
.get_dummy_context = ext4_get_dummy_context, .get_dummy_policy = ext4_get_dummy_policy,
.empty_dir = ext4_empty_dir, .empty_dir = ext4_empty_dir,
.max_namelen = EXT4_NAME_LEN, .max_namelen = EXT4_NAME_LEN,
.has_stable_inodes = ext4_has_stable_inodes, .has_stable_inodes = ext4_has_stable_inodes,
@ -1888,12 +1887,13 @@ static int ext4_set_test_dummy_encryption(struct super_block *sb,
* needed to allow it to be set or changed during remount. We do allow * needed to allow it to be set or changed during remount. We do allow
* it to be specified during remount, but only if there is no change. * it to be specified during remount, but only if there is no change.
*/ */
if (is_remount && !sbi->s_dummy_enc_ctx.ctx) { if (is_remount && !sbi->s_dummy_enc_policy.policy) {
ext4_msg(sb, KERN_WARNING, ext4_msg(sb, KERN_WARNING,
"Can't set test_dummy_encryption on remount"); "Can't set test_dummy_encryption on remount");
return -1; return -1;
} }
err = fscrypt_set_test_dummy_encryption(sb, arg, &sbi->s_dummy_enc_ctx); err = fscrypt_set_test_dummy_encryption(sb, arg->from,
&sbi->s_dummy_enc_policy);
if (err) { if (err) {
if (err == -EEXIST) if (err == -EEXIST)
ext4_msg(sb, KERN_WARNING, ext4_msg(sb, KERN_WARNING,
@ -4935,7 +4935,7 @@ failed_mount:
for (i = 0; i < EXT4_MAXQUOTAS; i++) for (i = 0; i < EXT4_MAXQUOTAS; i++)
kfree(get_qf_name(sb, sbi, i)); kfree(get_qf_name(sb, sbi, i));
#endif #endif
fscrypt_free_dummy_context(&sbi->s_dummy_enc_ctx); fscrypt_free_dummy_policy(&sbi->s_dummy_enc_policy);
ext4_blkdev_remove(sbi); ext4_blkdev_remove(sbi);
brelse(bh); brelse(bh);
out_fail: out_fail:

View File

@ -111,7 +111,7 @@ static int __f2fs_setup_filename(const struct inode *dir,
#ifdef CONFIG_FS_ENCRYPTION #ifdef CONFIG_FS_ENCRYPTION
fname->crypto_buf = crypt_name->crypto_buf; fname->crypto_buf = crypt_name->crypto_buf;
#endif #endif
if (crypt_name->is_ciphertext_name) { if (crypt_name->is_nokey_name) {
/* hash was decoded from the no-key name */ /* hash was decoded from the no-key name */
fname->hash = cpu_to_le32(crypt_name->hash); fname->hash = cpu_to_le32(crypt_name->hash);
} else { } else {
@ -537,7 +537,7 @@ struct page *f2fs_init_inode_metadata(struct inode *inode, struct inode *dir,
goto put_error; goto put_error;
if (IS_ENCRYPTED(inode)) { if (IS_ENCRYPTED(inode)) {
err = fscrypt_inherit_context(dir, inode, page, false); err = fscrypt_set_context(inode, page);
if (err) if (err)
goto put_error; goto put_error;
} }
@ -1032,7 +1032,7 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
if (err) if (err)
goto out; goto out;
err = fscrypt_fname_alloc_buffer(inode, F2FS_NAME_LEN, &fstr); err = fscrypt_fname_alloc_buffer(F2FS_NAME_LEN, &fstr);
if (err < 0) if (err < 0)
goto out; goto out;
} }

View File

@ -138,7 +138,7 @@ struct f2fs_mount_info {
int fsync_mode; /* fsync policy */ int fsync_mode; /* fsync policy */
int fs_mode; /* fs mode: LFS or ADAPTIVE */ int fs_mode; /* fs mode: LFS or ADAPTIVE */
int bggc_mode; /* bggc mode: off, on or sync */ int bggc_mode; /* bggc mode: off, on or sync */
struct fscrypt_dummy_context dummy_enc_ctx; /* test dummy encryption */ struct fscrypt_dummy_policy dummy_enc_policy; /* test dummy encryption */
block_t unusable_cap_perc; /* percentage for cap */ block_t unusable_cap_perc; /* percentage for cap */
block_t unusable_cap; /* Amount of space allowed to be block_t unusable_cap; /* Amount of space allowed to be
* unusable when disabling checkpoint * unusable when disabling checkpoint
@ -1315,13 +1315,6 @@ enum fsync_mode {
#define IS_IO_TRACED_PAGE(page) (0) #define IS_IO_TRACED_PAGE(page) (0)
#endif #endif
#ifdef CONFIG_FS_ENCRYPTION
#define DUMMY_ENCRYPTION_ENABLED(sbi) \
(unlikely(F2FS_OPTION(sbi).dummy_enc_ctx.ctx != NULL))
#else
#define DUMMY_ENCRYPTION_ENABLED(sbi) (0)
#endif
/* For compression */ /* For compression */
enum compress_algorithm_type { enum compress_algorithm_type {
COMPRESS_LZO, COMPRESS_LZO,
@ -4022,22 +4015,6 @@ static inline bool f2fs_lfs_mode(struct f2fs_sb_info *sbi)
return F2FS_OPTION(sbi).fs_mode == FS_MODE_LFS; return F2FS_OPTION(sbi).fs_mode == FS_MODE_LFS;
} }
static inline bool f2fs_may_encrypt(struct inode *dir, struct inode *inode)
{
#ifdef CONFIG_FS_ENCRYPTION
struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
umode_t mode = inode->i_mode;
/*
* If the directory encrypted or dummy encryption enabled,
* then we should encrypt the inode.
*/
if (IS_ENCRYPTED(dir) || DUMMY_ENCRYPTION_ENABLED(sbi))
return (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode));
#endif
return false;
}
static inline bool f2fs_may_compress(struct inode *inode) static inline bool f2fs_may_compress(struct inode *inode)
{ {
if (IS_SWAPFILE(inode) || f2fs_is_pinned_file(inode) || if (IS_SWAPFILE(inode) || f2fs_is_pinned_file(inode) ||

View File

@ -28,6 +28,7 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
nid_t ino; nid_t ino;
struct inode *inode; struct inode *inode;
bool nid_free = false; bool nid_free = false;
bool encrypt = false;
int xattr_size = 0; int xattr_size = 0;
int err; int err;
@ -69,13 +70,17 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
F2FS_I(inode)->i_projid = make_kprojid(&init_user_ns, F2FS_I(inode)->i_projid = make_kprojid(&init_user_ns,
F2FS_DEF_PROJID); F2FS_DEF_PROJID);
err = fscrypt_prepare_new_inode(dir, inode, &encrypt);
if (err)
goto fail_drop;
err = dquot_initialize(inode); err = dquot_initialize(inode);
if (err) if (err)
goto fail_drop; goto fail_drop;
set_inode_flag(inode, FI_NEW_INODE); set_inode_flag(inode, FI_NEW_INODE);
if (f2fs_may_encrypt(dir, inode)) if (encrypt)
f2fs_set_encrypted_inode(inode); f2fs_set_encrypted_inode(inode);
if (f2fs_sb_has_extra_attr(sbi)) { if (f2fs_sb_has_extra_attr(sbi)) {

View File

@ -433,12 +433,12 @@ static int f2fs_set_test_dummy_encryption(struct super_block *sb,
* needed to allow it to be set or changed during remount. We do allow * needed to allow it to be set or changed during remount. We do allow
* it to be specified during remount, but only if there is no change. * it to be specified during remount, but only if there is no change.
*/ */
if (is_remount && !F2FS_OPTION(sbi).dummy_enc_ctx.ctx) { if (is_remount && !F2FS_OPTION(sbi).dummy_enc_policy.policy) {
f2fs_warn(sbi, "Can't set test_dummy_encryption on remount"); f2fs_warn(sbi, "Can't set test_dummy_encryption on remount");
return -EINVAL; return -EINVAL;
} }
err = fscrypt_set_test_dummy_encryption( err = fscrypt_set_test_dummy_encryption(
sb, arg, &F2FS_OPTION(sbi).dummy_enc_ctx); sb, arg->from, &F2FS_OPTION(sbi).dummy_enc_policy);
if (err) { if (err) {
if (err == -EEXIST) if (err == -EEXIST)
f2fs_warn(sbi, f2fs_warn(sbi,
@ -1275,7 +1275,7 @@ static void f2fs_put_super(struct super_block *sb)
for (i = 0; i < MAXQUOTAS; i++) for (i = 0; i < MAXQUOTAS; i++)
kfree(F2FS_OPTION(sbi).s_qf_names[i]); kfree(F2FS_OPTION(sbi).s_qf_names[i]);
#endif #endif
fscrypt_free_dummy_context(&F2FS_OPTION(sbi).dummy_enc_ctx); fscrypt_free_dummy_policy(&F2FS_OPTION(sbi).dummy_enc_policy);
destroy_percpu_info(sbi); destroy_percpu_info(sbi);
for (i = 0; i < NR_PAGE_TYPE; i++) for (i = 0; i < NR_PAGE_TYPE; i++)
kvfree(sbi->write_io[i]); kvfree(sbi->write_io[i]);
@ -2482,10 +2482,9 @@ static int f2fs_set_context(struct inode *inode, const void *ctx, size_t len,
ctx, len, fs_data, XATTR_CREATE); ctx, len, fs_data, XATTR_CREATE);
} }
static const union fscrypt_context * static const union fscrypt_policy *f2fs_get_dummy_policy(struct super_block *sb)
f2fs_get_dummy_context(struct super_block *sb)
{ {
return F2FS_OPTION(F2FS_SB(sb)).dummy_enc_ctx.ctx; return F2FS_OPTION(F2FS_SB(sb)).dummy_enc_policy.policy;
} }
static bool f2fs_has_stable_inodes(struct super_block *sb) static bool f2fs_has_stable_inodes(struct super_block *sb)
@ -2523,7 +2522,7 @@ static const struct fscrypt_operations f2fs_cryptops = {
.key_prefix = "f2fs:", .key_prefix = "f2fs:",
.get_context = f2fs_get_context, .get_context = f2fs_get_context,
.set_context = f2fs_set_context, .set_context = f2fs_set_context,
.get_dummy_context = f2fs_get_dummy_context, .get_dummy_policy = f2fs_get_dummy_policy,
.empty_dir = f2fs_empty_dir, .empty_dir = f2fs_empty_dir,
.max_namelen = F2FS_NAME_LEN, .max_namelen = F2FS_NAME_LEN,
.has_stable_inodes = f2fs_has_stable_inodes, .has_stable_inodes = f2fs_has_stable_inodes,
@ -3864,7 +3863,7 @@ free_options:
for (i = 0; i < MAXQUOTAS; i++) for (i = 0; i < MAXQUOTAS; i++)
kfree(F2FS_OPTION(sbi).s_qf_names[i]); kfree(F2FS_OPTION(sbi).s_qf_names[i]);
#endif #endif
fscrypt_free_dummy_context(&F2FS_OPTION(sbi).dummy_enc_ctx); fscrypt_free_dummy_policy(&F2FS_OPTION(sbi).dummy_enc_policy);
kvfree(options); kvfree(options);
free_sb_buf: free_sb_buf:
kfree(raw_super); kfree(raw_super);

View File

@ -81,19 +81,6 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir,
struct ubifs_inode *ui; struct ubifs_inode *ui;
bool encrypted = false; bool encrypted = false;
if (IS_ENCRYPTED(dir)) {
err = fscrypt_get_encryption_info(dir);
if (err) {
ubifs_err(c, "fscrypt_get_encryption_info failed: %i", err);
return ERR_PTR(err);
}
if (!fscrypt_has_encryption_key(dir))
return ERR_PTR(-EPERM);
encrypted = true;
}
inode = new_inode(c->vfs_sb); inode = new_inode(c->vfs_sb);
ui = ubifs_inode(inode); ui = ubifs_inode(inode);
if (!inode) if (!inode)
@ -112,6 +99,12 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir,
current_time(inode); current_time(inode);
inode->i_mapping->nrpages = 0; inode->i_mapping->nrpages = 0;
err = fscrypt_prepare_new_inode(dir, inode, &encrypted);
if (err) {
ubifs_err(c, "fscrypt_prepare_new_inode failed: %i", err);
goto out_iput;
}
switch (mode & S_IFMT) { switch (mode & S_IFMT) {
case S_IFREG: case S_IFREG:
inode->i_mapping->a_ops = &ubifs_file_address_operations; inode->i_mapping->a_ops = &ubifs_file_address_operations;
@ -131,7 +124,6 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir,
case S_IFBLK: case S_IFBLK:
case S_IFCHR: case S_IFCHR:
inode->i_op = &ubifs_file_inode_operations; inode->i_op = &ubifs_file_inode_operations;
encrypted = false;
break; break;
default: default:
BUG(); BUG();
@ -151,9 +143,8 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir,
if (c->highest_inum >= INUM_WATERMARK) { if (c->highest_inum >= INUM_WATERMARK) {
spin_unlock(&c->cnt_lock); spin_unlock(&c->cnt_lock);
ubifs_err(c, "out of inode numbers"); ubifs_err(c, "out of inode numbers");
make_bad_inode(inode); err = -EINVAL;
iput(inode); goto out_iput;
return ERR_PTR(-EINVAL);
} }
ubifs_warn(c, "running out of inode numbers (current %lu, max %u)", ubifs_warn(c, "running out of inode numbers (current %lu, max %u)",
(unsigned long)c->highest_inum, INUM_WATERMARK); (unsigned long)c->highest_inum, INUM_WATERMARK);
@ -171,16 +162,19 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir,
spin_unlock(&c->cnt_lock); spin_unlock(&c->cnt_lock);
if (encrypted) { if (encrypted) {
err = fscrypt_inherit_context(dir, inode, &encrypted, true); err = fscrypt_set_context(inode, NULL);
if (err) { if (err) {
ubifs_err(c, "fscrypt_inherit_context failed: %i", err); ubifs_err(c, "fscrypt_set_context failed: %i", err);
make_bad_inode(inode); goto out_iput;
iput(inode);
return ERR_PTR(err);
} }
} }
return inode; return inode;
out_iput:
make_bad_inode(inode);
iput(inode);
return ERR_PTR(err);
} }
static int dbg_check_name(const struct ubifs_info *c, static int dbg_check_name(const struct ubifs_info *c,
@ -515,7 +509,7 @@ static int ubifs_readdir(struct file *file, struct dir_context *ctx)
if (err) if (err)
return err; return err;
err = fscrypt_fname_alloc_buffer(dir, UBIFS_MAX_NLEN, &fstr); err = fscrypt_fname_alloc_buffer(UBIFS_MAX_NLEN, &fstr);
if (err) if (err)
return err; return err;

View File

@ -213,7 +213,7 @@ struct dentry_operations {
#define DCACHE_MAY_FREE 0x00800000 #define DCACHE_MAY_FREE 0x00800000
#define DCACHE_FALLTHRU 0x01000000 /* Fall through to lower layer */ #define DCACHE_FALLTHRU 0x01000000 /* Fall through to lower layer */
#define DCACHE_ENCRYPTED_NAME 0x02000000 /* Encrypted name (dir key was unavailable) */ #define DCACHE_NOKEY_NAME 0x02000000 /* Encrypted name encoded without key */
#define DCACHE_OP_REAL 0x04000000 #define DCACHE_OP_REAL 0x04000000
#define DCACHE_PAR_LOOKUP 0x10000000 /* being looked up (with parent locked shared) */ #define DCACHE_PAR_LOOKUP 0x10000000 /* being looked up (with parent locked shared) */

View File

@ -15,13 +15,12 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/parser.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <uapi/linux/fscrypt.h> #include <uapi/linux/fscrypt.h>
#define FS_CRYPTO_BLOCK_SIZE 16 #define FS_CRYPTO_BLOCK_SIZE 16
union fscrypt_context; union fscrypt_policy;
struct fscrypt_info; struct fscrypt_info;
struct seq_file; struct seq_file;
@ -36,7 +35,7 @@ struct fscrypt_name {
u32 hash; u32 hash;
u32 minor_hash; u32 minor_hash;
struct fscrypt_str crypto_buf; struct fscrypt_str crypto_buf;
bool is_ciphertext_name; bool is_nokey_name;
}; };
#define FSTR_INIT(n, l) { .name = n, .len = l } #define FSTR_INIT(n, l) { .name = n, .len = l }
@ -62,8 +61,7 @@ struct fscrypt_operations {
int (*get_context)(struct inode *inode, void *ctx, size_t len); int (*get_context)(struct inode *inode, void *ctx, size_t len);
int (*set_context)(struct inode *inode, const void *ctx, size_t len, int (*set_context)(struct inode *inode, const void *ctx, size_t len,
void *fs_data); void *fs_data);
const union fscrypt_context *(*get_dummy_context)( const union fscrypt_policy *(*get_dummy_policy)(struct super_block *sb);
struct super_block *sb);
bool (*empty_dir)(struct inode *inode); bool (*empty_dir)(struct inode *inode);
unsigned int max_namelen; unsigned int max_namelen;
bool (*has_stable_inodes)(struct super_block *sb); bool (*has_stable_inodes)(struct super_block *sb);
@ -101,24 +99,16 @@ static inline bool fscrypt_needs_contents_encryption(const struct inode *inode)
return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode); return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode);
} }
static inline const union fscrypt_context *
fscrypt_get_dummy_context(struct super_block *sb)
{
if (!sb->s_cop->get_dummy_context)
return NULL;
return sb->s_cop->get_dummy_context(sb);
}
/* /*
* When d_splice_alias() moves a directory's encrypted alias to its decrypted * When d_splice_alias() moves a directory's no-key alias to its plaintext alias
* alias as a result of the encryption key being added, DCACHE_ENCRYPTED_NAME * as a result of the encryption key being added, DCACHE_NOKEY_NAME must be
* must be cleared. Note that we don't have to support arbitrary moves of this * cleared. Note that we don't have to support arbitrary moves of this flag
* flag because fscrypt doesn't allow encrypted aliases to be the source or * because fscrypt doesn't allow no-key names to be the source or target of a
* target of a rename(). * rename().
*/ */
static inline void fscrypt_handle_d_move(struct dentry *dentry) static inline void fscrypt_handle_d_move(struct dentry *dentry)
{ {
dentry->d_flags &= ~DCACHE_ENCRYPTED_NAME; dentry->d_flags &= ~DCACHE_NOKEY_NAME;
} }
/* crypto.c */ /* crypto.c */
@ -156,23 +146,21 @@ int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg);
int fscrypt_ioctl_get_policy_ex(struct file *filp, void __user *arg); int fscrypt_ioctl_get_policy_ex(struct file *filp, void __user *arg);
int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg); int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg);
int fscrypt_has_permitted_context(struct inode *parent, struct inode *child); int fscrypt_has_permitted_context(struct inode *parent, struct inode *child);
int fscrypt_inherit_context(struct inode *parent, struct inode *child, int fscrypt_set_context(struct inode *inode, void *fs_data);
void *fs_data, bool preload);
struct fscrypt_dummy_context { struct fscrypt_dummy_policy {
const union fscrypt_context *ctx; const union fscrypt_policy *policy;
}; };
int fscrypt_set_test_dummy_encryption(struct super_block *sb, int fscrypt_set_test_dummy_encryption(struct super_block *sb, const char *arg,
const substring_t *arg, struct fscrypt_dummy_policy *dummy_policy);
struct fscrypt_dummy_context *dummy_ctx);
void fscrypt_show_test_dummy_encryption(struct seq_file *seq, char sep, void fscrypt_show_test_dummy_encryption(struct seq_file *seq, char sep,
struct super_block *sb); struct super_block *sb);
static inline void static inline void
fscrypt_free_dummy_context(struct fscrypt_dummy_context *dummy_ctx) fscrypt_free_dummy_policy(struct fscrypt_dummy_policy *dummy_policy)
{ {
kfree(dummy_ctx->ctx); kfree(dummy_policy->policy);
dummy_ctx->ctx = NULL; dummy_policy->policy = NULL;
} }
/* keyring.c */ /* keyring.c */
@ -184,6 +172,8 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *arg);
/* keysetup.c */ /* keysetup.c */
int fscrypt_get_encryption_info(struct inode *inode); int fscrypt_get_encryption_info(struct inode *inode);
int fscrypt_prepare_new_inode(struct inode *dir, struct inode *inode,
bool *encrypt_ret);
void fscrypt_put_encryption_info(struct inode *inode); void fscrypt_put_encryption_info(struct inode *inode);
void fscrypt_free_inode(struct inode *inode); void fscrypt_free_inode(struct inode *inode);
int fscrypt_drop_inode(struct inode *inode); int fscrypt_drop_inode(struct inode *inode);
@ -197,7 +187,7 @@ static inline void fscrypt_free_filename(struct fscrypt_name *fname)
kfree(fname->crypto_buf.name); kfree(fname->crypto_buf.name);
} }
int fscrypt_fname_alloc_buffer(const struct inode *inode, u32 max_encrypted_len, int fscrypt_fname_alloc_buffer(u32 max_encrypted_len,
struct fscrypt_str *crypto_str); struct fscrypt_str *crypto_str);
void fscrypt_fname_free_buffer(struct fscrypt_str *crypto_str); void fscrypt_fname_free_buffer(struct fscrypt_str *crypto_str);
int fscrypt_fname_disk_to_usr(const struct inode *inode, int fscrypt_fname_disk_to_usr(const struct inode *inode,
@ -207,6 +197,7 @@ int fscrypt_fname_disk_to_usr(const struct inode *inode,
bool fscrypt_match_name(const struct fscrypt_name *fname, bool fscrypt_match_name(const struct fscrypt_name *fname,
const u8 *de_name, u32 de_name_len); const u8 *de_name, u32 de_name_len);
u64 fscrypt_fname_siphash(const struct inode *dir, const struct qstr *name); u64 fscrypt_fname_siphash(const struct inode *dir, const struct qstr *name);
int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags);
/* bio.c */ /* bio.c */
void fscrypt_decrypt_bio(struct bio *bio); void fscrypt_decrypt_bio(struct bio *bio);
@ -224,8 +215,8 @@ int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry,
struct fscrypt_name *fname); struct fscrypt_name *fname);
int fscrypt_prepare_setflags(struct inode *inode, int fscrypt_prepare_setflags(struct inode *inode,
unsigned int oldflags, unsigned int flags); unsigned int oldflags, unsigned int flags);
int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len, int fscrypt_prepare_symlink(struct inode *dir, const char *target,
unsigned int max_len, unsigned int len, unsigned int max_len,
struct fscrypt_str *disk_link); struct fscrypt_str *disk_link);
int __fscrypt_encrypt_symlink(struct inode *inode, const char *target, int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
unsigned int len, struct fscrypt_str *disk_link); unsigned int len, struct fscrypt_str *disk_link);
@ -249,12 +240,6 @@ static inline bool fscrypt_needs_contents_encryption(const struct inode *inode)
return false; return false;
} }
static inline const union fscrypt_context *
fscrypt_get_dummy_context(struct super_block *sb)
{
return NULL;
}
static inline void fscrypt_handle_d_move(struct dentry *dentry) static inline void fscrypt_handle_d_move(struct dentry *dentry)
{ {
} }
@ -340,14 +325,12 @@ static inline int fscrypt_has_permitted_context(struct inode *parent,
return 0; return 0;
} }
static inline int fscrypt_inherit_context(struct inode *parent, static inline int fscrypt_set_context(struct inode *inode, void *fs_data)
struct inode *child,
void *fs_data, bool preload)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
struct fscrypt_dummy_context { struct fscrypt_dummy_policy {
}; };
static inline void fscrypt_show_test_dummy_encryption(struct seq_file *seq, static inline void fscrypt_show_test_dummy_encryption(struct seq_file *seq,
@ -357,7 +340,7 @@ static inline void fscrypt_show_test_dummy_encryption(struct seq_file *seq,
} }
static inline void static inline void
fscrypt_free_dummy_context(struct fscrypt_dummy_context *dummy_ctx) fscrypt_free_dummy_policy(struct fscrypt_dummy_policy *dummy_policy)
{ {
} }
@ -394,6 +377,15 @@ static inline int fscrypt_get_encryption_info(struct inode *inode)
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline int fscrypt_prepare_new_inode(struct inode *dir,
struct inode *inode,
bool *encrypt_ret)
{
if (IS_ENCRYPTED(dir))
return -EOPNOTSUPP;
return 0;
}
static inline void fscrypt_put_encryption_info(struct inode *inode) static inline void fscrypt_put_encryption_info(struct inode *inode)
{ {
return; return;
@ -428,8 +420,7 @@ static inline void fscrypt_free_filename(struct fscrypt_name *fname)
return; return;
} }
static inline int fscrypt_fname_alloc_buffer(const struct inode *inode, static inline int fscrypt_fname_alloc_buffer(u32 max_encrypted_len,
u32 max_encrypted_len,
struct fscrypt_str *crypto_str) struct fscrypt_str *crypto_str)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
@ -464,6 +455,12 @@ static inline u64 fscrypt_fname_siphash(const struct inode *dir,
return 0; return 0;
} }
static inline int fscrypt_d_revalidate(struct dentry *dentry,
unsigned int flags)
{
return 1;
}
/* bio.c */ /* bio.c */
static inline void fscrypt_decrypt_bio(struct bio *bio) static inline void fscrypt_decrypt_bio(struct bio *bio)
{ {
@ -513,15 +510,21 @@ static inline int fscrypt_prepare_setflags(struct inode *inode,
return 0; return 0;
} }
static inline int __fscrypt_prepare_symlink(struct inode *dir, static inline int fscrypt_prepare_symlink(struct inode *dir,
const char *target,
unsigned int len, unsigned int len,
unsigned int max_len, unsigned int max_len,
struct fscrypt_str *disk_link) struct fscrypt_str *disk_link)
{ {
if (IS_ENCRYPTED(dir))
return -EOPNOTSUPP; return -EOPNOTSUPP;
disk_link->name = (unsigned char *)target;
disk_link->len = len + 1;
if (disk_link->len > max_len)
return -ENAMETOOLONG;
return 0;
} }
static inline int __fscrypt_encrypt_symlink(struct inode *inode, static inline int __fscrypt_encrypt_symlink(struct inode *inode,
const char *target, const char *target,
unsigned int len, unsigned int len,
@ -734,17 +737,16 @@ static inline int fscrypt_prepare_rename(struct inode *old_dir,
* @fname: (output) the name to use to search the on-disk directory * @fname: (output) the name to use to search the on-disk directory
* *
* Prepare for ->lookup() in a directory which may be encrypted by determining * Prepare for ->lookup() in a directory which may be encrypted by determining
* the name that will actually be used to search the directory on-disk. Lookups * the name that will actually be used to search the directory on-disk. If the
* can be done with or without the directory's encryption key; without the key, * directory's encryption key is available, then the lookup is assumed to be by
* filenames are presented in encrypted form. Therefore, we'll try to set up * plaintext name; otherwise, it is assumed to be by no-key name.
* the directory's encryption key, but even without it the lookup can continue.
* *
* This also installs a custom ->d_revalidate() method which will invalidate the * This also installs a custom ->d_revalidate() method which will invalidate the
* dentry if it was created without the key and the key is later added. * dentry if it was created without the key and the key is later added.
* *
* Return: 0 on success; -ENOENT if key is unavailable but the filename isn't a * Return: 0 on success; -ENOENT if the directory's key is unavailable but the
* correctly formed encoded ciphertext name, so a negative dentry should be * filename isn't a valid no-key name, so a negative dentry should be created;
* created; or another -errno code. * or another -errno code.
*/ */
static inline int fscrypt_prepare_lookup(struct inode *dir, static inline int fscrypt_prepare_lookup(struct inode *dir,
struct dentry *dentry, struct dentry *dentry,
@ -786,45 +788,6 @@ static inline int fscrypt_prepare_setattr(struct dentry *dentry,
return 0; return 0;
} }
/**
* fscrypt_prepare_symlink() - prepare to create a possibly-encrypted symlink
* @dir: directory in which the symlink is being created
* @target: plaintext symlink target
* @len: length of @target excluding null terminator
* @max_len: space the filesystem has available to store the symlink target
* @disk_link: (out) the on-disk symlink target being prepared
*
* This function computes the size the symlink target will require on-disk,
* stores it in @disk_link->len, and validates it against @max_len. An
* encrypted symlink may be longer than the original.
*
* Additionally, @disk_link->name is set to @target if the symlink will be
* unencrypted, but left NULL if the symlink will be encrypted. For encrypted
* symlinks, the filesystem must call fscrypt_encrypt_symlink() to create the
* on-disk target later. (The reason for the two-step process is that some
* filesystems need to know the size of the symlink target before creating the
* inode, e.g. to determine whether it will be a "fast" or "slow" symlink.)
*
* Return: 0 on success, -ENAMETOOLONG if the symlink target is too long,
* -ENOKEY if the encryption key is missing, or another -errno code if a problem
* occurred while setting up the encryption key.
*/
static inline int fscrypt_prepare_symlink(struct inode *dir,
const char *target,
unsigned int len,
unsigned int max_len,
struct fscrypt_str *disk_link)
{
if (IS_ENCRYPTED(dir) || fscrypt_get_dummy_context(dir->i_sb) != NULL)
return __fscrypt_prepare_symlink(dir, len, max_len, disk_link);
disk_link->name = (unsigned char *)target;
disk_link->len = len + 1;
if (disk_link->len > max_len)
return -ENAMETOOLONG;
return 0;
}
/** /**
* fscrypt_encrypt_symlink() - encrypt the symlink target if needed * fscrypt_encrypt_symlink() - encrypt the symlink target if needed
* @inode: symlink inode * @inode: symlink inode

View File

@ -45,7 +45,6 @@ struct fscrypt_policy_v1 {
__u8 flags; __u8 flags;
__u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; __u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE];
}; };
#define fscrypt_policy fscrypt_policy_v1
/* /*
* Process-subscribed "logon" key description prefix and payload format. * Process-subscribed "logon" key description prefix and payload format.
@ -156,9 +155,9 @@ struct fscrypt_get_key_status_arg {
__u32 __out_reserved[13]; __u32 __out_reserved[13];
}; };
#define FS_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct fscrypt_policy) #define FS_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct fscrypt_policy_v1)
#define FS_IOC_GET_ENCRYPTION_PWSALT _IOW('f', 20, __u8[16]) #define FS_IOC_GET_ENCRYPTION_PWSALT _IOW('f', 20, __u8[16])
#define FS_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct fscrypt_policy) #define FS_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct fscrypt_policy_v1)
#define FS_IOC_GET_ENCRYPTION_POLICY_EX _IOWR('f', 22, __u8[9]) /* size + version */ #define FS_IOC_GET_ENCRYPTION_POLICY_EX _IOWR('f', 22, __u8[9]) /* size + version */
#define FS_IOC_ADD_ENCRYPTION_KEY _IOWR('f', 23, struct fscrypt_add_key_arg) #define FS_IOC_ADD_ENCRYPTION_KEY _IOWR('f', 23, struct fscrypt_add_key_arg)
#define FS_IOC_REMOVE_ENCRYPTION_KEY _IOWR('f', 24, struct fscrypt_remove_key_arg) #define FS_IOC_REMOVE_ENCRYPTION_KEY _IOWR('f', 24, struct fscrypt_remove_key_arg)
@ -170,6 +169,7 @@ struct fscrypt_get_key_status_arg {
/* old names; don't add anything new here! */ /* old names; don't add anything new here! */
#ifndef __KERNEL__ #ifndef __KERNEL__
#define fscrypt_policy fscrypt_policy_v1
#define FS_KEY_DESCRIPTOR_SIZE FSCRYPT_KEY_DESCRIPTOR_SIZE #define FS_KEY_DESCRIPTOR_SIZE FSCRYPT_KEY_DESCRIPTOR_SIZE
#define FS_POLICY_FLAGS_PAD_4 FSCRYPT_POLICY_FLAGS_PAD_4 #define FS_POLICY_FLAGS_PAD_4 FSCRYPT_POLICY_FLAGS_PAD_4
#define FS_POLICY_FLAGS_PAD_8 FSCRYPT_POLICY_FLAGS_PAD_8 #define FS_POLICY_FLAGS_PAD_8 FSCRYPT_POLICY_FLAGS_PAD_8