Merge remote-tracking branch 'aosp/upstream-f2fs-stable-linux-4.19.y' into android-4.19-stable

* aosp/upstream-f2fs-stable-linux-4.19.y:
  fscrypt: remove stale definition
  fs-verity: remove unnecessary extern keywords
  fs-verity: fix all kerneldoc warnings
  fscrypt: add support for IV_INO_LBLK_32 policies
  fscrypt: make test_dummy_encryption use v2 by default
  fscrypt: support test_dummy_encryption=v2
  fscrypt: add fscrypt_add_test_dummy_key()
  linux/parser.h: add include guards
  fscrypt: remove unnecessary extern keywords
  fscrypt: name all function parameters
  fscrypt: fix all kerneldoc warnings

Conflicts:
	fs/crypto/fscrypt_private.h
	fs/crypto/keyring.c
	fs/crypto/keysetup.c
	fs/ext4/ext4.h
	fs/ext4/super.c
	fs/f2fs/f2fs.h
	fs/f2fs/super.c
	include/linux/fscrypt.h

Resolved the conflicts as per the corresponding android-mainline change,
I7198edbca759839aceeec2598e7a81305756c4d7.

Bug: 154167995
Test: kvm-xfstests -c ext4,f2fs,ext4/encrypt,f2fs/encrypt \
        -g encrypt -g verity -g casefold
      kvm-xfstests -c ext4,f2fs,ext4/encrypt,f2fs/encrypt \
        -g encrypt -g verity -g casefold -m inlinecrypt
Change-Id: Id12839f7948374575f9d15eee6a9c6a9382eacf3
Signed-off-by: Eric Biggers <ebiggers@google.com>
This commit is contained in:
Eric Biggers 2020-06-16 15:48:21 -07:00
commit 0764ced2f0
23 changed files with 635 additions and 298 deletions

View file

@ -217,8 +217,12 @@ fsync_mode=%s Control the policy of fsync. Currently supports "posix",
pass, but the performance will regress. "nobarrier" is
based on "posix", but doesn't issue flush command for
non-atomic files likewise "nobarrier" mount option.
test_dummy_encryption Enable dummy encryption, which provides a fake fscrypt
test_dummy_encryption
test_dummy_encryption=%s
Enable dummy encryption, which provides a fake fscrypt
context. The fake fscrypt context is used by xfstests.
The argument may be either "v1" or "v2", in order to
select the corresponding fscrypt policy version.
checkpoint=%s[:%u[%]] Set to "disable" to turn off checkpointing. Set to "enable"
to reenable checkpointing. Is enabled by default. While
disabled, any unmounting or unexpected shutdowns will cause

View file

@ -53,6 +53,7 @@ struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags)
/**
* fscrypt_free_bounce_page() - free a ciphertext bounce page
* @bounce_page: the bounce page to free, or NULL
*
* Free a bounce page that was allocated by fscrypt_encrypt_pagecache_blocks(),
* or by fscrypt_alloc_bounce_page() directly.
@ -143,7 +144,8 @@ int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw,
}
/**
* fscrypt_encrypt_pagecache_blocks() - Encrypt filesystem blocks from a pagecache page
* fscrypt_encrypt_pagecache_blocks() - Encrypt filesystem blocks from a
* pagecache page
* @page: The locked pagecache page containing the block(s) to encrypt
* @len: Total size of the block(s) to encrypt. Must be a nonzero
* multiple of the filesystem's block size.
@ -233,7 +235,8 @@ int fscrypt_encrypt_block_inplace(const struct inode *inode, struct page *page,
EXPORT_SYMBOL(fscrypt_encrypt_block_inplace);
/**
* fscrypt_decrypt_pagecache_blocks() - Decrypt filesystem blocks in a pagecache page
* fscrypt_decrypt_pagecache_blocks() - Decrypt filesystem blocks in a
* pagecache page
* @page: The locked pagecache page containing the block(s) to decrypt
* @len: Total size of the block(s) to decrypt. Must be a nonzero
* multiple of the filesystem's block size.
@ -357,6 +360,8 @@ void fscrypt_msg(const struct inode *inode, const char *level,
/**
* fscrypt_init() - Set up for fs encryption.
*
* Return: 0 on success; -errno on failure
*/
static int __init fscrypt_init(void)
{

View file

@ -18,7 +18,7 @@
#include <crypto/skcipher.h>
#include "fscrypt_private.h"
/**
/*
* struct fscrypt_nokey_name - identifier for directory entry when key is absent
*
* When userspace lists an encrypted directory without access to the key, the
@ -106,9 +106,12 @@ static inline bool fscrypt_is_dot_dotdot(const struct qstr *str)
/**
* fscrypt_fname_encrypt() - encrypt a filename
*
* The output buffer must be at least as large as the input buffer.
* Any extra space is filled with NUL padding before encryption.
* @inode: inode of the parent directory (for regular filenames)
* or of the symlink (for symlink targets)
* @iname: the filename to encrypt
* @out: (output) the encrypted filename
* @olen: size of the encrypted filename. It must be at least @iname->len.
* Any extra space is filled with NUL padding before encryption.
*
* Return: 0 on success, -errno on failure
*/
@ -158,8 +161,11 @@ int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
/**
* fname_decrypt() - decrypt a filename
*
* The caller must have allocated sufficient memory for the @oname string.
* @inode: inode of the parent directory (for regular filenames)
* or of the symlink (for symlink targets)
* @iname: the encrypted filename to decrypt
* @oname: (output) the decrypted filename. The caller must have allocated
* enough space for this, e.g. using fscrypt_fname_alloc_buffer().
*
* Return: 0 on success, -errno on failure
*/
@ -207,7 +213,10 @@ static const char lookup_table[65] =
#define BASE64_CHARS(nbytes) DIV_ROUND_UP((nbytes) * 4, 3)
/**
* base64_encode() -
* base64_encode() - base64-encode some bytes
* @src: the bytes to encode
* @len: number of bytes to encode
* @dst: (output) the base64-encoded string. Not NUL-terminated.
*
* Encodes the input string using characters from the set [A-Za-z0-9+,].
* The encoded string is roughly 4/3 times the size of the input string.
@ -273,7 +282,12 @@ 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
* used to present
* @crypto_str: (output) buffer to allocate
*
* Allocate a buffer that is large enough to hold any decrypted or encoded
* filename (null-terminated), for the given maximum encrypted filename length.
@ -298,9 +312,10 @@ int fscrypt_fname_alloc_buffer(const struct inode *inode,
EXPORT_SYMBOL(fscrypt_fname_alloc_buffer);
/**
* fscrypt_fname_free_buffer - free the buffer for presented filenames
* fscrypt_fname_free_buffer() - free a buffer for presented filenames
* @crypto_str: the buffer to free
*
* Free the buffer allocated by fscrypt_fname_alloc_buffer().
* Free a buffer that was allocated by fscrypt_fname_alloc_buffer().
*/
void fscrypt_fname_free_buffer(struct fscrypt_str *crypto_str)
{
@ -312,10 +327,19 @@ void fscrypt_fname_free_buffer(struct fscrypt_str *crypto_str)
EXPORT_SYMBOL(fscrypt_fname_free_buffer);
/**
* fscrypt_fname_disk_to_usr() - converts a filename from disk space to user
* space
*
* The caller must have allocated sufficient memory for the @oname string.
* fscrypt_fname_disk_to_usr() - convert an encrypted filename to
* user-presentable form
* @inode: inode of the parent directory (for regular filenames)
* or of the symlink (for symlink targets)
* @hash: first part of the name's dirhash, if applicable. This only needs to
* be provided if the filename is located in an indexed directory whose
* encryption key may be unavailable. Not needed for symlink targets.
* @minor_hash: second part of the name's dirhash, if applicable
* @iname: encrypted filename to convert. May also be "." or "..", which
* aren't actually encrypted.
* @oname: output buffer for the user-presentable filename. The caller must
* have allocated enough space for this, e.g. using
* fscrypt_fname_alloc_buffer().
*
* If the key is available, we'll decrypt the disk name. Otherwise, we'll
* encode it for presentation in fscrypt_nokey_name format.

View file

@ -45,7 +45,7 @@ struct fscrypt_context_v2 {
u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
};
/**
/*
* fscrypt_context - the encryption context of an inode
*
* This is the on-disk equivalent of an fscrypt_policy, stored alongside each
@ -159,7 +159,7 @@ fscrypt_policy_flags(const union fscrypt_policy *policy)
BUG();
}
/**
/*
* For encrypted symlinks, the ciphertext length is stored at the beginning
* of the string in little-endian format.
*/
@ -258,15 +258,14 @@ typedef enum {
/* crypto.c */
extern struct kmem_cache *fscrypt_info_cachep;
extern int fscrypt_initialize(unsigned int cop_flags);
extern int fscrypt_crypt_block(const struct inode *inode,
fscrypt_direction_t rw, u64 lblk_num,
struct page *src_page, struct page *dest_page,
unsigned int len, unsigned int offs,
gfp_t gfp_flags);
extern struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags);
int fscrypt_initialize(unsigned int cop_flags);
int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw,
u64 lblk_num, struct page *src_page,
struct page *dest_page, unsigned int len,
unsigned int offs, gfp_t gfp_flags);
struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags);
extern void __printf(3, 4) __cold
void __printf(3, 4) __cold
fscrypt_msg(const struct inode *inode, const char *level, const char *fmt, ...);
#define fscrypt_warn(inode, fmt, ...) \
@ -292,12 +291,10 @@ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num,
const struct fscrypt_info *ci);
/* fname.c */
extern int fscrypt_fname_encrypt(const struct inode *inode,
const struct qstr *iname,
u8 *out, unsigned int olen);
extern bool fscrypt_fname_encrypted_size(const struct inode *inode,
u32 orig_len, u32 max_len,
u32 *encrypted_len_ret);
int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
u8 *out, unsigned int olen);
bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len,
u32 max_len, u32 *encrypted_len_ret);
/* hkdf.c */
@ -305,8 +302,8 @@ struct fscrypt_hkdf {
struct crypto_shash *hmac_tfm;
};
extern int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key,
unsigned int master_key_size);
int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key,
unsigned int master_key_size);
/*
* The list of contexts in which fscrypt uses HKDF. These values are used as
@ -323,11 +320,11 @@ extern int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key,
#define HKDF_CONTEXT_IV_INO_LBLK_32_KEY 6
#define HKDF_CONTEXT_INODE_HASH_KEY 7
extern int fscrypt_hkdf_expand(const struct fscrypt_hkdf *hkdf, u8 context,
const u8 *info, unsigned int infolen,
u8 *okm, unsigned int okmlen);
int fscrypt_hkdf_expand(const struct fscrypt_hkdf *hkdf, u8 context,
const u8 *info, unsigned int infolen,
u8 *okm, unsigned int okmlen);
extern void fscrypt_destroy_hkdf(struct fscrypt_hkdf *hkdf);
void fscrypt_destroy_hkdf(struct fscrypt_hkdf *hkdf);
/* inline_crypt.c */
#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
@ -568,14 +565,17 @@ static inline int master_key_spec_len(const struct fscrypt_key_specifier *spec)
return 0;
}
extern struct key *
struct key *
fscrypt_find_master_key(struct super_block *sb,
const struct fscrypt_key_specifier *mk_spec);
extern int fscrypt_verify_key_added(struct super_block *sb,
const u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]);
int fscrypt_add_test_dummy_key(struct super_block *sb,
struct fscrypt_key_specifier *key_spec);
extern int __init fscrypt_init_keyring(void);
int fscrypt_verify_key_added(struct super_block *sb,
const u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]);
int __init fscrypt_init_keyring(void);
/* keysetup.c */
@ -590,36 +590,34 @@ struct fscrypt_mode {
extern struct fscrypt_mode fscrypt_modes[];
extern int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key,
const u8 *raw_key, unsigned int raw_key_size,
bool is_hw_wrapped,
const struct fscrypt_info *ci);
int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key,
const u8 *raw_key, unsigned int raw_key_size,
bool is_hw_wrapped, const struct fscrypt_info *ci);
extern void fscrypt_destroy_prepared_key(struct fscrypt_prepared_key *prep_key);
void fscrypt_destroy_prepared_key(struct fscrypt_prepared_key *prep_key);
extern int fscrypt_set_per_file_enc_key(struct fscrypt_info *ci,
const u8 *raw_key);
int fscrypt_set_per_file_enc_key(struct fscrypt_info *ci, const u8 *raw_key);
extern int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
const struct fscrypt_master_key *mk);
int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
const struct fscrypt_master_key *mk);
/* keysetup_v1.c */
extern void fscrypt_put_direct_key(struct fscrypt_direct_key *dk);
void fscrypt_put_direct_key(struct fscrypt_direct_key *dk);
extern int fscrypt_setup_v1_file_key(struct fscrypt_info *ci,
const u8 *raw_master_key);
int fscrypt_setup_v1_file_key(struct fscrypt_info *ci,
const u8 *raw_master_key);
int fscrypt_setup_v1_file_key_via_subscribed_keyrings(struct fscrypt_info *ci);
extern int fscrypt_setup_v1_file_key_via_subscribed_keyrings(
struct fscrypt_info *ci);
/* policy.c */
extern bool fscrypt_policies_equal(const union fscrypt_policy *policy1,
const union fscrypt_policy *policy2);
extern bool fscrypt_supported_policy(const union fscrypt_policy *policy_u,
const struct inode *inode);
extern int fscrypt_policy_from_context(union fscrypt_policy *policy_u,
const union fscrypt_context *ctx_u,
int ctx_size);
bool fscrypt_policies_equal(const union fscrypt_policy *policy1,
const union fscrypt_policy *policy2);
bool fscrypt_supported_policy(const union fscrypt_policy *policy_u,
const struct inode *inode);
int fscrypt_policy_from_context(union fscrypt_policy *policy_u,
const union fscrypt_context *ctx_u,
int ctx_size);
#endif /* _FSCRYPT_PRIVATE_H */

View file

@ -9,7 +9,7 @@
#include "fscrypt_private.h"
/**
* fscrypt_file_open - prepare to open a possibly-encrypted regular file
* fscrypt_file_open() - prepare to open a possibly-encrypted regular file
* @inode: the inode being opened
* @filp: the struct file being set up
*
@ -260,7 +260,7 @@ int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
EXPORT_SYMBOL_GPL(__fscrypt_encrypt_symlink);
/**
* fscrypt_get_symlink - get the target of an encrypted symlink
* fscrypt_get_symlink() - get the target of an encrypted symlink
* @inode: the symlink inode
* @caddr: the on-disk contents of the symlink
* @max_size: size of @caddr buffer

View file

@ -20,6 +20,7 @@
#include <crypto/skcipher.h>
#include <linux/key-type.h>
#include <linux/random.h>
#include <linux/seq_file.h>
#include "fscrypt_private.h"
@ -425,9 +426,9 @@ static int add_existing_master_key(struct fscrypt_master_key *mk,
return 0;
}
static int add_master_key(struct super_block *sb,
struct fscrypt_master_key_secret *secret,
const struct fscrypt_key_specifier *mk_spec)
static int do_add_master_key(struct super_block *sb,
struct fscrypt_master_key_secret *secret,
const struct fscrypt_key_specifier *mk_spec)
{
static DEFINE_MUTEX(fscrypt_add_key_mutex);
struct key *key;
@ -466,6 +467,49 @@ static int add_master_key(struct super_block *sb,
return err;
}
/* Size of software "secret" derived from hardware-wrapped key */
#define RAW_SECRET_SIZE 32
static int add_master_key(struct super_block *sb,
struct fscrypt_master_key_secret *secret,
struct fscrypt_key_specifier *key_spec)
{
int err;
if (key_spec->type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) {
u8 _kdf_key[RAW_SECRET_SIZE];
u8 *kdf_key = secret->raw;
unsigned int kdf_key_size = secret->size;
if (secret->is_hw_wrapped) {
kdf_key = _kdf_key;
kdf_key_size = RAW_SECRET_SIZE;
err = fscrypt_derive_raw_secret(sb, secret->raw,
secret->size,
kdf_key, kdf_key_size);
if (err)
return err;
}
err = fscrypt_init_hkdf(&secret->hkdf, kdf_key, kdf_key_size);
/*
* Now that the HKDF context is initialized, the raw HKDF key is
* no longer needed.
*/
memzero_explicit(kdf_key, kdf_key_size);
if (err)
return err;
/* Calculate the key identifier */
err = fscrypt_hkdf_expand(&secret->hkdf,
HKDF_CONTEXT_KEY_IDENTIFIER, NULL, 0,
key_spec->u.identifier,
FSCRYPT_KEY_IDENTIFIER_SIZE);
if (err)
return err;
}
return do_add_master_key(sb, secret, key_spec);
}
static int fscrypt_provisioning_key_preparse(struct key_preparsed_payload *prep)
{
const struct fscrypt_provisioning_key_payload *payload = prep->data;
@ -571,9 +615,6 @@ static int get_keyring_key(u32 key_id, u32 type,
return err;
}
/* Size of software "secret" derived from hardware-wrapped key */
#define RAW_SECRET_SIZE 32
/*
* Add a master encryption key to the filesystem, causing all files which were
* encrypted with it to appear "unlocked" (decrypted) when accessed.
@ -604,9 +645,6 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg)
struct fscrypt_add_key_arg __user *uarg = _uarg;
struct fscrypt_add_key_arg arg;
struct fscrypt_master_key_secret secret;
u8 _kdf_key[RAW_SECRET_SIZE];
u8 *kdf_key;
unsigned int kdf_key_size;
int err;
if (copy_from_user(&arg, uarg, sizeof(arg)))
@ -618,7 +656,25 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg)
if (memchr_inv(arg.__reserved, 0, sizeof(arg.__reserved)))
return -EINVAL;
/*
* Only root can add keys that are identified by an arbitrary descriptor
* rather than by a cryptographic hash --- since otherwise a malicious
* user could add the wrong key.
*/
if (arg.key_spec.type == FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR &&
!capable(CAP_SYS_ADMIN))
return -EACCES;
memset(&secret, 0, sizeof(secret));
if (arg.__flags) {
if (arg.__flags & ~__FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED)
return -EINVAL;
if (arg.key_spec.type != FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER)
return -EINVAL;
secret.is_hw_wrapped = true;
}
if (arg.key_id) {
if (arg.raw_size != 0)
return -EINVAL;
@ -626,14 +682,13 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg)
if (err)
goto out_wipe_secret;
err = -EINVAL;
if (!(arg.__flags & __FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED) &&
secret.size > FSCRYPT_MAX_KEY_SIZE)
if (secret.size > FSCRYPT_MAX_KEY_SIZE && !secret.is_hw_wrapped)
goto out_wipe_secret;
} else {
if (arg.raw_size < FSCRYPT_MIN_KEY_SIZE ||
arg.raw_size >
((arg.__flags & __FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED) ?
FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE : FSCRYPT_MAX_KEY_SIZE))
arg.raw_size > (secret.is_hw_wrapped ?
FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE :
FSCRYPT_MAX_KEY_SIZE))
return -EINVAL;
secret.size = arg.raw_size;
err = -EFAULT;
@ -641,73 +696,46 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg)
goto out_wipe_secret;
}
switch (arg.key_spec.type) {
case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR:
/*
* Only root can add keys that are identified by an arbitrary
* descriptor rather than by a cryptographic hash --- since
* otherwise a malicious user could add the wrong key.
*/
err = -EACCES;
if (!capable(CAP_SYS_ADMIN))
goto out_wipe_secret;
err = -EINVAL;
if (arg.__flags)
goto out_wipe_secret;
break;
case FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER:
err = -EINVAL;
if (arg.__flags & ~__FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED)
goto out_wipe_secret;
if (arg.__flags & __FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED) {
kdf_key = _kdf_key;
kdf_key_size = RAW_SECRET_SIZE;
err = fscrypt_derive_raw_secret(sb, secret.raw,
secret.size,
kdf_key, kdf_key_size);
if (err)
goto out_wipe_secret;
secret.is_hw_wrapped = true;
} else {
kdf_key = secret.raw;
kdf_key_size = secret.size;
}
err = fscrypt_init_hkdf(&secret.hkdf, kdf_key, kdf_key_size);
/*
* Now that the HKDF context is initialized, the raw HKDF
* key is no longer needed.
*/
memzero_explicit(kdf_key, kdf_key_size);
if (err)
goto out_wipe_secret;
/* Calculate the key identifier and return it to userspace. */
err = fscrypt_hkdf_expand(&secret.hkdf,
HKDF_CONTEXT_KEY_IDENTIFIER,
NULL, 0, arg.key_spec.u.identifier,
FSCRYPT_KEY_IDENTIFIER_SIZE);
if (err)
goto out_wipe_secret;
err = -EFAULT;
if (copy_to_user(uarg->key_spec.u.identifier,
arg.key_spec.u.identifier,
FSCRYPT_KEY_IDENTIFIER_SIZE))
goto out_wipe_secret;
break;
default:
WARN_ON(1);
err = -EINVAL;
goto out_wipe_secret;
}
err = add_master_key(sb, &secret, &arg.key_spec);
if (err)
goto out_wipe_secret;
/* Return the key identifier to userspace, if applicable */
err = -EFAULT;
if (arg.key_spec.type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER &&
copy_to_user(uarg->key_spec.u.identifier, arg.key_spec.u.identifier,
FSCRYPT_KEY_IDENTIFIER_SIZE))
goto out_wipe_secret;
err = 0;
out_wipe_secret:
wipe_master_key_secret(&secret);
return err;
}
EXPORT_SYMBOL_GPL(fscrypt_ioctl_add_key);
/*
* Add the key for '-o test_dummy_encryption' to the filesystem keyring.
*
* Use a per-boot random key to prevent people from misusing this option.
*/
int fscrypt_add_test_dummy_key(struct super_block *sb,
struct fscrypt_key_specifier *key_spec)
{
static u8 test_key[FSCRYPT_MAX_KEY_SIZE];
struct fscrypt_master_key_secret secret;
int err;
get_random_once(test_key, FSCRYPT_MAX_KEY_SIZE);
memset(&secret, 0, sizeof(secret));
secret.size = FSCRYPT_MAX_KEY_SIZE;
memcpy(secret.raw, test_key, FSCRYPT_MAX_KEY_SIZE);
err = add_master_key(sb, &secret, key_spec);
wipe_master_key_secret(&secret);
return err;
}
/*
* Verify that the current user has added a master key with the given identifier
* (returns -ENOKEY if not). This is needed to prevent a user from encrypting

View file

@ -161,7 +161,6 @@ static int setup_per_mode_enc_key(struct fscrypt_info *ci,
struct fscrypt_prepared_key *keys,
u8 hkdf_context, bool include_fs_uuid)
{
static DEFINE_MUTEX(mode_key_setup_mutex);
const struct inode *inode = ci->ci_inode;
const struct super_block *sb = inode->i_sb;
struct fscrypt_mode *mode = ci->ci_mode;
@ -230,6 +229,7 @@ static int setup_per_mode_enc_key(struct fscrypt_info *ci,
}
done_unlock:
ci->ci_key = *prep_key;
err = 0;
out_unlock:
mutex_unlock(&fscrypt_mode_key_setup_mutex);
@ -513,21 +513,18 @@ int fscrypt_get_encryption_info(struct inode *inode)
res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx));
if (res < 0) {
if (!fscrypt_dummy_context_enabled(inode) ||
IS_ENCRYPTED(inode)) {
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 */
memset(&ctx, 0, sizeof(ctx));
ctx.version = FSCRYPT_CONTEXT_V1;
ctx.v1.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS;
ctx.v1.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS;
memset(ctx.v1.master_key_descriptor, 0x42,
FSCRYPT_KEY_DESCRIPTOR_SIZE);
res = sizeof(ctx.v1);
res = fscrypt_context_size(dummy_ctx);
memcpy(&ctx, dummy_ctx, res);
}
crypt_info = kmem_cache_zalloc(fscrypt_info_cachep, GFP_NOFS);
@ -593,7 +590,8 @@ int fscrypt_get_encryption_info(struct inode *inode)
EXPORT_SYMBOL(fscrypt_get_encryption_info);
/**
* 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
*
* Free the inode's fscrypt_info. Filesystems must call this when the inode is
* being evicted. An RCU grace period need not have elapsed yet.
@ -606,7 +604,8 @@ void fscrypt_put_encryption_info(struct inode *inode)
EXPORT_SYMBOL(fscrypt_put_encryption_info);
/**
* fscrypt_free_inode - free an inode's fscrypt data requiring RCU delay
* fscrypt_free_inode() - free an inode's fscrypt data requiring RCU delay
* @inode: an inode being freed
*
* Free the inode's cached decrypted symlink target, if any. Filesystems must
* call this after an RCU grace period, just before they free the inode.
@ -621,7 +620,8 @@ void fscrypt_free_inode(struct inode *inode)
EXPORT_SYMBOL(fscrypt_free_inode);
/**
* fscrypt_drop_inode - check whether the inode's master key has been removed
* fscrypt_drop_inode() - check whether the inode's master key has been removed
* @inode: an inode being considered for eviction
*
* Filesystems supporting fscrypt must call this from their ->drop_inode()
* method so that encrypted inodes are evicted as soon as they're no longer in

View file

@ -11,12 +11,15 @@
*/
#include <linux/random.h>
#include <linux/seq_file.h>
#include <linux/string.h>
#include <linux/mount.h>
#include "fscrypt_private.h"
/**
* fscrypt_policies_equal - check whether two encryption policies are the same
* fscrypt_policies_equal() - check whether two encryption policies are the same
* @policy1: the first policy
* @policy2: the second policy
*
* Return: %true if equal, else %false
*/
@ -190,7 +193,9 @@ static bool fscrypt_supported_v2_policy(const struct fscrypt_policy_v2 *policy,
}
/**
* fscrypt_supported_policy - check whether an encryption policy is supported
* fscrypt_supported_policy() - check whether an encryption policy is supported
* @policy_u: the encryption policy
* @inode: the inode on which the policy will be used
*
* Given an encryption policy, check whether all its encryption modes and other
* settings are supported by this kernel on the given inode. (But we don't
@ -212,7 +217,10 @@ bool fscrypt_supported_policy(const union fscrypt_policy *policy_u,
}
/**
* fscrypt_new_context_from_policy - create a new fscrypt_context from a policy
* fscrypt_new_context_from_policy() - create a new fscrypt_context from
* an fscrypt_policy
* @ctx_u: output context
* @policy_u: input policy
*
* Create an fscrypt_context for an inode that is being assigned the given
* encryption policy. A new nonce is randomly generated.
@ -262,7 +270,11 @@ static int fscrypt_new_context_from_policy(union fscrypt_context *ctx_u,
}
/**
* fscrypt_policy_from_context - convert an fscrypt_context to an fscrypt_policy
* fscrypt_policy_from_context() - convert an fscrypt_context to
* an fscrypt_policy
* @policy_u: output policy
* @ctx_u: input context
* @ctx_size: size of input context in bytes
*
* Given an fscrypt_context, build the corresponding fscrypt_policy.
*
@ -628,3 +640,127 @@ int fscrypt_inherit_context(struct inode *parent, struct inode *child,
return preload ? fscrypt_get_encryption_info(child): 0;
}
EXPORT_SYMBOL(fscrypt_inherit_context);
/**
* fscrypt_set_test_dummy_encryption() - handle '-o test_dummy_encryption'
* @sb: the filesystem on which test_dummy_encryption is being specified
* @arg: the argument to the test_dummy_encryption option.
* If no argument was specified, then @arg->from == NULL.
* @dummy_ctx: the filesystem's current dummy context (input/output, see below)
*
* Handle the test_dummy_encryption mount option by creating a dummy encryption
* context, saving it in @dummy_ctx, and adding the corresponding dummy
* encryption key to the filesystem. If the @dummy_ctx is already set, then
* instead validate that it matches @arg. Don't support changing it via
* remount, as that is difficult to do safely.
*
* The reason we use an fscrypt_context rather than an fscrypt_policy is because
* we mustn't generate a new nonce each time we access a dummy-encrypted
* 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.
*/
int fscrypt_set_test_dummy_encryption(struct super_block *sb,
const substring_t *arg,
struct fscrypt_dummy_context *dummy_ctx)
{
const char *argstr = "v2";
const char *argstr_to_free = NULL;
struct fscrypt_key_specifier key_spec = { 0 };
int version;
union fscrypt_context *ctx = NULL;
int err;
if (arg->from) {
argstr = argstr_to_free = match_strdup(arg);
if (!argstr)
return -ENOMEM;
}
if (!strcmp(argstr, "v1")) {
version = FSCRYPT_CONTEXT_V1;
key_spec.type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR;
memset(key_spec.u.descriptor, 0x42,
FSCRYPT_KEY_DESCRIPTOR_SIZE);
} else if (!strcmp(argstr, "v2")) {
version = FSCRYPT_CONTEXT_V2;
key_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
/* key_spec.u.identifier gets filled in when adding the key */
} else {
err = -EINVAL;
goto out;
}
if (dummy_ctx->ctx) {
/*
* 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;
goto out;
}
err = fscrypt_add_test_dummy_key(sb, &key_spec);
if (err)
goto out;
ctx->version = version;
switch (ctx->version) {
case FSCRYPT_CONTEXT_V1:
ctx->v1.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS;
ctx->v1.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS;
memcpy(ctx->v1.master_key_descriptor, key_spec.u.descriptor,
FSCRYPT_KEY_DESCRIPTOR_SIZE);
break;
case FSCRYPT_CONTEXT_V2:
ctx->v2.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS;
ctx->v2.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS;
memcpy(ctx->v2.master_key_identifier, key_spec.u.identifier,
FSCRYPT_KEY_IDENTIFIER_SIZE);
break;
default:
WARN_ON(1);
err = -EINVAL;
goto out;
}
dummy_ctx->ctx = ctx;
ctx = NULL;
err = 0;
out:
kfree(ctx);
kfree(argstr_to_free);
return err;
}
EXPORT_SYMBOL_GPL(fscrypt_set_test_dummy_encryption);
/**
* fscrypt_show_test_dummy_encryption() - show '-o test_dummy_encryption'
* @seq: the seq_file to print the option to
* @sep: the separator character to use
* @sb: the filesystem whose options are being shown
*
* Show the test_dummy_encryption mount option, if it was specified.
* This is mainly used for /proc/mounts.
*/
void fscrypt_show_test_dummy_encryption(struct seq_file *seq, char sep,
struct super_block *sb)
{
const union fscrypt_context *ctx = fscrypt_get_dummy_context(sb);
if (!ctx)
return;
seq_printf(seq, "%ctest_dummy_encryption=v%d", sep, ctx->version);
}
EXPORT_SYMBOL_GPL(fscrypt_show_test_dummy_encryption);

View file

@ -1347,11 +1347,9 @@ struct ext4_super_block {
*/
#define EXT4_MF_MNTDIR_SAMPLED 0x0001
#define EXT4_MF_FS_ABORTED 0x0002 /* Fatal error detected */
#define EXT4_MF_TEST_DUMMY_ENCRYPTION 0x0004
#ifdef CONFIG_FS_ENCRYPTION
#define DUMMY_ENCRYPTION_ENABLED(sbi) (unlikely((sbi)->s_mount_flags & \
EXT4_MF_TEST_DUMMY_ENCRYPTION))
#define DUMMY_ENCRYPTION_ENABLED(sbi) ((sbi)->s_dummy_enc_ctx.ctx != NULL)
#else
#define DUMMY_ENCRYPTION_ENABLED(sbi) (0)
#endif
@ -1529,6 +1527,9 @@ struct ext4_sb_info {
struct ratelimit_state s_warning_ratelimit_state;
struct ratelimit_state s_msg_ratelimit_state;
/* Encryption context for '-o test_dummy_encryption' */
struct fscrypt_dummy_context s_dummy_enc_ctx;
/*
* Barrier between writepages ops and changing any inode's JOURNAL_DATA
* or EXTENTS flag.

View file

@ -1067,6 +1067,7 @@ static void ext4_put_super(struct super_block *sb)
crypto_free_shash(sbi->s_chksum_driver);
kfree(sbi->s_blockgroup_lock);
fs_put_dax(sbi->s_daxdev);
fscrypt_free_dummy_context(&sbi->s_dummy_enc_ctx);
#ifdef CONFIG_UNICODE
utf8_unload(sb->s_encoding);
#endif
@ -1355,9 +1356,10 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
return res;
}
static bool ext4_dummy_context(struct inode *inode)
static const union fscrypt_context *
ext4_get_dummy_context(struct super_block *sb)
{
return DUMMY_ENCRYPTION_ENABLED(EXT4_SB(inode->i_sb));
return EXT4_SB(sb)->s_dummy_enc_ctx.ctx;
}
static bool ext4_has_stable_inodes(struct super_block *sb)
@ -1381,7 +1383,7 @@ static const struct fscrypt_operations ext4_cryptops = {
.key_prefix = "ext4:",
.get_context = ext4_get_context,
.set_context = ext4_set_context,
.dummy_context = ext4_dummy_context,
.get_dummy_context = ext4_get_dummy_context,
.empty_dir = ext4_empty_dir,
.max_namelen = EXT4_NAME_LEN,
.has_stable_inodes = ext4_has_stable_inodes,
@ -1577,6 +1579,7 @@ static const match_table_t tokens = {
{Opt_init_itable, "init_itable"},
{Opt_noinit_itable, "noinit_itable"},
{Opt_max_dir_size_kb, "max_dir_size_kb=%u"},
{Opt_test_dummy_encryption, "test_dummy_encryption=%s"},
{Opt_test_dummy_encryption, "test_dummy_encryption"},
{Opt_inlinecrypt, "inlinecrypt"},
{Opt_nombcache, "nombcache"},
@ -1789,7 +1792,7 @@ static const struct mount_opts {
{Opt_jqfmt_vfsv0, QFMT_VFS_V0, MOPT_QFMT},
{Opt_jqfmt_vfsv1, QFMT_VFS_V1, MOPT_QFMT},
{Opt_max_dir_size_kb, 0, MOPT_GTE0},
{Opt_test_dummy_encryption, 0, MOPT_GTE0},
{Opt_test_dummy_encryption, 0, MOPT_STRING},
#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
{Opt_inlinecrypt, EXT4_MOUNT_INLINECRYPT, MOPT_SET},
#else
@ -1829,6 +1832,48 @@ static int ext4_sb_read_encoding(const struct ext4_super_block *es,
}
#endif
static int ext4_set_test_dummy_encryption(struct super_block *sb,
const char *opt,
const substring_t *arg,
bool is_remount)
{
#ifdef CONFIG_FS_ENCRYPTION
struct ext4_sb_info *sbi = EXT4_SB(sb);
int err;
/*
* This mount option is just for testing, and it's not worthwhile to
* implement the extra complexity (e.g. RCU protection) that would be
* 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.
*/
if (is_remount && !sbi->s_dummy_enc_ctx.ctx) {
ext4_msg(sb, KERN_WARNING,
"Can't set test_dummy_encryption on remount");
return -1;
}
err = fscrypt_set_test_dummy_encryption(sb, arg, &sbi->s_dummy_enc_ctx);
if (err) {
if (err == -EEXIST)
ext4_msg(sb, KERN_WARNING,
"Can't change test_dummy_encryption on remount");
else if (err == -EINVAL)
ext4_msg(sb, KERN_WARNING,
"Value of option \"%s\" is unrecognized", opt);
else
ext4_msg(sb, KERN_WARNING,
"Error processing option \"%s\" [%d]",
opt, err);
return -1;
}
ext4_msg(sb, KERN_WARNING, "Test dummy encryption mode enabled");
#else
ext4_msg(sb, KERN_WARNING,
"Test dummy encryption mount option ignored");
#endif
return 1;
}
static int handle_mount_opt(struct super_block *sb, char *opt, int token,
substring_t *args, unsigned long *journal_devnum,
unsigned int *journal_ioprio, int is_remount)
@ -2018,14 +2063,8 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
*journal_ioprio =
IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, arg);
} else if (token == Opt_test_dummy_encryption) {
#ifdef CONFIG_FS_ENCRYPTION
sbi->s_mount_flags |= EXT4_MF_TEST_DUMMY_ENCRYPTION;
ext4_msg(sb, KERN_WARNING,
"Test dummy encryption mode enabled");
#else
ext4_msg(sb, KERN_WARNING,
"Test dummy encryption mount option ignored");
#endif
return ext4_set_test_dummy_encryption(sb, opt, &args[0],
is_remount);
} else if (m->flags & MOPT_DATAJ) {
if (is_remount) {
if (!sbi->s_journal)
@ -2284,8 +2323,8 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
SEQ_OPTS_PRINT("max_dir_size_kb=%u", sbi->s_max_dir_size_kb);
if (test_opt(sb, DATA_ERR_ABORT))
SEQ_OPTS_PUTS("data_err=abort");
if (DUMMY_ENCRYPTION_ENABLED(sbi))
SEQ_OPTS_PUTS("test_dummy_encryption");
fscrypt_show_test_dummy_encryption(seq, sep, sb);
ext4_show_quota_options(seq, sb);
return 0;
@ -4769,6 +4808,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
for (i = 0; i < EXT4_MAXQUOTAS; i++)
kfree(sbi->s_qf_names[i]);
#endif
fscrypt_free_dummy_context(&sbi->s_dummy_enc_ctx);
ext4_blkdev_remove(sbi);
brelse(bh);
out_fail:

View file

@ -226,6 +226,7 @@ EXT4_ATTR_FEATURE(batched_discard);
EXT4_ATTR_FEATURE(meta_bg_resize);
#ifdef CONFIG_FS_ENCRYPTION
EXT4_ATTR_FEATURE(encryption);
EXT4_ATTR_FEATURE(test_dummy_encryption_v2);
#endif
#ifdef CONFIG_UNICODE
EXT4_ATTR_FEATURE(casefold);
@ -241,6 +242,7 @@ static struct attribute *ext4_feat_attrs[] = {
ATTR_LIST(meta_bg_resize),
#ifdef CONFIG_FS_ENCRYPTION
ATTR_LIST(encryption),
ATTR_LIST(test_dummy_encryption_v2),
#endif
#ifdef CONFIG_UNICODE
ATTR_LIST(casefold),

View file

@ -137,7 +137,7 @@ struct f2fs_mount_info {
int fsync_mode; /* fsync policy */
int fs_mode; /* fs mode: LFS or ADAPTIVE */
int bggc_mode; /* bggc mode: off, on or sync */
bool test_dummy_encryption; /* test dummy encryption */
struct fscrypt_dummy_context dummy_enc_ctx; /* test dummy encryption */
#ifdef CONFIG_FS_ENCRYPTION
bool inlinecrypt; /* inline encryption enabled */
#endif
@ -1319,7 +1319,7 @@ enum fsync_mode {
#ifdef CONFIG_FS_ENCRYPTION
#define DUMMY_ENCRYPTION_ENABLED(sbi) \
(unlikely(F2FS_OPTION(sbi).test_dummy_encryption))
(unlikely(F2FS_OPTION(sbi).dummy_enc_ctx.ctx != NULL))
#else
#define DUMMY_ENCRYPTION_ENABLED(sbi) (0)
#endif

View file

@ -202,6 +202,7 @@ static match_table_t f2fs_tokens = {
{Opt_whint, "whint_mode=%s"},
{Opt_alloc, "alloc_mode=%s"},
{Opt_fsync, "fsync_mode=%s"},
{Opt_test_dummy_encryption, "test_dummy_encryption=%s"},
{Opt_test_dummy_encryption, "test_dummy_encryption"},
{Opt_inlinecrypt, "inlinecrypt"},
{Opt_checkpoint_disable, "checkpoint=disable"},
@ -411,7 +412,52 @@ static int f2fs_check_quota_options(struct f2fs_sb_info *sbi)
}
#endif
static int parse_options(struct super_block *sb, char *options)
static int f2fs_set_test_dummy_encryption(struct super_block *sb,
const char *opt,
const substring_t *arg,
bool is_remount)
{
struct f2fs_sb_info *sbi = F2FS_SB(sb);
#ifdef CONFIG_FS_ENCRYPTION
int err;
if (!f2fs_sb_has_encrypt(sbi)) {
f2fs_err(sbi, "Encrypt feature is off");
return -EINVAL;
}
/*
* This mount option is just for testing, and it's not worthwhile to
* implement the extra complexity (e.g. RCU protection) that would be
* 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.
*/
if (is_remount && !F2FS_OPTION(sbi).dummy_enc_ctx.ctx) {
f2fs_warn(sbi, "Can't set test_dummy_encryption on remount");
return -EINVAL;
}
err = fscrypt_set_test_dummy_encryption(
sb, arg, &F2FS_OPTION(sbi).dummy_enc_ctx);
if (err) {
if (err == -EEXIST)
f2fs_warn(sbi,
"Can't change test_dummy_encryption on remount");
else if (err == -EINVAL)
f2fs_warn(sbi, "Value of option \"%s\" is unrecognized",
opt);
else
f2fs_warn(sbi, "Error processing option \"%s\" [%d]",
opt, err);
return -EINVAL;
}
f2fs_warn(sbi, "Test dummy encryption mode enabled");
#else
f2fs_warn(sbi, "Test dummy encryption mount option ignored");
#endif
return 0;
}
static int parse_options(struct super_block *sb, char *options, bool is_remount)
{
struct f2fs_sb_info *sbi = F2FS_SB(sb);
substring_t args[MAX_OPT_ARGS];
@ -420,9 +466,7 @@ static int parse_options(struct super_block *sb, char *options)
int arg = 0, ext_cnt;
kuid_t uid;
kgid_t gid;
#ifdef CONFIG_QUOTA
int ret;
#endif
if (!options)
return 0;
@ -785,17 +829,10 @@ static int parse_options(struct super_block *sb, char *options)
kvfree(name);
break;
case Opt_test_dummy_encryption:
#ifdef CONFIG_FS_ENCRYPTION
if (!f2fs_sb_has_encrypt(sbi)) {
f2fs_err(sbi, "Encrypt feature is off");
return -EINVAL;
}
F2FS_OPTION(sbi).test_dummy_encryption = true;
f2fs_info(sbi, "Test dummy encryption mode enabled");
#else
f2fs_info(sbi, "Test dummy encryption mount option ignored");
#endif
ret = f2fs_set_test_dummy_encryption(sb, p, &args[0],
is_remount);
if (ret)
return ret;
break;
case Opt_inlinecrypt:
#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
@ -1228,6 +1265,7 @@ static void f2fs_put_super(struct super_block *sb)
for (i = 0; i < MAXQUOTAS; i++)
kvfree(F2FS_OPTION(sbi).s_qf_names[i]);
#endif
fscrypt_free_dummy_context(&F2FS_OPTION(sbi).dummy_enc_ctx);
destroy_percpu_info(sbi);
for (i = 0; i < NR_PAGE_TYPE; i++)
kvfree(sbi->write_io[i]);
@ -1559,9 +1597,10 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
seq_printf(seq, ",whint_mode=%s", "user-based");
else if (F2FS_OPTION(sbi).whint_mode == WHINT_MODE_FS)
seq_printf(seq, ",whint_mode=%s", "fs-based");
fscrypt_show_test_dummy_encryption(seq, ',', sbi->sb);
#ifdef CONFIG_FS_ENCRYPTION
if (F2FS_OPTION(sbi).test_dummy_encryption)
seq_puts(seq, ",test_dummy_encryption");
if (F2FS_OPTION(sbi).inlinecrypt)
seq_puts(seq, ",inlinecrypt");
#endif
@ -1593,7 +1632,6 @@ static void default_options(struct f2fs_sb_info *sbi)
F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
F2FS_OPTION(sbi).fsync_mode = FSYNC_MODE_POSIX;
F2FS_OPTION(sbi).test_dummy_encryption = false;
#ifdef CONFIG_FS_ENCRYPTION
F2FS_OPTION(sbi).inlinecrypt = false;
#endif
@ -1755,7 +1793,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
default_options(sbi);
/* parse mount options */
err = parse_options(sb, data);
err = parse_options(sb, data, true);
if (err)
goto restore_opts;
checkpoint_changed =
@ -2432,9 +2470,10 @@ static int f2fs_set_context(struct inode *inode, const void *ctx, size_t len,
ctx, len, fs_data, XATTR_CREATE);
}
static bool f2fs_dummy_context(struct inode *inode)
static const union fscrypt_context *
f2fs_get_dummy_context(struct super_block *sb)
{
return DUMMY_ENCRYPTION_ENABLED(F2FS_I_SB(inode));
return F2FS_OPTION(F2FS_SB(sb)).dummy_enc_ctx.ctx;
}
static bool f2fs_has_stable_inodes(struct super_block *sb)
@ -2477,7 +2516,7 @@ static const struct fscrypt_operations f2fs_cryptops = {
.key_prefix = "f2fs:",
.get_context = f2fs_get_context,
.set_context = f2fs_set_context,
.dummy_context = f2fs_dummy_context,
.get_dummy_context = f2fs_get_dummy_context,
.empty_dir = f2fs_empty_dir,
.max_namelen = F2FS_NAME_LEN,
.has_stable_inodes = f2fs_has_stable_inodes,
@ -3429,7 +3468,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
goto free_sb_buf;
}
err = parse_options(sb, options);
err = parse_options(sb, options, false);
if (err)
goto free_options;
@ -3822,6 +3861,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
for (i = 0; i < MAXQUOTAS; i++)
kvfree(F2FS_OPTION(sbi).s_qf_names[i]);
#endif
fscrypt_free_dummy_context(&F2FS_OPTION(sbi).dummy_enc_ctx);
kvfree(options);
free_sb_buf:
kvfree(raw_super);

View file

@ -457,6 +457,7 @@ enum feat_id {
FEAT_SB_CHECKSUM,
FEAT_CASEFOLD,
FEAT_COMPRESSION,
FEAT_TEST_DUMMY_ENCRYPTION_V2,
};
static ssize_t f2fs_feature_show(struct f2fs_attr *a,
@ -477,6 +478,7 @@ static ssize_t f2fs_feature_show(struct f2fs_attr *a,
case FEAT_SB_CHECKSUM:
case FEAT_CASEFOLD:
case FEAT_COMPRESSION:
case FEAT_TEST_DUMMY_ENCRYPTION_V2:
return sprintf(buf, "supported\n");
}
return 0;
@ -577,6 +579,7 @@ F2FS_GENERAL_RO_ATTR(avg_vblocks);
#ifdef CONFIG_FS_ENCRYPTION
F2FS_FEATURE_RO_ATTR(encryption, FEAT_CRYPTO);
F2FS_FEATURE_RO_ATTR(test_dummy_encryption_v2, FEAT_TEST_DUMMY_ENCRYPTION_V2);
#endif
#ifdef CONFIG_BLK_DEV_ZONED
F2FS_FEATURE_RO_ATTR(block_zoned, FEAT_BLKZONED);
@ -663,6 +666,7 @@ static struct attribute *f2fs_attrs[] = {
static struct attribute *f2fs_feat_attrs[] = {
#ifdef CONFIG_FS_ENCRYPTION
ATTR_LIST(encryption),
ATTR_LIST(test_dummy_encryption_v2),
#endif
#ifdef CONFIG_BLK_DEV_ZONED
ATTR_LIST(block_zoned),

View file

@ -329,6 +329,8 @@ static int enable_verity(struct file *filp,
/**
* fsverity_ioctl_enable() - enable verity on a file
* @filp: file to enable verity on
* @uarg: user pointer to fsverity_enable_arg
*
* Enable fs-verity on a file. See the "FS_IOC_ENABLE_VERITY" section of
* Documentation/filesystems/fsverity.rst for the documentation.

View file

@ -61,7 +61,7 @@ struct merkle_tree_params {
u64 level_start[FS_VERITY_MAX_LEVELS];
};
/**
/*
* fsverity_info - cached verity metadata for an inode
*
* When a verity file is first opened, an instance of this struct is allocated
@ -134,7 +134,7 @@ void __init fsverity_check_hash_algs(void);
/* init.c */
extern void __printf(3, 4) __cold
void __printf(3, 4) __cold
fsverity_msg(const struct inode *inode, const char *level,
const char *fmt, ...);

View file

@ -11,6 +11,8 @@
/**
* fsverity_ioctl_measure() - get a verity file's measurement
* @filp: file to get measurement of
* @_uarg: user pointer to fsverity_digest
*
* Retrieve the file measurement that the kernel is enforcing for reads from a
* verity file. See the "FS_IOC_MEASURE_VERITY" section of

View file

@ -330,6 +330,7 @@ EXPORT_SYMBOL_GPL(fsverity_prepare_setattr);
/**
* fsverity_cleanup_inode() - free the inode's verity info, if present
* @inode: an inode being evicted
*
* Filesystems must call this on inode eviction to free ->i_verity_info.
*/

View file

@ -28,6 +28,9 @@ static struct key *fsverity_keyring;
/**
* fsverity_verify_signature() - check a verity file's signature
* @vi: the file's fsverity_info
* @desc: the file's fsverity_descriptor
* @desc_size: size of @desc
*
* If the file's fs-verity descriptor includes a signature of the file
* measurement, verify it against the certificates in the fs-verity keyring.

View file

@ -179,6 +179,7 @@ static bool verify_page(struct inode *inode, const struct fsverity_info *vi,
/**
* fsverity_verify_page() - verify a data page
* @page: the page to verity
*
* Verify a page that has just been read from a verity file. The page must be a
* pagecache page that is still locked and not yet uptodate.
@ -206,6 +207,7 @@ EXPORT_SYMBOL_GPL(fsverity_verify_page);
#ifdef CONFIG_BLOCK
/**
* fsverity_verify_bio() - verify a 'read' bio that has just completed
* @bio: the bio to verify
*
* Verify a set of pages that have just been read from a verity file. The pages
* must be pagecache pages that are still locked and not yet uptodate. Pages
@ -264,6 +266,7 @@ EXPORT_SYMBOL_GPL(fsverity_verify_bio);
/**
* fsverity_enqueue_verify_work() - enqueue work on the fs-verity workqueue
* @work: the work to enqueue
*
* Enqueue verification work for asynchronous processing.
*/

View file

@ -15,12 +15,15 @@
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/parser.h>
#include <linux/slab.h>
#include <uapi/linux/fscrypt.h>
#define FS_CRYPTO_BLOCK_SIZE 16
union fscrypt_context;
struct fscrypt_info;
struct seq_file;
struct fscrypt_str {
unsigned char *name;
@ -56,10 +59,12 @@ struct fscrypt_name {
struct fscrypt_operations {
unsigned int flags;
const char *key_prefix;
int (*get_context)(struct inode *, void *, size_t);
int (*set_context)(struct inode *, const void *, size_t, void *);
bool (*dummy_context)(struct inode *);
bool (*empty_dir)(struct inode *);
int (*get_context)(struct inode *inode, void *ctx, size_t len);
int (*set_context)(struct inode *inode, const void *ctx, size_t len,
void *fs_data);
const union fscrypt_context *(*get_dummy_context)(
struct super_block *sb);
bool (*empty_dir)(struct inode *inode);
unsigned int max_namelen;
bool (*has_stable_inodes)(struct super_block *sb);
void (*get_ino_and_lblk_bits)(struct super_block *sb,
@ -79,6 +84,7 @@ static inline bool fscrypt_has_encryption_key(const struct inode *inode)
/**
* fscrypt_needs_contents_encryption() - check whether an inode needs
* contents encryption
* @inode: the inode to check
*
* Return: %true iff the inode is an encrypted regular file and the kernel was
* built with fscrypt support.
@ -91,10 +97,12 @@ static inline bool fscrypt_needs_contents_encryption(const struct inode *inode)
return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode);
}
static inline bool fscrypt_dummy_context_enabled(struct inode *inode)
static inline const union fscrypt_context *
fscrypt_get_dummy_context(struct super_block *sb)
{
return inode->i_sb->s_cop->dummy_context &&
inode->i_sb->s_cop->dummy_context(inode);
if (!sb->s_cop->get_dummy_context)
return NULL;
return sb->s_cop->get_dummy_context(sb);
}
/*
@ -110,22 +118,21 @@ static inline void fscrypt_handle_d_move(struct dentry *dentry)
}
/* crypto.c */
extern void fscrypt_enqueue_decrypt_work(struct work_struct *);
void fscrypt_enqueue_decrypt_work(struct work_struct *);
extern struct page *fscrypt_encrypt_pagecache_blocks(struct page *page,
unsigned int len,
unsigned int offs,
gfp_t gfp_flags);
extern int fscrypt_encrypt_block_inplace(const struct inode *inode,
struct page *page, unsigned int len,
unsigned int offs, u64 lblk_num,
gfp_t gfp_flags);
struct page *fscrypt_encrypt_pagecache_blocks(struct page *page,
unsigned int len,
unsigned int offs,
gfp_t gfp_flags);
int fscrypt_encrypt_block_inplace(const struct inode *inode, struct page *page,
unsigned int len, unsigned int offs,
u64 lblk_num, gfp_t gfp_flags);
extern int fscrypt_decrypt_pagecache_blocks(struct page *page, unsigned int len,
unsigned int offs);
extern int fscrypt_decrypt_block_inplace(const struct inode *inode,
struct page *page, unsigned int len,
unsigned int offs, u64 lblk_num);
int fscrypt_decrypt_pagecache_blocks(struct page *page, unsigned int len,
unsigned int offs);
int fscrypt_decrypt_block_inplace(const struct inode *inode, struct page *page,
unsigned int len, unsigned int offs,
u64 lblk_num);
static inline bool fscrypt_is_bounce_page(struct page *page)
{
@ -137,81 +144,93 @@ static inline struct page *fscrypt_pagecache_page(struct page *bounce_page)
return (struct page *)page_private(bounce_page);
}
extern void fscrypt_free_bounce_page(struct page *bounce_page);
extern int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags);
void fscrypt_free_bounce_page(struct page *bounce_page);
int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags);
/* policy.c */
extern int fscrypt_ioctl_set_policy(struct file *, const void __user *);
extern int fscrypt_ioctl_get_policy(struct file *, void __user *);
extern int fscrypt_ioctl_get_policy_ex(struct file *, void __user *);
extern int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg);
extern int fscrypt_has_permitted_context(struct inode *, struct inode *);
extern int fscrypt_inherit_context(struct inode *, struct inode *,
void *, bool);
int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg);
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_nonce(struct file *filp, void __user *arg);
int fscrypt_has_permitted_context(struct inode *parent, struct inode *child);
int fscrypt_inherit_context(struct inode *parent, struct inode *child,
void *fs_data, bool preload);
struct fscrypt_dummy_context {
const union fscrypt_context *ctx;
};
int fscrypt_set_test_dummy_encryption(struct super_block *sb,
const substring_t *arg,
struct fscrypt_dummy_context *dummy_ctx);
void fscrypt_show_test_dummy_encryption(struct seq_file *seq, char sep,
struct super_block *sb);
static inline void
fscrypt_free_dummy_context(struct fscrypt_dummy_context *dummy_ctx)
{
kfree(dummy_ctx->ctx);
dummy_ctx->ctx = NULL;
}
/* keyring.c */
extern void fscrypt_sb_free(struct super_block *sb);
extern int fscrypt_ioctl_add_key(struct file *filp, void __user *arg);
extern int fscrypt_ioctl_remove_key(struct file *filp, void __user *arg);
extern int fscrypt_ioctl_remove_key_all_users(struct file *filp,
void __user *arg);
extern int fscrypt_ioctl_get_key_status(struct file *filp, void __user *arg);
extern int fscrypt_register_key_removal_notifier(struct notifier_block *nb);
extern int fscrypt_unregister_key_removal_notifier(struct notifier_block *nb);
void fscrypt_sb_free(struct super_block *sb);
int fscrypt_ioctl_add_key(struct file *filp, void __user *arg);
int fscrypt_ioctl_remove_key(struct file *filp, void __user *arg);
int fscrypt_ioctl_remove_key_all_users(struct file *filp, void __user *arg);
int fscrypt_ioctl_get_key_status(struct file *filp, void __user *arg);
int fscrypt_register_key_removal_notifier(struct notifier_block *nb);
int fscrypt_unregister_key_removal_notifier(struct notifier_block *nb);
/* keysetup.c */
extern int fscrypt_get_encryption_info(struct inode *);
extern void fscrypt_put_encryption_info(struct inode *);
extern void fscrypt_free_inode(struct inode *);
extern int fscrypt_drop_inode(struct inode *inode);
int fscrypt_get_encryption_info(struct inode *inode);
void fscrypt_put_encryption_info(struct inode *inode);
void fscrypt_free_inode(struct inode *inode);
int fscrypt_drop_inode(struct inode *inode);
/* fname.c */
extern int fscrypt_setup_filename(struct inode *, const struct qstr *,
int lookup, struct fscrypt_name *);
int fscrypt_setup_filename(struct inode *inode, const struct qstr *iname,
int lookup, struct fscrypt_name *fname);
static inline void fscrypt_free_filename(struct fscrypt_name *fname)
{
kfree(fname->crypto_buf.name);
}
extern int fscrypt_fname_alloc_buffer(const struct inode *, u32,
struct fscrypt_str *);
extern void fscrypt_fname_free_buffer(struct fscrypt_str *);
extern int fscrypt_fname_disk_to_usr(const struct inode *inode,
u32 hash, u32 minor_hash,
const struct fscrypt_str *iname,
struct fscrypt_str *oname);
extern bool fscrypt_match_name(const struct fscrypt_name *fname,
const u8 *de_name, u32 de_name_len);
extern u64 fscrypt_fname_siphash(const struct inode *dir,
const struct qstr *name);
int fscrypt_fname_alloc_buffer(const struct inode *inode, u32 max_encrypted_len,
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,
u32 hash, u32 minor_hash,
const struct fscrypt_str *iname,
struct fscrypt_str *oname);
bool fscrypt_match_name(const struct fscrypt_name *fname,
const u8 *de_name, u32 de_name_len);
u64 fscrypt_fname_siphash(const struct inode *dir, const struct qstr *name);
/* bio.c */
extern void fscrypt_decrypt_bio(struct bio *);
extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t,
unsigned int);
void fscrypt_decrypt_bio(struct bio *bio);
int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
sector_t pblk, unsigned int len);
/* hooks.c */
extern int fscrypt_file_open(struct inode *inode, struct file *filp);
extern int __fscrypt_prepare_link(struct inode *inode, struct inode *dir,
struct dentry *dentry);
extern int __fscrypt_prepare_rename(struct inode *old_dir,
struct dentry *old_dentry,
struct inode *new_dir,
struct dentry *new_dentry,
unsigned int flags);
extern int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry,
struct fscrypt_name *fname);
extern int fscrypt_prepare_setflags(struct inode *inode,
unsigned int oldflags, unsigned int flags);
extern int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len,
unsigned int max_len,
struct fscrypt_str *disk_link);
extern int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
unsigned int len,
struct fscrypt_str *disk_link);
extern const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
unsigned int max_size,
struct delayed_call *done);
int fscrypt_file_open(struct inode *inode, struct file *filp);
int __fscrypt_prepare_link(struct inode *inode, struct inode *dir,
struct dentry *dentry);
int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry,
unsigned int flags);
int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry,
struct fscrypt_name *fname);
int fscrypt_prepare_setflags(struct inode *inode,
unsigned int oldflags, unsigned int flags);
int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len,
unsigned int max_len,
struct fscrypt_str *disk_link);
int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
unsigned int len, struct fscrypt_str *disk_link);
const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
unsigned int max_size,
struct delayed_call *done);
#else /* !CONFIG_FS_ENCRYPTION */
static inline bool fscrypt_has_encryption_key(const struct inode *inode)
@ -224,9 +243,10 @@ static inline bool fscrypt_needs_contents_encryption(const struct inode *inode)
return false;
}
static inline bool fscrypt_dummy_context_enabled(struct inode *inode)
static inline const union fscrypt_context *
fscrypt_get_dummy_context(struct super_block *sb)
{
return false;
return NULL;
}
static inline void fscrypt_handle_d_move(struct dentry *dentry)
@ -321,6 +341,20 @@ static inline int fscrypt_inherit_context(struct inode *parent,
return -EOPNOTSUPP;
}
struct fscrypt_dummy_context {
};
static inline void fscrypt_show_test_dummy_encryption(struct seq_file *seq,
char sep,
struct super_block *sb)
{
}
static inline void
fscrypt_free_dummy_context(struct fscrypt_dummy_context *dummy_ctx)
{
}
/* keyring.c */
static inline void fscrypt_sb_free(struct super_block *sb)
{
@ -599,7 +633,7 @@ fscrypt_inode_should_skip_dm_default_key(const struct inode *inode)
#endif
/**
* fscrypt_require_key - require an inode's encryption key
* fscrypt_require_key() - require an inode's encryption key
* @inode: the inode we need the key for
*
* If the inode is encrypted, set up its encryption key if not already done.
@ -625,7 +659,8 @@ static inline int fscrypt_require_key(struct inode *inode)
}
/**
* fscrypt_prepare_link - prepare to link an inode into a possibly-encrypted directory
* fscrypt_prepare_link() - prepare to link an inode into a possibly-encrypted
* directory
* @old_dentry: an existing dentry for the inode being linked
* @dir: the target directory
* @dentry: negative dentry for the target filename
@ -652,7 +687,8 @@ static inline int fscrypt_prepare_link(struct dentry *old_dentry,
}
/**
* fscrypt_prepare_rename - prepare for a rename between possibly-encrypted directories
* fscrypt_prepare_rename() - prepare for a rename between possibly-encrypted
* directories
* @old_dir: source directory
* @old_dentry: dentry for source file
* @new_dir: target directory
@ -685,7 +721,8 @@ static inline int fscrypt_prepare_rename(struct inode *old_dir,
}
/**
* fscrypt_prepare_lookup - prepare to lookup a name in a possibly-encrypted directory
* fscrypt_prepare_lookup() - prepare to lookup a name in a possibly-encrypted
* directory
* @dir: directory being searched
* @dentry: filename being looked up
* @fname: (output) the name to use to search the on-disk directory
@ -719,7 +756,8 @@ static inline int fscrypt_prepare_lookup(struct inode *dir,
}
/**
* fscrypt_prepare_setattr - prepare to change a possibly-encrypted inode's attributes
* fscrypt_prepare_setattr() - prepare to change a possibly-encrypted inode's
* attributes
* @dentry: dentry through which the inode is being changed
* @attr: attributes to change
*
@ -744,7 +782,7 @@ static inline int fscrypt_prepare_setattr(struct dentry *dentry,
}
/**
* fscrypt_prepare_symlink - prepare to create a possibly-encrypted symlink
* 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
@ -772,7 +810,7 @@ static inline int fscrypt_prepare_symlink(struct inode *dir,
unsigned int max_len,
struct fscrypt_str *disk_link)
{
if (IS_ENCRYPTED(dir) || fscrypt_dummy_context_enabled(dir))
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;
@ -783,7 +821,7 @@ static inline int fscrypt_prepare_symlink(struct inode *dir,
}
/**
* fscrypt_encrypt_symlink - encrypt the symlink target if needed
* fscrypt_encrypt_symlink() - encrypt the symlink target if needed
* @inode: symlink inode
* @target: plaintext symlink target
* @len: length of @target excluding null terminator

View file

@ -121,23 +121,23 @@ static inline struct fsverity_info *fsverity_get_info(const struct inode *inode)
/* enable.c */
extern int fsverity_ioctl_enable(struct file *filp, const void __user *arg);
int fsverity_ioctl_enable(struct file *filp, const void __user *arg);
/* measure.c */
extern int fsverity_ioctl_measure(struct file *filp, void __user *arg);
int fsverity_ioctl_measure(struct file *filp, void __user *arg);
/* open.c */
extern int fsverity_file_open(struct inode *inode, struct file *filp);
extern int fsverity_prepare_setattr(struct dentry *dentry, struct iattr *attr);
extern void fsverity_cleanup_inode(struct inode *inode);
int fsverity_file_open(struct inode *inode, struct file *filp);
int fsverity_prepare_setattr(struct dentry *dentry, struct iattr *attr);
void fsverity_cleanup_inode(struct inode *inode);
/* verify.c */
extern bool fsverity_verify_page(struct page *page);
extern void fsverity_verify_bio(struct bio *bio);
extern void fsverity_enqueue_verify_work(struct work_struct *work);
bool fsverity_verify_page(struct page *page);
void fsverity_verify_bio(struct bio *bio);
void fsverity_enqueue_verify_work(struct work_struct *work);
#else /* !CONFIG_FS_VERITY */
@ -200,6 +200,7 @@ static inline void fsverity_enqueue_verify_work(struct work_struct *work)
/**
* fsverity_active() - do reads from the inode need to go through fs-verity?
* @inode: inode to check
*
* This checks whether ->i_verity_info has been set.
*
@ -207,6 +208,8 @@ static inline void fsverity_enqueue_verify_work(struct work_struct *work)
* be verified or not. Don't use IS_VERITY() for this purpose; it's subject to
* a race condition where the file is being read concurrently with
* FS_IOC_ENABLE_VERITY completing. (S_VERITY is set before ->i_verity_info.)
*
* Return: true if reads need to go through fs-verity, otherwise false
*/
static inline bool fsverity_active(const struct inode *inode)
{

View file

@ -7,7 +7,8 @@
* but could potentially be used anywhere else that simple option=arg
* parsing is required.
*/
#ifndef _LINUX_PARSER_H
#define _LINUX_PARSER_H
/* associates an integer enumerator with a pattern string. */
struct match_token {
@ -34,3 +35,5 @@ int match_hex(substring_t *, int *result);
bool match_wildcard(const char *pattern, const char *str);
size_t match_strlcpy(char *, const substring_t *, size_t);
char *match_strdup(const substring_t *);
#endif /* _LINUX_PARSER_H */