Commit 690b2567 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull fscrypt updates from Eric Biggers:
 "This release, we add support for inline encryption via the blk-crypto
  framework which was added in 5.8.

  Now when an ext4 or f2fs filesystem is mounted with '-o inlinecrypt',
  the contents of encrypted files will be encrypted/decrypted via
  blk-crypto, instead of directly using the crypto API. This model
  allows taking advantage of the inline encryption hardware that is
  integrated into the UFS or eMMC host controllers on most mobile SoCs.

  Note that this is just an alternate implementation; the ciphertext
  written to disk stays the same.

  (This pull request does *not* include support for direct I/O on
  encrypted files, which blk-crypto makes possible, since that part is
  still being discussed.)

  Besides the above feature update, there are also a few fixes and
  cleanups, e.g. strengthening some memory barriers that may be too
  weak.

  All these patches have been in linux-next with no reported issues.
  I've also tested them with the fscrypt xfstests, as usual. It's also
  been tested that the inline encryption support works with the support
  for Qualcomm and Mediatek inline encryption hardware that will be in
  the scsi pull request for 5.9. Also, several SoC vendors are already
  using a previous, functionally equivalent version of these patches"

* tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt:
  fscrypt: don't load ->i_crypt_info before it's known to be valid
  fscrypt: document inline encryption support
  fscrypt: use smp_load_acquire() for ->i_crypt_info
  fscrypt: use smp_load_acquire() for ->s_master_keys
  fscrypt: use smp_load_acquire() for fscrypt_prepared_key
  fscrypt: switch fscrypt_do_sha256() to use the SHA-256 library
  fscrypt: restrict IV_INO_LBLK_* to AES-256-XTS
  fscrypt: rename FS_KEY_DERIVATION_NONCE_SIZE
  fscrypt: add comments that describe the HKDF info strings
  ext4: add inline encryption support
  f2fs: add inline encryption support
  fscrypt: add inline encryption support
  fs: introduce SB_INLINECRYPT
parents 6dec9f40 55e32c54
...@@ -395,6 +395,13 @@ When mounting an ext4 filesystem, the following option are accepted: ...@@ -395,6 +395,13 @@ When mounting an ext4 filesystem, the following option are accepted:
Documentation/filesystems/dax.txt. Note that this option is Documentation/filesystems/dax.txt. Note that this option is
incompatible with data=journal. incompatible with data=journal.
inlinecrypt
When possible, encrypt/decrypt the contents of encrypted files using the
blk-crypto framework rather than filesystem-layer encryption. This
allows the use of inline encryption hardware. The on-disk format is
unaffected. For more details, see
Documentation/block/inline-encryption.rst.
Data Mode Data Mode
========= =========
There are 3 different data modes: There are 3 different data modes:
......
...@@ -258,6 +258,13 @@ compress_extension=%s Support adding specified extension, so that f2fs can enab ...@@ -258,6 +258,13 @@ compress_extension=%s Support adding specified extension, so that f2fs can enab
on compression extension list and enable compression on on compression extension list and enable compression on
these file by default rather than to enable it via ioctl. these file by default rather than to enable it via ioctl.
For other files, we can still enable compression via ioctl. For other files, we can still enable compression via ioctl.
inlinecrypt
When possible, encrypt/decrypt the contents of encrypted
files using the blk-crypto framework rather than
filesystem-layer encryption. This allows the use of
inline encryption hardware. The on-disk format is
unaffected. For more details, see
Documentation/block/inline-encryption.rst.
====================== ============================================================ ====================== ============================================================
Debugfs Entries Debugfs Entries
......
...@@ -1158,7 +1158,7 @@ setxattr() because of the special semantics of the encryption xattr. ...@@ -1158,7 +1158,7 @@ setxattr() because of the special semantics of the encryption xattr.
were to be added to or removed from anything other than an empty were to be added to or removed from anything other than an empty
directory.) These structs are defined as follows:: directory.) These structs are defined as follows::
#define FS_KEY_DERIVATION_NONCE_SIZE 16 #define FSCRYPT_FILE_NONCE_SIZE 16
#define FSCRYPT_KEY_DESCRIPTOR_SIZE 8 #define FSCRYPT_KEY_DESCRIPTOR_SIZE 8
struct fscrypt_context_v1 { struct fscrypt_context_v1 {
...@@ -1167,7 +1167,7 @@ directory.) These structs are defined as follows:: ...@@ -1167,7 +1167,7 @@ directory.) These structs are defined as follows::
u8 filenames_encryption_mode; u8 filenames_encryption_mode;
u8 flags; u8 flags;
u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE];
u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE]; u8 nonce[FSCRYPT_FILE_NONCE_SIZE];
}; };
#define FSCRYPT_KEY_IDENTIFIER_SIZE 16 #define FSCRYPT_KEY_IDENTIFIER_SIZE 16
...@@ -1178,7 +1178,7 @@ directory.) These structs are defined as follows:: ...@@ -1178,7 +1178,7 @@ directory.) These structs are defined as follows::
u8 flags; u8 flags;
u8 __reserved[4]; u8 __reserved[4];
u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]; u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE];
u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE]; u8 nonce[FSCRYPT_FILE_NONCE_SIZE];
}; };
The context structs contain the same information as the corresponding The context structs contain the same information as the corresponding
...@@ -1204,6 +1204,18 @@ buffer. Some filesystems, such as UBIFS, already use temporary ...@@ -1204,6 +1204,18 @@ buffer. Some filesystems, such as UBIFS, already use temporary
buffers regardless of encryption. Other filesystems, such as ext4 and buffers regardless of encryption. Other filesystems, such as ext4 and
F2FS, have to allocate bounce pages specially for encryption. F2FS, have to allocate bounce pages specially for encryption.
Fscrypt is also able to use inline encryption hardware instead of the
kernel crypto API for en/decryption of file contents. When possible,
and if directed to do so (by specifying the 'inlinecrypt' mount option
for an ext4/F2FS filesystem), it adds encryption contexts to bios and
uses blk-crypto to perform the en/decryption instead of making use of
the above read/write path changes. Of course, even if directed to
make use of inline encryption, fscrypt will only be able to do so if
either hardware inline encryption support is available for the
selected encryption algorithm or CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK
is selected. If neither is the case, fscrypt will fall back to using
the above mentioned read/write path changes for en/decryption.
Filename hashing and encoding Filename hashing and encoding
----------------------------- -----------------------------
...@@ -1250,11 +1262,14 @@ Tests ...@@ -1250,11 +1262,14 @@ Tests
To test fscrypt, use xfstests, which is Linux's de facto standard To test fscrypt, use xfstests, which is Linux's de facto standard
filesystem test suite. First, run all the tests in the "encrypt" filesystem test suite. First, run all the tests in the "encrypt"
group on the relevant filesystem(s). For example, to test ext4 and group on the relevant filesystem(s). One can also run the tests
with the 'inlinecrypt' mount option to test the implementation for
inline encryption support. For example, to test ext4 and
f2fs encryption using `kvm-xfstests f2fs encryption using `kvm-xfstests
<https://github.com/tytso/xfstests-bld/blob/master/Documentation/kvm-quickstart.md>`_:: <https://github.com/tytso/xfstests-bld/blob/master/Documentation/kvm-quickstart.md>`_::
kvm-xfstests -c ext4,f2fs -g encrypt kvm-xfstests -c ext4,f2fs -g encrypt
kvm-xfstests -c ext4,f2fs -g encrypt -m inlinecrypt
UBIFS encryption can also be tested this way, but it should be done in UBIFS encryption can also be tested this way, but it should be done in
a separate command, and it takes some time for kvm-xfstests to set up a separate command, and it takes some time for kvm-xfstests to set up
...@@ -1276,6 +1291,7 @@ This tests the encrypted I/O paths more thoroughly. To do this with ...@@ -1276,6 +1291,7 @@ This tests the encrypted I/O paths more thoroughly. To do this with
kvm-xfstests, use the "encrypt" filesystem configuration:: kvm-xfstests, use the "encrypt" filesystem configuration::
kvm-xfstests -c ext4/encrypt,f2fs/encrypt -g auto kvm-xfstests -c ext4/encrypt,f2fs/encrypt -g auto
kvm-xfstests -c ext4/encrypt,f2fs/encrypt -g auto -m inlinecrypt
Because this runs many more tests than "-g encrypt" does, it takes Because this runs many more tests than "-g encrypt" does, it takes
much longer to run; so also consider using `gce-xfstests much longer to run; so also consider using `gce-xfstests
...@@ -1283,3 +1299,4 @@ much longer to run; so also consider using `gce-xfstests ...@@ -1283,3 +1299,4 @@ much longer to run; so also consider using `gce-xfstests
instead of kvm-xfstests:: instead of kvm-xfstests::
gce-xfstests -c ext4/encrypt,f2fs/encrypt -g auto gce-xfstests -c ext4/encrypt,f2fs/encrypt -g auto
gce-xfstests -c ext4/encrypt,f2fs/encrypt -g auto -m inlinecrypt
...@@ -320,9 +320,8 @@ static void decrypt_bh(struct work_struct *work) ...@@ -320,9 +320,8 @@ static void decrypt_bh(struct work_struct *work)
static void end_buffer_async_read_io(struct buffer_head *bh, int uptodate) static void end_buffer_async_read_io(struct buffer_head *bh, int uptodate)
{ {
/* Decrypt if needed */ /* Decrypt if needed */
if (uptodate && IS_ENABLED(CONFIG_FS_ENCRYPTION) && if (uptodate &&
IS_ENCRYPTED(bh->b_page->mapping->host) && fscrypt_inode_uses_fs_layer_crypto(bh->b_page->mapping->host)) {
S_ISREG(bh->b_page->mapping->host->i_mode)) {
struct decrypt_bh_ctx *ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC); struct decrypt_bh_ctx *ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC);
if (ctx) { if (ctx) {
...@@ -3046,6 +3045,8 @@ static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh, ...@@ -3046,6 +3045,8 @@ static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh,
*/ */
bio = bio_alloc(GFP_NOIO, 1); bio = bio_alloc(GFP_NOIO, 1);
fscrypt_set_bio_crypt_ctx_bh(bio, bh, GFP_NOIO);
bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9); bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9);
bio_set_dev(bio, bh->b_bdev); bio_set_dev(bio, bh->b_bdev);
bio->bi_write_hint = write_hint; bio->bi_write_hint = write_hint;
......
...@@ -4,6 +4,7 @@ config FS_ENCRYPTION ...@@ -4,6 +4,7 @@ config FS_ENCRYPTION
select CRYPTO select CRYPTO
select CRYPTO_HASH select CRYPTO_HASH
select CRYPTO_SKCIPHER select CRYPTO_SKCIPHER
select CRYPTO_LIB_SHA256
select KEYS select KEYS
help help
Enable encryption of files and directories. This Enable encryption of files and directories. This
...@@ -21,6 +22,11 @@ config FS_ENCRYPTION_ALGS ...@@ -21,6 +22,11 @@ config FS_ENCRYPTION_ALGS
select CRYPTO_CTS select CRYPTO_CTS
select CRYPTO_ECB select CRYPTO_ECB
select CRYPTO_HMAC select CRYPTO_HMAC
select CRYPTO_SHA256
select CRYPTO_SHA512 select CRYPTO_SHA512
select CRYPTO_XTS select CRYPTO_XTS
config FS_ENCRYPTION_INLINE_CRYPT
bool "Enable fscrypt to use inline crypto"
depends on FS_ENCRYPTION && BLK_INLINE_ENCRYPTION
help
Enable fscrypt to use inline encryption hardware if available.
...@@ -11,3 +11,4 @@ fscrypto-y := crypto.o \ ...@@ -11,3 +11,4 @@ fscrypto-y := crypto.o \
policy.o policy.o
fscrypto-$(CONFIG_BLOCK) += bio.o fscrypto-$(CONFIG_BLOCK) += bio.o
fscrypto-$(CONFIG_FS_ENCRYPTION_INLINE_CRYPT) += inline_crypt.o
...@@ -41,6 +41,53 @@ void fscrypt_decrypt_bio(struct bio *bio) ...@@ -41,6 +41,53 @@ void fscrypt_decrypt_bio(struct bio *bio)
} }
EXPORT_SYMBOL(fscrypt_decrypt_bio); EXPORT_SYMBOL(fscrypt_decrypt_bio);
static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
pgoff_t lblk, sector_t pblk,
unsigned int len)
{
const unsigned int blockbits = inode->i_blkbits;
const unsigned int blocks_per_page = 1 << (PAGE_SHIFT - blockbits);
struct bio *bio;
int ret, err = 0;
int num_pages = 0;
/* This always succeeds since __GFP_DIRECT_RECLAIM is set. */
bio = bio_alloc(GFP_NOFS, BIO_MAX_PAGES);
while (len) {
unsigned int blocks_this_page = min(len, blocks_per_page);
unsigned int bytes_this_page = blocks_this_page << blockbits;
if (num_pages == 0) {
fscrypt_set_bio_crypt_ctx(bio, inode, lblk, GFP_NOFS);
bio_set_dev(bio, inode->i_sb->s_bdev);
bio->bi_iter.bi_sector =
pblk << (blockbits - SECTOR_SHIFT);
bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
}
ret = bio_add_page(bio, ZERO_PAGE(0), bytes_this_page, 0);
if (WARN_ON(ret != bytes_this_page)) {
err = -EIO;
goto out;
}
num_pages++;
len -= blocks_this_page;
lblk += blocks_this_page;
pblk += blocks_this_page;
if (num_pages == BIO_MAX_PAGES || !len ||
!fscrypt_mergeable_bio(bio, inode, lblk)) {
err = submit_bio_wait(bio);
if (err)
goto out;
bio_reset(bio);
num_pages = 0;
}
}
out:
bio_put(bio);
return err;
}
/** /**
* fscrypt_zeroout_range() - zero out a range of blocks in an encrypted file * fscrypt_zeroout_range() - zero out a range of blocks in an encrypted file
* @inode: the file's inode * @inode: the file's inode
...@@ -75,6 +122,10 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, ...@@ -75,6 +122,10 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
if (len == 0) if (len == 0)
return 0; return 0;
if (fscrypt_inode_uses_inline_crypto(inode))
return fscrypt_zeroout_range_inline_crypt(inode, lblk, pblk,
len);
BUILD_BUG_ON(ARRAY_SIZE(pages) > BIO_MAX_PAGES); BUILD_BUG_ON(ARRAY_SIZE(pages) > BIO_MAX_PAGES);
nr_pages = min_t(unsigned int, ARRAY_SIZE(pages), nr_pages = min_t(unsigned int, ARRAY_SIZE(pages),
(len + blocks_per_page - 1) >> blocks_per_page_bits); (len + blocks_per_page - 1) >> blocks_per_page_bits);
......
...@@ -84,7 +84,7 @@ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num, ...@@ -84,7 +84,7 @@ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num,
WARN_ON_ONCE(lblk_num > U32_MAX); WARN_ON_ONCE(lblk_num > U32_MAX);
lblk_num = (u32)(ci->ci_hashed_ino + lblk_num); lblk_num = (u32)(ci->ci_hashed_ino + lblk_num);
} else if (flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) { } else if (flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) {
memcpy(iv->nonce, ci->ci_nonce, FS_KEY_DERIVATION_NONCE_SIZE); memcpy(iv->nonce, ci->ci_nonce, FSCRYPT_FILE_NONCE_SIZE);
} }
iv->lblk_num = cpu_to_le64(lblk_num); iv->lblk_num = cpu_to_le64(lblk_num);
} }
...@@ -100,7 +100,7 @@ int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw, ...@@ -100,7 +100,7 @@ int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw,
DECLARE_CRYPTO_WAIT(wait); DECLARE_CRYPTO_WAIT(wait);
struct scatterlist dst, src; struct scatterlist dst, src;
struct fscrypt_info *ci = inode->i_crypt_info; struct fscrypt_info *ci = inode->i_crypt_info;
struct crypto_skcipher *tfm = ci->ci_ctfm; struct crypto_skcipher *tfm = ci->ci_enc_key.tfm;
int res = 0; int res = 0;
if (WARN_ON_ONCE(len <= 0)) if (WARN_ON_ONCE(len <= 0))
......
...@@ -61,30 +61,13 @@ struct fscrypt_nokey_name { ...@@ -61,30 +61,13 @@ 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 struct crypto_shash *sha256_hash_tfm; static void fscrypt_do_sha256(const u8 *data, unsigned int data_len, u8 *result)
static int fscrypt_do_sha256(const u8 *data, unsigned int data_len, u8 *result)
{ {
struct crypto_shash *tfm = READ_ONCE(sha256_hash_tfm); struct sha256_state sctx;
if (unlikely(!tfm)) {
struct crypto_shash *prev_tfm;
tfm = crypto_alloc_shash("sha256", 0, 0);
if (IS_ERR(tfm)) {
fscrypt_err(NULL,
"Error allocating SHA-256 transform: %ld",
PTR_ERR(tfm));
return PTR_ERR(tfm);
}
prev_tfm = cmpxchg(&sha256_hash_tfm, NULL, tfm);
if (prev_tfm) {
crypto_free_shash(tfm);
tfm = prev_tfm;
}
}
return crypto_shash_tfm_digest(tfm, data, data_len, result); 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)
...@@ -115,7 +98,7 @@ int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname, ...@@ -115,7 +98,7 @@ int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
struct skcipher_request *req = NULL; struct skcipher_request *req = NULL;
DECLARE_CRYPTO_WAIT(wait); DECLARE_CRYPTO_WAIT(wait);
const struct fscrypt_info *ci = inode->i_crypt_info; const struct fscrypt_info *ci = inode->i_crypt_info;
struct crypto_skcipher *tfm = ci->ci_ctfm; struct crypto_skcipher *tfm = ci->ci_enc_key.tfm;
union fscrypt_iv iv; union fscrypt_iv iv;
struct scatterlist sg; struct scatterlist sg;
int res; int res;
...@@ -171,7 +154,7 @@ static int fname_decrypt(const struct inode *inode, ...@@ -171,7 +154,7 @@ static int fname_decrypt(const struct inode *inode,
DECLARE_CRYPTO_WAIT(wait); DECLARE_CRYPTO_WAIT(wait);
struct scatterlist src_sg, dst_sg; struct scatterlist src_sg, dst_sg;
const struct fscrypt_info *ci = inode->i_crypt_info; const struct fscrypt_info *ci = inode->i_crypt_info;
struct crypto_skcipher *tfm = ci->ci_ctfm; struct crypto_skcipher *tfm = ci->ci_enc_key.tfm;
union fscrypt_iv iv; union fscrypt_iv iv;
int res; int res;
...@@ -349,7 +332,6 @@ int fscrypt_fname_disk_to_usr(const struct inode *inode, ...@@ -349,7 +332,6 @@ int fscrypt_fname_disk_to_usr(const struct inode *inode,
const struct qstr qname = FSTR_TO_QSTR(iname); const struct qstr qname = FSTR_TO_QSTR(iname);
struct fscrypt_nokey_name nokey_name; struct fscrypt_nokey_name nokey_name;
u32 size; /* size of the unencoded no-key name */ u32 size; /* size of the unencoded no-key name */
int err;
if (fscrypt_is_dot_dotdot(&qname)) { if (fscrypt_is_dot_dotdot(&qname)) {
oname->name[0] = '.'; oname->name[0] = '.';
...@@ -387,11 +369,9 @@ int fscrypt_fname_disk_to_usr(const struct inode *inode, ...@@ -387,11 +369,9 @@ 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. */
err = fscrypt_do_sha256(&iname->name[sizeof(nokey_name.bytes)], fscrypt_do_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);
if (err)
return err;
size = FSCRYPT_NOKEY_NAME_MAX; size = FSCRYPT_NOKEY_NAME_MAX;
} }
oname->len = base64_encode((const u8 *)&nokey_name, size, oname->name); oname->len = base64_encode((const u8 *)&nokey_name, size, oname->name);
...@@ -530,9 +510,8 @@ bool fscrypt_match_name(const struct fscrypt_name *fname, ...@@ -530,9 +510,8 @@ 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;
if (fscrypt_do_sha256(&de_name[sizeof(nokey_name->bytes)], fscrypt_do_sha256(&de_name[sizeof(nokey_name->bytes)],
de_name_len - sizeof(nokey_name->bytes), sha256)) de_name_len - sizeof(nokey_name->bytes), sha256);
return false;
return !memcmp(sha256, nokey_name->sha256, sizeof(sha256)); return !memcmp(sha256, nokey_name->sha256, sizeof(sha256));
} }
EXPORT_SYMBOL_GPL(fscrypt_match_name); EXPORT_SYMBOL_GPL(fscrypt_match_name);
......
...@@ -14,12 +14,13 @@ ...@@ -14,12 +14,13 @@
#include <linux/fscrypt.h> #include <linux/fscrypt.h>
#include <linux/siphash.h> #include <linux/siphash.h>
#include <crypto/hash.h> #include <crypto/hash.h>
#include <linux/blk-crypto.h>
#define CONST_STRLEN(str) (sizeof(str) - 1) #define CONST_STRLEN(str) (sizeof(str) - 1)
#define FS_KEY_DERIVATION_NONCE_SIZE 16 #define FSCRYPT_FILE_NONCE_SIZE 16
#define FSCRYPT_MIN_KEY_SIZE 16 #define FSCRYPT_MIN_KEY_SIZE 16
#define FSCRYPT_CONTEXT_V1 1 #define FSCRYPT_CONTEXT_V1 1
#define FSCRYPT_CONTEXT_V2 2 #define FSCRYPT_CONTEXT_V2 2
...@@ -30,7 +31,7 @@ struct fscrypt_context_v1 { ...@@ -30,7 +31,7 @@ struct fscrypt_context_v1 {
u8 filenames_encryption_mode; u8 filenames_encryption_mode;
u8 flags; u8 flags;
u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE];
u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE]; u8 nonce[FSCRYPT_FILE_NONCE_SIZE];
}; };
struct fscrypt_context_v2 { struct fscrypt_context_v2 {
...@@ -40,7 +41,7 @@ struct fscrypt_context_v2 { ...@@ -40,7 +41,7 @@ struct fscrypt_context_v2 {
u8 flags; u8 flags;
u8 __reserved[4]; u8 __reserved[4];
u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]; u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE];
u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE]; u8 nonce[FSCRYPT_FILE_NONCE_SIZE];
}; };
/* /*
...@@ -166,6 +167,20 @@ struct fscrypt_symlink_data { ...@@ -166,6 +167,20 @@ struct fscrypt_symlink_data {
char encrypted_path[1]; char encrypted_path[1];
} __packed; } __packed;
/**
* struct fscrypt_prepared_key - a key prepared for actual encryption/decryption
* @tfm: crypto API transform object
* @blk_key: key for blk-crypto
*
* Normally only one of the fields will be non-NULL.
*/
struct fscrypt_prepared_key {
struct crypto_skcipher *tfm;
#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
struct fscrypt_blk_crypto_key *blk_key;
#endif
};
/* /*
* fscrypt_info - the "encryption key" for an inode * fscrypt_info - the "encryption key" for an inode
* *
...@@ -175,12 +190,20 @@ struct fscrypt_symlink_data { ...@@ -175,12 +190,20 @@ struct fscrypt_symlink_data {
*/ */
struct fscrypt_info { struct fscrypt_info {
/* The actual crypto transform used for encryption and decryption */ /* The key in a form prepared for actual encryption/decryption */
struct crypto_skcipher *ci_ctfm; struct fscrypt_prepared_key ci_enc_key;
/* True if the key should be freed when this fscrypt_info is freed */ /* True if ci_enc_key should be freed when this fscrypt_info is freed */
bool ci_owns_key; bool ci_owns_key;
#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
/*
* True if this inode will use inline encryption (blk-crypto) instead of
* the traditional filesystem-layer encryption.
*/
bool ci_inlinecrypt;
#endif
/* /*
* Encryption mode used for this inode. It corresponds to either the * Encryption mode used for this inode. It corresponds to either the
* contents or filenames encryption mode, depending on the inode type. * contents or filenames encryption mode, depending on the inode type.
...@@ -205,7 +228,7 @@ struct fscrypt_info { ...@@ -205,7 +228,7 @@ struct fscrypt_info {
/* /*
* If non-NULL, then encryption is done using the master key directly * If non-NULL, then encryption is done using the master key directly
* and ci_ctfm will equal ci_direct_key->dk_ctfm. * and ci_enc_key will equal ci_direct_key->dk_key.
*/ */
struct fscrypt_direct_key *ci_direct_key; struct fscrypt_direct_key *ci_direct_key;
...@@ -221,7 +244,7 @@ struct fscrypt_info { ...@@ -221,7 +244,7 @@ struct fscrypt_info {
union fscrypt_policy ci_policy; union fscrypt_policy ci_policy;
/* This inode's nonce, copied from the fscrypt_context */ /* This inode's nonce, copied from the fscrypt_context */
u8 ci_nonce[FS_KEY_DERIVATION_NONCE_SIZE]; u8 ci_nonce[FSCRYPT_FILE_NONCE_SIZE];
/* Hashed inode number. Only set for IV_INO_LBLK_32 */ /* Hashed inode number. Only set for IV_INO_LBLK_32 */
u32 ci_hashed_ino; u32 ci_hashed_ino;
...@@ -257,9 +280,10 @@ union fscrypt_iv { ...@@ -257,9 +280,10 @@ union fscrypt_iv {
__le64 lblk_num; __le64 lblk_num;
/* per-file nonce; only set in DIRECT_KEY mode */ /* per-file nonce; only set in DIRECT_KEY mode */
u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE]; u8 nonce[FSCRYPT_FILE_NONCE_SIZE];
}; };
u8 raw[FSCRYPT_MAX_IV_SIZE]; u8 raw[FSCRYPT_MAX_IV_SIZE];
__le64 dun[FSCRYPT_MAX_IV_SIZE / sizeof(__le64)];
}; };
void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num, void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num,
...@@ -288,13 +312,13 @@ int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key, ...@@ -288,13 +312,13 @@ int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key,
* outputs are unique and cryptographically isolated, i.e. knowledge of one * outputs are unique and cryptographically isolated, i.e. knowledge of one
* output doesn't reveal another. * output doesn't reveal another.
*/ */
#define HKDF_CONTEXT_KEY_IDENTIFIER 1 #define HKDF_CONTEXT_KEY_IDENTIFIER 1 /* info=<empty> */
#define HKDF_CONTEXT_PER_FILE_ENC_KEY 2 #define HKDF_CONTEXT_PER_FILE_ENC_KEY 2 /* info=file_nonce */
#define HKDF_CONTEXT_DIRECT_KEY 3 #define HKDF_CONTEXT_DIRECT_KEY 3 /* info=mode_num */
#define HKDF_CONTEXT_IV_INO_LBLK_64_KEY 4 #define HKDF_CONTEXT_IV_INO_LBLK_64_KEY 4 /* info=mode_num||fs_uuid */
#define HKDF_CONTEXT_DIRHASH_KEY 5 #define HKDF_CONTEXT_DIRHASH_KEY 5 /* info=file_nonce */
#define HKDF_CONTEXT_IV_INO_LBLK_32_KEY 6 #define HKDF_CONTEXT_IV_INO_LBLK_32_KEY 6 /* info=mode_num||fs_uuid */
#define HKDF_CONTEXT_INODE_HASH_KEY 7 #define HKDF_CONTEXT_INODE_HASH_KEY 7 /* info=<empty> */
int fscrypt_hkdf_expand(const struct fscrypt_hkdf *hkdf, u8 context, int fscrypt_hkdf_expand(const struct fscrypt_hkdf *hkdf, u8 context,
const u8 *info, unsigned int infolen, const u8 *info, unsigned int infolen,
...@@ -302,6 +326,78 @@ int fscrypt_hkdf_expand(const struct fscrypt_hkdf *hkdf, u8 context, ...@@ -302,6 +326,78 @@ int fscrypt_hkdf_expand(const struct fscrypt_hkdf *hkdf, u8 context,
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
int fscrypt_select_encryption_impl(struct fscrypt_info *ci);
static inline bool
fscrypt_using_inline_encryption(const struct fscrypt_info *ci)
{
return ci->ci_inlinecrypt;
}
int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
const u8 *raw_key,
const struct fscrypt_info *ci);
void fscrypt_destroy_inline_crypt_key(struct fscrypt_prepared_key *prep_key);
/*
* Check whether the crypto transform or blk-crypto key has been allocated in
* @prep_key, depending on which encryption implementation the file will use.
*/
static inline bool
fscrypt_is_key_prepared(struct fscrypt_prepared_key *prep_key,
const struct fscrypt_info *ci)
{
/*
* The two smp_load_acquire()'s here pair with the smp_store_release()'s
* in fscrypt_prepare_inline_crypt_key() and fscrypt_prepare_key().
* I.e., in some cases (namely, if this prep_key is a per-mode
* encryption key) another task can publish blk_key or tfm concurrently,
* executing a RELEASE barrier. We need to use smp_load_acquire() here
* to safely ACQUIRE the memory the other task published.
*/
if (fscrypt_using_inline_encryption(ci))
return smp_load_acquire(&prep_key->blk_key) != NULL;
return smp_load_acquire(&prep_key->tfm) != NULL;
}
#else /* CONFIG_FS_ENCRYPTION_INLINE_CRYPT */
static inline int fscrypt_select_encryption_impl(struct fscrypt_info *ci)
{
return 0;
}
static inline bool
fscrypt_using_inline_encryption(const struct fscrypt_info *ci)
{
return false;
}
static inline int
fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
const u8 *raw_key,
const struct fscrypt_info *ci)
{
WARN_ON(1);
return -EOPNOTSUPP;
}
static inline void
fscrypt_destroy_inline_crypt_key(struct fscrypt_prepared_key *prep_key)
{
}
static inline bool
fscrypt_is_key_prepared(struct fscrypt_prepared_key *prep_key,
const struct fscrypt_info *ci)
{
return smp_load_acquire(&prep_key->tfm) != NULL;
}
#endif /* !CONFIG_FS_ENCRYPTION_INLINE_CRYPT */
/* keyring.c */ /* keyring.c */
/* /*
...@@ -395,9 +491,9 @@ struct fscrypt_master_key { ...@@ -395,9 +491,9 @@ struct fscrypt_master_key {
* Per-mode encryption keys for the various types of encryption policies * Per-mode encryption keys for the various types of encryption policies
* that use them. Allocated and derived on-demand. * that use them. Allocated and derived on-demand.
*/ */
struct crypto_skcipher *mk_direct_keys[__FSCRYPT_MODE_MAX + 1]; struct fscrypt_prepared_key mk_direct_keys[__FSCRYPT_MODE_MAX + 1];
struct crypto_skcipher *mk_iv_ino_lblk_64_keys[__FSCRYPT_MODE_MAX + 1]; struct fscrypt_prepared_key mk_iv_ino_lblk_64_keys[__FSCRYPT_MODE_MAX + 1];
struct crypto_skcipher *mk_iv_ino_lblk_32_keys[__FSCRYPT_MODE_MAX + 1]; struct fscrypt_prepared_key mk_iv_ino_lblk_32_keys[__FSCRYPT_MODE_MAX + 1];
/* Hash key for inode numbers. Initialized only when needed. */ /* Hash key for inode numbers. Initialized only when needed. */
siphash_key_t mk_ino_hash_key; siphash_key_t mk_ino_hash_key;
...@@ -461,13 +557,15 @@ struct fscrypt_mode { ...@@ -461,13 +557,15 @@ struct fscrypt_mode {
int keysize; int keysize;
int ivsize; int ivsize;
int logged_impl_name; int logged_impl_name;
enum blk_crypto_mode_num blk_crypto_mode;
}; };
extern struct fscrypt_mode fscrypt_modes[]; extern struct fscrypt_mode fscrypt_modes[];
struct crypto_skcipher *fscrypt_allocate_skcipher(struct fscrypt_mode *mode, int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key,
const u8 *raw_key, const u8 *raw_key, const struct fscrypt_info *ci);
const struct inode *inode);
void fscrypt_destroy_prepared_key(struct fscrypt_prepared_key *prep_key);
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);
......
This diff is collapsed.
...@@ -45,9 +45,9 @@ static void free_master_key(struct fscrypt_master_key *mk) ...@@ -45,9 +45,9 @@ static void free_master_key(struct fscrypt_master_key *mk)
wipe_master_key_secret(&mk->mk_secret); wipe_master_key_secret(&mk->mk_secret);
for (i = 0; i <= __FSCRYPT_MODE_MAX; i++) { for (i = 0; i <= __FSCRYPT_MODE_MAX; i++) {
crypto_free_skcipher(mk->mk_direct_keys[i]); fscrypt_destroy_prepared_key(&mk->mk_direct_keys[i]);
crypto_free_skcipher(mk->mk_iv_ino_lblk_64_keys[i]); fscrypt_destroy_prepared_key(&mk->mk_iv_ino_lblk_64_keys[i]);
crypto_free_skcipher(mk->mk_iv_ino_lblk_32_keys[i]); fscrypt_destroy_prepared_key(&mk->mk_iv_ino_lblk_32_keys[i]);
} }
key_put(mk->mk_users); key_put(mk->mk_users);
...@@ -213,7 +213,11 @@ static int allocate_filesystem_keyring(struct super_block *sb) ...@@ -213,7 +213,11 @@ static int allocate_filesystem_keyring(struct super_block *sb)
if (IS_ERR(keyring)) if (IS_ERR(keyring))
return PTR_ERR(keyring); return PTR_ERR(keyring);
/* Pairs with READ_ONCE() in fscrypt_find_master_key() */ /*
* Pairs with the smp_load_acquire() in fscrypt_find_master_key().
* I.e., here we publish ->s_master_keys with a RELEASE barrier so that
* concurrent tasks can ACQUIRE it.
*/
smp_store_release(&sb->s_master_keys, keyring); smp_store_release(&sb->s_master_keys, keyring);
return 0; return 0;
} }
...@@ -234,8 +238,13 @@ struct key *fscrypt_find_master_key(struct super_block *sb, ...@@ -234,8 +238,13 @@ struct key *fscrypt_find_master_key(struct super_block *sb,
struct key *keyring; struct key *keyring;
char description[FSCRYPT_MK_DESCRIPTION_SIZE]; char description[FSCRYPT_MK_DESCRIPTION_SIZE];
/* pairs with smp_store_release() in allocate_filesystem_keyring() */ /*
keyring = READ_ONCE(sb->s_master_keys); * Pairs with the smp_store_release() in allocate_filesystem_keyring().
* I.e., another task can publish ->s_master_keys concurrently,
* executing a RELEASE barrier. We need to use smp_load_acquire() here
* to safely ACQUIRE the memory the other task published.
*/
keyring = smp_load_acquire(&sb->s_master_keys);
if (keyring == NULL) if (keyring == NULL)
return ERR_PTR(-ENOKEY); /* No keyring yet, so no keys yet. */ return ERR_PTR(-ENOKEY); /* No keyring yet, so no keys yet. */
......
...@@ -19,6 +19,7 @@ struct fscrypt_mode fscrypt_modes[] = { ...@@ -19,6 +19,7 @@ struct fscrypt_mode fscrypt_modes[] = {
.cipher_str = "xts(aes)", .cipher_str = "xts(aes)",
.keysize = 64, .keysize = 64,
.ivsize = 16, .ivsize = 16,
.blk_crypto_mode = BLK_ENCRYPTION_MODE_AES_256_XTS,
}, },
[FSCRYPT_MODE_AES_256_CTS] = { [FSCRYPT_MODE_AES_256_CTS] = {
.friendly_name = "AES-256-CTS-CBC", .friendly_name = "AES-256-CTS-CBC",
...@@ -31,6 +32,7 @@ struct fscrypt_mode fscrypt_modes[] = { ...@@ -31,6 +32,7 @@ struct fscrypt_mode fscrypt_modes[] = {
.cipher_str = "essiv(cbc(aes),sha256)", .cipher_str = "essiv(cbc(aes),sha256)",
.keysize = 16, .keysize = 16,
.ivsize = 16, .ivsize = 16,
.blk_crypto_mode = BLK_ENCRYPTION_MODE_AES_128_CBC_ESSIV,
}, },
[FSCRYPT_MODE_AES_128_CTS] = { [FSCRYPT_MODE_AES_128_CTS] = {
.friendly_name = "AES-128-CTS-CBC", .friendly_name = "AES-128-CTS-CBC",
...@@ -43,6 +45,7 @@ struct fscrypt_mode fscrypt_modes[] = { ...@@ -43,6 +45,7 @@ struct fscrypt_mode fscrypt_modes[] = {
.cipher_str = "adiantum(xchacha12,aes)", .cipher_str = "adiantum(xchacha12,aes)",
.keysize = 32, .keysize = 32,
.ivsize = 32, .ivsize = 32,
.blk_crypto_mode = BLK_ENCRYPTION_MODE_ADIANTUM,
}, },
}; };
...@@ -64,9 +67,9 @@ select_encryption_mode(const union fscrypt_policy *policy, ...@@ -64,9 +67,9 @@ select_encryption_mode(const union fscrypt_policy *policy,
} }
/* Create a symmetric cipher object for the given encryption mode and key */ /* Create a symmetric cipher object for the given encryption mode and key */
struct crypto_skcipher *fscrypt_allocate_skcipher(struct fscrypt_mode *mode, static struct crypto_skcipher *
const u8 *raw_key, fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key,
const struct inode *inode) const struct inode *inode)
{ {
struct crypto_skcipher *tfm; struct crypto_skcipher *tfm;
int err; int err;
...@@ -109,30 +112,56 @@ struct crypto_skcipher *fscrypt_allocate_skcipher(struct fscrypt_mode *mode, ...@@ -109,30 +112,56 @@ struct crypto_skcipher *fscrypt_allocate_skcipher(struct fscrypt_mode *mode,
return ERR_PTR(err); return ERR_PTR(err);
} }
/* Given a per-file encryption key, set up the file's crypto transform object */ /*
int fscrypt_set_per_file_enc_key(struct fscrypt_info *ci, const u8 *raw_key) * Prepare the crypto transform object or blk-crypto key in @prep_key, given the
* raw key, encryption mode, and flag indicating which encryption implementation
* (fs-layer or blk-crypto) will be used.
*/
int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key,
const u8 *raw_key, const struct fscrypt_info *ci)
{ {
struct crypto_skcipher *tfm; struct crypto_skcipher *tfm;
if (fscrypt_using_inline_encryption(ci))
return fscrypt_prepare_inline_crypt_key(prep_key, raw_key, ci);
tfm = fscrypt_allocate_skcipher(ci->ci_mode, raw_key, ci->ci_inode); tfm = fscrypt_allocate_skcipher(ci->ci_mode, raw_key, ci->ci_inode);
if (IS_ERR(tfm)) if (IS_ERR(tfm))
return PTR_ERR(tfm); return PTR_ERR(tfm);
/*
* Pairs with the smp_load_acquire() in fscrypt_is_key_prepared().
* I.e., here we publish ->tfm with a RELEASE barrier so that
* concurrent tasks can ACQUIRE it. Note that this concurrency is only
* possible for per-mode keys, not for per-file keys.
*/
smp_store_release(&prep_key->tfm, tfm);
return 0;
}
ci->ci_ctfm = tfm; /* Destroy a crypto transform object and/or blk-crypto key. */
void fscrypt_destroy_prepared_key(struct fscrypt_prepared_key *prep_key)
{
crypto_free_skcipher(prep_key->tfm);
fscrypt_destroy_inline_crypt_key(prep_key);
}
/* Given a per-file encryption key, set up the file's crypto transform object */
int fscrypt_set_per_file_enc_key(struct fscrypt_info *ci, const u8 *raw_key)
{
ci->ci_owns_key = true; ci->ci_owns_key = true;
return 0; return fscrypt_prepare_key(&ci->ci_enc_key, raw_key, ci);
} }
static int setup_per_mode_enc_key(struct fscrypt_info *ci, static int setup_per_mode_enc_key(struct fscrypt_info *ci,
struct fscrypt_master_key *mk, struct fscrypt_master_key *mk,
struct crypto_skcipher **tfms, struct fscrypt_prepared_key *keys,
u8 hkdf_context, bool include_fs_uuid) u8 hkdf_context, bool include_fs_uuid)
{ {
const struct inode *inode = ci->ci_inode; const struct inode *inode = ci->ci_inode;
const struct super_block *sb = inode->i_sb; const struct super_block *sb = inode->i_sb;
struct fscrypt_mode *mode = ci->ci_mode; struct fscrypt_mode *mode = ci->ci_mode;
const u8 mode_num = mode - fscrypt_modes; const u8 mode_num = mode - fscrypt_modes;
struct crypto_skcipher *tfm; struct fscrypt_prepared_key *prep_key;
u8 mode_key[FSCRYPT_MAX_KEY_SIZE]; u8 mode_key[FSCRYPT_MAX_KEY_SIZE];
u8 hkdf_info[sizeof(mode_num) + sizeof(sb->s_uuid)]; u8 hkdf_info[sizeof(mode_num) + sizeof(sb->s_uuid)];
unsigned int hkdf_infolen = 0; unsigned int hkdf_infolen = 0;
...@@ -141,16 +170,15 @@ static int setup_per_mode_enc_key(struct fscrypt_info *ci, ...@@ -141,16 +170,15 @@ static int setup_per_mode_enc_key(struct fscrypt_info *ci,
if (WARN_ON(mode_num > __FSCRYPT_MODE_MAX)) if (WARN_ON(mode_num > __FSCRYPT_MODE_MAX))
return -EINVAL; return -EINVAL;
/* pairs with smp_store_release() below */ prep_key = &keys[mode_num];
tfm = READ_ONCE(tfms[mode_num]); if (fscrypt_is_key_prepared(prep_key, ci)) {
if (likely(tfm != NULL)) { ci->ci_enc_key = *prep_key;
ci->ci_ctfm = tfm;
return 0; return 0;
} }
mutex_lock(&fscrypt_mode_key_setup_mutex); mutex_lock(&fscrypt_mode_key_setup_mutex);
if (tfms[mode_num]) if (fscrypt_is_key_prepared(prep_key, ci))
goto done_unlock; goto done_unlock;
BUILD_BUG_ON(sizeof(mode_num) != 1); BUILD_BUG_ON(sizeof(mode_num) != 1);
...@@ -167,16 +195,12 @@ static int setup_per_mode_enc_key(struct fscrypt_info *ci, ...@@ -167,16 +195,12 @@ static int setup_per_mode_enc_key(struct fscrypt_info *ci,
mode_key, mode->keysize); mode_key, mode->keysize);
if (err) if (err)
goto out_unlock; goto out_unlock;
tfm = fscrypt_allocate_skcipher(mode, mode_key, inode); err = fscrypt_prepare_key(prep_key, mode_key, ci);
memzero_explicit(mode_key, mode->keysize); memzero_explicit(mode_key, mode->keysize);
if (IS_ERR(tfm)) { if (err)
err = PTR_ERR(tfm);
goto out_unlock; goto out_unlock;
}
/* pairs with READ_ONCE() above */
smp_store_release(&tfms[mode_num], tfm);
done_unlock: done_unlock:
ci->ci_ctfm = tfm; ci->ci_enc_key = *prep_key;
err = 0; err = 0;
out_unlock: out_unlock:
mutex_unlock(&fscrypt_mode_key_setup_mutex); mutex_unlock(&fscrypt_mode_key_setup_mutex);
...@@ -189,7 +213,7 @@ int fscrypt_derive_dirhash_key(struct fscrypt_info *ci, ...@@ -189,7 +213,7 @@ int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
int err; int err;
err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, HKDF_CONTEXT_DIRHASH_KEY, err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, HKDF_CONTEXT_DIRHASH_KEY,
ci->ci_nonce, FS_KEY_DERIVATION_NONCE_SIZE, ci->ci_nonce, FSCRYPT_FILE_NONCE_SIZE,
(u8 *)&ci->ci_dirhash_key, (u8 *)&ci->ci_dirhash_key,
sizeof(ci->ci_dirhash_key)); sizeof(ci->ci_dirhash_key));
if (err) if (err)
...@@ -270,8 +294,7 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci, ...@@ -270,8 +294,7 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci,
err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf,
HKDF_CONTEXT_PER_FILE_ENC_KEY, HKDF_CONTEXT_PER_FILE_ENC_KEY,
ci->ci_nonce, ci->ci_nonce, FSCRYPT_FILE_NONCE_SIZE,
FS_KEY_DERIVATION_NONCE_SIZE,
derived_key, ci->ci_mode->keysize); derived_key, ci->ci_mode->keysize);
if (err) if (err)
return err; return err;
...@@ -310,6 +333,10 @@ static int setup_file_encryption_key(struct fscrypt_info *ci, ...@@ -310,6 +333,10 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
struct fscrypt_key_specifier mk_spec; struct fscrypt_key_specifier mk_spec;
int err; int err;
err = fscrypt_select_encryption_impl(ci);
if (err)
return err;
switch (ci->ci_policy.version) { switch (ci->ci_policy.version) {
case FSCRYPT_POLICY_V1: case FSCRYPT_POLICY_V1:
mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR; mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR;
...@@ -402,7 +429,7 @@ static void put_crypt_info(struct fscrypt_info *ci) ...@@ -402,7 +429,7 @@ static void put_crypt_info(struct fscrypt_info *ci)
if (ci->ci_direct_key) if (ci->ci_direct_key)
fscrypt_put_direct_key(ci->ci_direct_key); fscrypt_put_direct_key(ci->ci_direct_key);
else if (ci->ci_owns_key) else if (ci->ci_owns_key)
crypto_free_skcipher(ci->ci_ctfm); fscrypt_destroy_prepared_key(&ci->ci_enc_key);
key = ci->ci_master_key; key = ci->ci_master_key;
if (key) { if (key) {
...@@ -472,7 +499,7 @@ int fscrypt_get_encryption_info(struct inode *inode) ...@@ -472,7 +499,7 @@ int fscrypt_get_encryption_info(struct inode *inode)
} }
memcpy(crypt_info->ci_nonce, fscrypt_context_nonce(&ctx), memcpy(crypt_info->ci_nonce, fscrypt_context_nonce(&ctx),
FS_KEY_DERIVATION_NONCE_SIZE); FSCRYPT_FILE_NONCE_SIZE);
if (!fscrypt_supported_policy(&crypt_info->ci_policy, inode)) { if (!fscrypt_supported_policy(&crypt_info->ci_policy, inode)) {
res = -EINVAL; res = -EINVAL;
...@@ -491,7 +518,17 @@ int fscrypt_get_encryption_info(struct inode *inode) ...@@ -491,7 +518,17 @@ int fscrypt_get_encryption_info(struct inode *inode)
if (res) if (res)
goto out; goto out;
/*
* Multiple tasks may race to set ->i_crypt_info, 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
* RELEASE barrier so that other tasks can ACQUIRE it.
*/
if (cmpxchg_release(&inode->i_crypt_info, NULL, crypt_info) == NULL) { if (cmpxchg_release(&inode->i_crypt_info, NULL, crypt_info) == NULL) {
/*
* We won the race and set ->i_crypt_info to our crypt_info.
* Now link it into the master key's inode list.
*/
if (master_key) { if (master_key) {
struct fscrypt_master_key *mk = struct fscrypt_master_key *mk =
master_key->payload.data[0]; master_key->payload.data[0];
...@@ -562,7 +599,7 @@ EXPORT_SYMBOL(fscrypt_free_inode); ...@@ -562,7 +599,7 @@ EXPORT_SYMBOL(fscrypt_free_inode);
*/ */
int fscrypt_drop_inode(struct inode *inode) int fscrypt_drop_inode(struct inode *inode)
{ {
const struct fscrypt_info *ci = READ_ONCE(inode->i_crypt_info); const struct fscrypt_info *ci = fscrypt_get_info(inode);
const struct fscrypt_master_key *mk; const struct fscrypt_master_key *mk;
/* /*
......
...@@ -45,7 +45,7 @@ static DEFINE_SPINLOCK(fscrypt_direct_keys_lock); ...@@ -45,7 +45,7 @@ static DEFINE_SPINLOCK(fscrypt_direct_keys_lock);
* key is longer, then only the first 'derived_keysize' bytes are used. * key is longer, then only the first 'derived_keysize' bytes are used.
*/ */
static int derive_key_aes(const u8 *master_key, static int derive_key_aes(const u8 *master_key,
const u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE], const u8 nonce[FSCRYPT_FILE_NONCE_SIZE],
u8 *derived_key, unsigned int derived_keysize) u8 *derived_key, unsigned int derived_keysize)
{ {
int res = 0; int res = 0;
...@@ -68,7 +68,7 @@ static int derive_key_aes(const u8 *master_key, ...@@ -68,7 +68,7 @@ static int derive_key_aes(const u8 *master_key,
skcipher_request_set_callback(req, skcipher_request_set_callback(req,
CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
crypto_req_done, &wait); crypto_req_done, &wait);
res = crypto_skcipher_setkey(tfm, nonce, FS_KEY_DERIVATION_NONCE_SIZE); res = crypto_skcipher_setkey(tfm, nonce, FSCRYPT_FILE_NONCE_SIZE);
if (res < 0) if (res < 0)
goto out; goto out;
...@@ -146,7 +146,7 @@ struct fscrypt_direct_key { ...@@ -146,7 +146,7 @@ struct fscrypt_direct_key {
struct hlist_node dk_node; struct hlist_node dk_node;
refcount_t dk_refcount; refcount_t dk_refcount;
const struct fscrypt_mode *dk_mode; const struct fscrypt_mode *dk_mode;
struct crypto_skcipher *dk_ctfm; struct fscrypt_prepared_key dk_key;
u8 dk_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; u8 dk_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE];
u8 dk_raw[FSCRYPT_MAX_KEY_SIZE]; u8 dk_raw[FSCRYPT_MAX_KEY_SIZE];
}; };
...@@ -154,7 +154,7 @@ struct fscrypt_direct_key { ...@@ -154,7 +154,7 @@ struct fscrypt_direct_key {
static void free_direct_key(struct fscrypt_direct_key *dk) static void free_direct_key(struct fscrypt_direct_key *dk)
{ {
if (dk) { if (dk) {
crypto_free_skcipher(dk->dk_ctfm); fscrypt_destroy_prepared_key(&dk->dk_key);
kzfree(dk); kzfree(dk);
} }
} }
...@@ -199,6 +199,8 @@ find_or_insert_direct_key(struct fscrypt_direct_key *to_insert, ...@@ -199,6 +199,8 @@ find_or_insert_direct_key(struct fscrypt_direct_key *to_insert,
continue; continue;
if (ci->ci_mode != dk->dk_mode) if (ci->ci_mode != dk->dk_mode)
continue; continue;
if (!fscrypt_is_key_prepared(&dk->dk_key, ci))
continue;
if (crypto_memneq(raw_key, dk->dk_raw, ci->ci_mode->keysize)) if (crypto_memneq(raw_key, dk->dk_raw, ci->ci_mode->keysize))
continue; continue;
/* using existing tfm with same (descriptor, mode, raw_key) */ /* using existing tfm with same (descriptor, mode, raw_key) */
...@@ -231,13 +233,9 @@ fscrypt_get_direct_key(const struct fscrypt_info *ci, const u8 *raw_key) ...@@ -231,13 +233,9 @@ fscrypt_get_direct_key(const struct fscrypt_info *ci, const u8 *raw_key)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
refcount_set(&dk->dk_refcount, 1); refcount_set(&dk->dk_refcount, 1);
dk->dk_mode = ci->ci_mode; dk->dk_mode = ci->ci_mode;
dk->dk_ctfm = fscrypt_allocate_skcipher(ci->ci_mode, raw_key, err = fscrypt_prepare_key(&dk->dk_key, raw_key, ci);
ci->ci_inode); if (err)
if (IS_ERR(dk->dk_ctfm)) {
err = PTR_ERR(dk->dk_ctfm);
dk->dk_ctfm = NULL;
goto err_free_dk; goto err_free_dk;
}
memcpy(dk->dk_descriptor, ci->ci_policy.v1.master_key_descriptor, memcpy(dk->dk_descriptor, ci->ci_policy.v1.master_key_descriptor,
FSCRYPT_KEY_DESCRIPTOR_SIZE); FSCRYPT_KEY_DESCRIPTOR_SIZE);
memcpy(dk->dk_raw, raw_key, ci->ci_mode->keysize); memcpy(dk->dk_raw, raw_key, ci->ci_mode->keysize);
...@@ -259,7 +257,7 @@ static int setup_v1_file_key_direct(struct fscrypt_info *ci, ...@@ -259,7 +257,7 @@ static int setup_v1_file_key_direct(struct fscrypt_info *ci,
if (IS_ERR(dk)) if (IS_ERR(dk))
return PTR_ERR(dk); return PTR_ERR(dk);
ci->ci_direct_key = dk; ci->ci_direct_key = dk;
ci->ci_ctfm = dk->dk_ctfm; ci->ci_enc_key = dk->dk_key;
return 0; return 0;
} }
......
...@@ -77,6 +77,20 @@ static bool supported_iv_ino_lblk_policy(const struct fscrypt_policy_v2 *policy, ...@@ -77,6 +77,20 @@ static bool supported_iv_ino_lblk_policy(const struct fscrypt_policy_v2 *policy,
struct super_block *sb = inode->i_sb; struct super_block *sb = inode->i_sb;
int ino_bits = 64, lblk_bits = 64; int ino_bits = 64, lblk_bits = 64;
/*
* IV_INO_LBLK_* exist only because of hardware limitations, and
* currently the only known use case for them involves AES-256-XTS.
* That's also all we test currently. For these reasons, for now only
* allow AES-256-XTS here. This can be relaxed later if a use case for
* IV_INO_LBLK_* with other encryption modes arises.
*/
if (policy->contents_encryption_mode != FSCRYPT_MODE_AES_256_XTS) {
fscrypt_warn(inode,
"Can't use %s policy with contents mode other than AES-256-XTS",
type);
return false;
}
/* /*
* It's unsafe to include inode numbers in the IVs if the filesystem can * It's unsafe to include inode numbers in the IVs if the filesystem can
* potentially renumber inodes, e.g. via filesystem shrinking. * potentially renumber inodes, e.g. via filesystem shrinking.
...@@ -338,7 +352,7 @@ static int fscrypt_get_policy(struct inode *inode, union fscrypt_policy *policy) ...@@ -338,7 +352,7 @@ static int fscrypt_get_policy(struct inode *inode, union fscrypt_policy *policy)
union fscrypt_context ctx; union fscrypt_context ctx;
int ret; int ret;
ci = READ_ONCE(inode->i_crypt_info); ci = fscrypt_get_info(inode);
if (ci) { if (ci) {
/* key available, use the cached policy */ /* key available, use the cached policy */
*policy = ci->ci_policy; *policy = ci->ci_policy;
...@@ -529,7 +543,7 @@ int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg) ...@@ -529,7 +543,7 @@ int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg)
if (!fscrypt_context_is_valid(&ctx, ret)) if (!fscrypt_context_is_valid(&ctx, ret))
return -EINVAL; return -EINVAL;
if (copy_to_user(arg, fscrypt_context_nonce(&ctx), if (copy_to_user(arg, fscrypt_context_nonce(&ctx),
FS_KEY_DERIVATION_NONCE_SIZE)) FSCRYPT_FILE_NONCE_SIZE))
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
...@@ -627,7 +641,7 @@ int fscrypt_inherit_context(struct inode *parent, struct inode *child, ...@@ -627,7 +641,7 @@ int fscrypt_inherit_context(struct inode *parent, struct inode *child,
if (res < 0) if (res < 0)
return res; return res;
ci = READ_ONCE(parent->i_crypt_info); ci = fscrypt_get_info(parent);
if (ci == NULL) if (ci == NULL)
return -ENOKEY; return -ENOKEY;
......
...@@ -1096,7 +1096,7 @@ static int ext4_block_write_begin(struct page *page, loff_t pos, unsigned len, ...@@ -1096,7 +1096,7 @@ static int ext4_block_write_begin(struct page *page, loff_t pos, unsigned len,
} }
if (unlikely(err)) { if (unlikely(err)) {
page_zero_new_buffers(page, from, to); page_zero_new_buffers(page, from, to);
} else if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode)) { } else if (fscrypt_inode_uses_fs_layer_crypto(inode)) {
for (i = 0; i < nr_wait; i++) { for (i = 0; i < nr_wait; i++) {
int err2; int err2;
...@@ -3737,7 +3737,7 @@ static int __ext4_block_zero_page_range(handle_t *handle, ...@@ -3737,7 +3737,7 @@ static int __ext4_block_zero_page_range(handle_t *handle,
/* Uhhuh. Read error. Complain and punt. */ /* Uhhuh. Read error. Complain and punt. */
if (!buffer_uptodate(bh)) if (!buffer_uptodate(bh))
goto unlock; goto unlock;
if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode)) { if (fscrypt_inode_uses_fs_layer_crypto(inode)) {
/* We expect the key to be set. */ /* We expect the key to be set. */
BUG_ON(!fscrypt_has_encryption_key(inode)); BUG_ON(!fscrypt_has_encryption_key(inode));
err = fscrypt_decrypt_pagecache_blocks(page, blocksize, err = fscrypt_decrypt_pagecache_blocks(page, blocksize,
......
...@@ -402,6 +402,7 @@ static void io_submit_init_bio(struct ext4_io_submit *io, ...@@ -402,6 +402,7 @@ static void io_submit_init_bio(struct ext4_io_submit *io,
* __GFP_DIRECT_RECLAIM is set, see comments for bio_alloc_bioset(). * __GFP_DIRECT_RECLAIM is set, see comments for bio_alloc_bioset().
*/ */
bio = bio_alloc(GFP_NOIO, BIO_MAX_PAGES); bio = bio_alloc(GFP_NOIO, BIO_MAX_PAGES);
fscrypt_set_bio_crypt_ctx_bh(bio, bh, GFP_NOIO);
bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9); bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9);
bio_set_dev(bio, bh->b_bdev); bio_set_dev(bio, bh->b_bdev);
bio->bi_end_io = ext4_end_bio; bio->bi_end_io = ext4_end_bio;
...@@ -418,7 +419,8 @@ static void io_submit_add_bh(struct ext4_io_submit *io, ...@@ -418,7 +419,8 @@ static void io_submit_add_bh(struct ext4_io_submit *io,
{ {
int ret; int ret;
if (io->io_bio && bh->b_blocknr != io->io_next_block) { if (io->io_bio && (bh->b_blocknr != io->io_next_block ||
!fscrypt_mergeable_bio_bh(io->io_bio, bh))) {
submit_and_retry: submit_and_retry:
ext4_io_submit(io); ext4_io_submit(io);
} }
...@@ -506,7 +508,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io, ...@@ -506,7 +508,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
* (e.g. holes) to be unnecessarily encrypted, but this is rare and * (e.g. holes) to be unnecessarily encrypted, but this is rare and
* can't happen in the common case of blocksize == PAGE_SIZE. * can't happen in the common case of blocksize == PAGE_SIZE.
*/ */
if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode) && nr_to_submit) { if (fscrypt_inode_uses_fs_layer_crypto(inode) && nr_to_submit) {
gfp_t gfp_flags = GFP_NOFS; gfp_t gfp_flags = GFP_NOFS;
unsigned int enc_bytes = round_up(len, i_blocksize(inode)); unsigned int enc_bytes = round_up(len, i_blocksize(inode));
......
...@@ -195,7 +195,7 @@ static void ext4_set_bio_post_read_ctx(struct bio *bio, ...@@ -195,7 +195,7 @@ static void ext4_set_bio_post_read_ctx(struct bio *bio,
{ {
unsigned int post_read_steps = 0; unsigned int post_read_steps = 0;
if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode)) if (fscrypt_inode_uses_fs_layer_crypto(inode))
post_read_steps |= 1 << STEP_DECRYPT; post_read_steps |= 1 << STEP_DECRYPT;
if (ext4_need_verity(inode, first_idx)) if (ext4_need_verity(inode, first_idx))
...@@ -230,6 +230,7 @@ int ext4_mpage_readpages(struct inode *inode, ...@@ -230,6 +230,7 @@ int ext4_mpage_readpages(struct inode *inode,
const unsigned blkbits = inode->i_blkbits; const unsigned blkbits = inode->i_blkbits;
const unsigned blocks_per_page = PAGE_SIZE >> blkbits; const unsigned blocks_per_page = PAGE_SIZE >> blkbits;
const unsigned blocksize = 1 << blkbits; const unsigned blocksize = 1 << blkbits;
sector_t next_block;
sector_t block_in_file; sector_t block_in_file;
sector_t last_block; sector_t last_block;
sector_t last_block_in_file; sector_t last_block_in_file;
...@@ -258,7 +259,8 @@ int ext4_mpage_readpages(struct inode *inode, ...@@ -258,7 +259,8 @@ int ext4_mpage_readpages(struct inode *inode,
if (page_has_buffers(page)) if (page_has_buffers(page))
goto confused; goto confused;
block_in_file = (sector_t)page->index << (PAGE_SHIFT - blkbits); block_in_file = next_block =
(sector_t)page->index << (PAGE_SHIFT - blkbits);
last_block = block_in_file + nr_pages * blocks_per_page; last_block = block_in_file + nr_pages * blocks_per_page;
last_block_in_file = (ext4_readpage_limit(inode) + last_block_in_file = (ext4_readpage_limit(inode) +
blocksize - 1) >> blkbits; blocksize - 1) >> blkbits;
...@@ -358,7 +360,8 @@ int ext4_mpage_readpages(struct inode *inode, ...@@ -358,7 +360,8 @@ int ext4_mpage_readpages(struct inode *inode,
* This page will go to BIO. Do we need to send this * This page will go to BIO. Do we need to send this
* BIO off first? * BIO off first?
*/ */
if (bio && (last_block_in_bio != blocks[0] - 1)) { if (bio && (last_block_in_bio != blocks[0] - 1 ||
!fscrypt_mergeable_bio(bio, inode, next_block))) {
submit_and_realloc: submit_and_realloc:
submit_bio(bio); submit_bio(bio);
bio = NULL; bio = NULL;
...@@ -370,6 +373,8 @@ int ext4_mpage_readpages(struct inode *inode, ...@@ -370,6 +373,8 @@ int ext4_mpage_readpages(struct inode *inode,
*/ */
bio = bio_alloc(GFP_KERNEL, bio = bio_alloc(GFP_KERNEL,
min_t(int, nr_pages, BIO_MAX_PAGES)); min_t(int, nr_pages, BIO_MAX_PAGES));
fscrypt_set_bio_crypt_ctx(bio, inode, next_block,
GFP_KERNEL);
ext4_set_bio_post_read_ctx(bio, inode, page->index); ext4_set_bio_post_read_ctx(bio, inode, page->index);
bio_set_dev(bio, bdev); bio_set_dev(bio, bdev);
bio->bi_iter.bi_sector = blocks[0] << (blkbits - 9); bio->bi_iter.bi_sector = blocks[0] << (blkbits - 9);
......
...@@ -1508,6 +1508,7 @@ enum { ...@@ -1508,6 +1508,7 @@ enum {
Opt_journal_path, Opt_journal_checksum, Opt_journal_async_commit, Opt_journal_path, Opt_journal_checksum, Opt_journal_async_commit,
Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
Opt_data_err_abort, Opt_data_err_ignore, Opt_test_dummy_encryption, Opt_data_err_abort, Opt_data_err_ignore, Opt_test_dummy_encryption,
Opt_inlinecrypt,
Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota, Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota,
Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err, Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err,
...@@ -1610,6 +1611,7 @@ static const match_table_t tokens = { ...@@ -1610,6 +1611,7 @@ static const match_table_t tokens = {
{Opt_max_dir_size_kb, "max_dir_size_kb=%u"}, {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=%s"},
{Opt_test_dummy_encryption, "test_dummy_encryption"}, {Opt_test_dummy_encryption, "test_dummy_encryption"},
{Opt_inlinecrypt, "inlinecrypt"},
{Opt_nombcache, "nombcache"}, {Opt_nombcache, "nombcache"},
{Opt_nombcache, "no_mbcache"}, /* for backward compatibility */ {Opt_nombcache, "no_mbcache"}, /* for backward compatibility */
{Opt_removed, "check=none"}, /* mount option from ext2/3 */ {Opt_removed, "check=none"}, /* mount option from ext2/3 */
...@@ -1946,6 +1948,13 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token, ...@@ -1946,6 +1948,13 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
case Opt_nolazytime: case Opt_nolazytime:
sb->s_flags &= ~SB_LAZYTIME; sb->s_flags &= ~SB_LAZYTIME;
return 1; return 1;
case Opt_inlinecrypt:
#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
sb->s_flags |= SB_INLINECRYPT;
#else
ext4_msg(sb, KERN_ERR, "inline encryption not supported");
#endif
return 1;
} }
for (m = ext4_mount_opts; m->token != Opt_err; m++) for (m = ext4_mount_opts; m->token != Opt_err; m++)
...@@ -2404,6 +2413,9 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb, ...@@ -2404,6 +2413,9 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
fscrypt_show_test_dummy_encryption(seq, sep, sb); fscrypt_show_test_dummy_encryption(seq, sep, sb);
if (sb->s_flags & SB_INLINECRYPT)
SEQ_OPTS_PUTS("inlinecrypt");
if (test_opt(sb, DAX_ALWAYS)) { if (test_opt(sb, DAX_ALWAYS)) {
if (IS_EXT2_SB(sb)) if (IS_EXT2_SB(sb))
SEQ_OPTS_PUTS("dax"); SEQ_OPTS_PUTS("dax");
......
...@@ -1086,7 +1086,7 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc, ...@@ -1086,7 +1086,7 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc,
.submitted = false, .submitted = false,
.io_type = io_type, .io_type = io_type,
.io_wbc = wbc, .io_wbc = wbc,
.encrypted = f2fs_encrypted_file(cc->inode), .encrypted = fscrypt_inode_uses_fs_layer_crypto(cc->inode),
}; };
struct dnode_of_data dn; struct dnode_of_data dn;
struct node_info ni; struct node_info ni;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/pagevec.h> #include <linux/pagevec.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/bio.h> #include <linux/bio.h>
#include <linux/blk-crypto.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/prefetch.h> #include <linux/prefetch.h>
#include <linux/uio.h> #include <linux/uio.h>
...@@ -459,6 +460,33 @@ static struct bio *__bio_alloc(struct f2fs_io_info *fio, int npages) ...@@ -459,6 +460,33 @@ static struct bio *__bio_alloc(struct f2fs_io_info *fio, int npages)
return bio; return bio;
} }
static void f2fs_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode,
pgoff_t first_idx,
const struct f2fs_io_info *fio,
gfp_t gfp_mask)
{
/*
* The f2fs garbage collector sets ->encrypted_page when it wants to
* read/write raw data without encryption.
*/
if (!fio || !fio->encrypted_page)
fscrypt_set_bio_crypt_ctx(bio, inode, first_idx, gfp_mask);
}
static bool f2fs_crypt_mergeable_bio(struct bio *bio, const struct inode *inode,
pgoff_t next_idx,
const struct f2fs_io_info *fio)
{
/*
* The f2fs garbage collector sets ->encrypted_page when it wants to
* read/write raw data without encryption.
*/
if (fio && fio->encrypted_page)
return !bio_has_crypt_ctx(bio);
return fscrypt_mergeable_bio(bio, inode, next_idx);
}
static inline void __submit_bio(struct f2fs_sb_info *sbi, static inline void __submit_bio(struct f2fs_sb_info *sbi,
struct bio *bio, enum page_type type) struct bio *bio, enum page_type type)
{ {
...@@ -684,6 +712,9 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) ...@@ -684,6 +712,9 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
/* Allocate a new bio */ /* Allocate a new bio */
bio = __bio_alloc(fio, 1); bio = __bio_alloc(fio, 1);
f2fs_set_bio_crypt_ctx(bio, fio->page->mapping->host,
fio->page->index, fio, GFP_NOIO);
if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
bio_put(bio); bio_put(bio);
return -EFAULT; return -EFAULT;
...@@ -763,9 +794,10 @@ static void del_bio_entry(struct bio_entry *be) ...@@ -763,9 +794,10 @@ static void del_bio_entry(struct bio_entry *be)
kmem_cache_free(bio_entry_slab, be); kmem_cache_free(bio_entry_slab, be);
} }
static int add_ipu_page(struct f2fs_sb_info *sbi, struct bio **bio, static int add_ipu_page(struct f2fs_io_info *fio, struct bio **bio,
struct page *page) struct page *page)
{ {
struct f2fs_sb_info *sbi = fio->sbi;
enum temp_type temp; enum temp_type temp;
bool found = false; bool found = false;
int ret = -EAGAIN; int ret = -EAGAIN;
...@@ -782,13 +814,19 @@ static int add_ipu_page(struct f2fs_sb_info *sbi, struct bio **bio, ...@@ -782,13 +814,19 @@ static int add_ipu_page(struct f2fs_sb_info *sbi, struct bio **bio,
found = true; found = true;
if (bio_add_page(*bio, page, PAGE_SIZE, 0) == f2fs_bug_on(sbi, !page_is_mergeable(sbi, *bio,
PAGE_SIZE) { *fio->last_block,
fio->new_blkaddr));
if (f2fs_crypt_mergeable_bio(*bio,
fio->page->mapping->host,
fio->page->index, fio) &&
bio_add_page(*bio, page, PAGE_SIZE, 0) ==
PAGE_SIZE) {
ret = 0; ret = 0;
break; break;
} }
/* bio is full */ /* page can't be merged into bio; submit the bio */
del_bio_entry(be); del_bio_entry(be);
__submit_bio(sbi, *bio, DATA); __submit_bio(sbi, *bio, DATA);
break; break;
...@@ -880,11 +918,13 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio) ...@@ -880,11 +918,13 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio)
if (!bio) { if (!bio) {
bio = __bio_alloc(fio, BIO_MAX_PAGES); bio = __bio_alloc(fio, BIO_MAX_PAGES);
__attach_io_flag(fio); __attach_io_flag(fio);
f2fs_set_bio_crypt_ctx(bio, fio->page->mapping->host,
fio->page->index, fio, GFP_NOIO);
bio_set_op_attrs(bio, fio->op, fio->op_flags); bio_set_op_attrs(bio, fio->op, fio->op_flags);
add_bio_entry(fio->sbi, bio, page, fio->temp); add_bio_entry(fio->sbi, bio, page, fio->temp);
} else { } else {
if (add_ipu_page(fio->sbi, &bio, page)) if (add_ipu_page(fio, &bio, page))
goto alloc_new; goto alloc_new;
} }
...@@ -936,8 +976,11 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio) ...@@ -936,8 +976,11 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
inc_page_count(sbi, WB_DATA_TYPE(bio_page)); inc_page_count(sbi, WB_DATA_TYPE(bio_page));
if (io->bio && !io_is_mergeable(sbi, io->bio, io, fio, if (io->bio &&
io->last_block_in_bio, fio->new_blkaddr)) (!io_is_mergeable(sbi, io->bio, io, fio, io->last_block_in_bio,
fio->new_blkaddr) ||
!f2fs_crypt_mergeable_bio(io->bio, fio->page->mapping->host,
bio_page->index, fio)))
__submit_merged_bio(io); __submit_merged_bio(io);
alloc_new: alloc_new:
if (io->bio == NULL) { if (io->bio == NULL) {
...@@ -949,6 +992,8 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio) ...@@ -949,6 +992,8 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
goto skip; goto skip;
} }
io->bio = __bio_alloc(fio, BIO_MAX_PAGES); io->bio = __bio_alloc(fio, BIO_MAX_PAGES);
f2fs_set_bio_crypt_ctx(io->bio, fio->page->mapping->host,
bio_page->index, fio, GFP_NOIO);
io->fio = *fio; io->fio = *fio;
} }
...@@ -993,11 +1038,14 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr, ...@@ -993,11 +1038,14 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr,
for_write); for_write);
if (!bio) if (!bio)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
f2fs_set_bio_crypt_ctx(bio, inode, first_idx, NULL, GFP_NOFS);
f2fs_target_device(sbi, blkaddr, bio); f2fs_target_device(sbi, blkaddr, bio);
bio->bi_end_io = f2fs_read_end_io; bio->bi_end_io = f2fs_read_end_io;
bio_set_op_attrs(bio, REQ_OP_READ, op_flag); bio_set_op_attrs(bio, REQ_OP_READ, op_flag);
if (f2fs_encrypted_file(inode)) if (fscrypt_inode_uses_fs_layer_crypto(inode))
post_read_steps |= 1 << STEP_DECRYPT; post_read_steps |= 1 << STEP_DECRYPT;
if (f2fs_compressed_file(inode)) if (f2fs_compressed_file(inode))
post_read_steps |= 1 << STEP_DECOMPRESS_NOWQ; post_read_steps |= 1 << STEP_DECOMPRESS_NOWQ;
...@@ -2073,8 +2121,9 @@ static int f2fs_read_single_page(struct inode *inode, struct page *page, ...@@ -2073,8 +2121,9 @@ static int f2fs_read_single_page(struct inode *inode, struct page *page,
* This page will go to BIO. Do we need to send this * This page will go to BIO. Do we need to send this
* BIO off first? * BIO off first?
*/ */
if (bio && !page_is_mergeable(F2FS_I_SB(inode), bio, if (bio && (!page_is_mergeable(F2FS_I_SB(inode), bio,
*last_block_in_bio, block_nr)) { *last_block_in_bio, block_nr) ||
!f2fs_crypt_mergeable_bio(bio, inode, page->index, NULL))) {
submit_and_realloc: submit_and_realloc:
__submit_bio(F2FS_I_SB(inode), bio, DATA); __submit_bio(F2FS_I_SB(inode), bio, DATA);
bio = NULL; bio = NULL;
...@@ -2204,8 +2253,9 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret, ...@@ -2204,8 +2253,9 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
blkaddr = data_blkaddr(dn.inode, dn.node_page, blkaddr = data_blkaddr(dn.inode, dn.node_page,
dn.ofs_in_node + i + 1); dn.ofs_in_node + i + 1);
if (bio && !page_is_mergeable(sbi, bio, if (bio && (!page_is_mergeable(sbi, bio,
*last_block_in_bio, blkaddr)) { *last_block_in_bio, blkaddr) ||
!f2fs_crypt_mergeable_bio(bio, inode, page->index, NULL))) {
submit_and_realloc: submit_and_realloc:
__submit_bio(sbi, bio, DATA); __submit_bio(sbi, bio, DATA);
bio = NULL; bio = NULL;
...@@ -2421,6 +2471,9 @@ int f2fs_encrypt_one_page(struct f2fs_io_info *fio) ...@@ -2421,6 +2471,9 @@ int f2fs_encrypt_one_page(struct f2fs_io_info *fio)
/* wait for GCed page writeback via META_MAPPING */ /* wait for GCed page writeback via META_MAPPING */
f2fs_wait_on_block_writeback(inode, fio->old_blkaddr); f2fs_wait_on_block_writeback(inode, fio->old_blkaddr);
if (fscrypt_inode_uses_inline_crypto(inode))
return 0;
retry_encrypt: retry_encrypt:
fio->encrypted_page = fscrypt_encrypt_pagecache_blocks(page, fio->encrypted_page = fscrypt_encrypt_pagecache_blocks(page,
PAGE_SIZE, 0, gfp_flags); PAGE_SIZE, 0, gfp_flags);
...@@ -2594,7 +2647,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) ...@@ -2594,7 +2647,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
f2fs_unlock_op(fio->sbi); f2fs_unlock_op(fio->sbi);
err = f2fs_inplace_write_data(fio); err = f2fs_inplace_write_data(fio);
if (err) { if (err) {
if (f2fs_encrypted_file(inode)) if (fscrypt_inode_uses_fs_layer_crypto(inode))
fscrypt_finalize_bounce_page(&fio->encrypted_page); fscrypt_finalize_bounce_page(&fio->encrypted_page);
if (PageWriteback(page)) if (PageWriteback(page))
end_page_writeback(page); end_page_writeback(page);
......
...@@ -138,6 +138,7 @@ enum { ...@@ -138,6 +138,7 @@ enum {
Opt_alloc, Opt_alloc,
Opt_fsync, Opt_fsync,
Opt_test_dummy_encryption, Opt_test_dummy_encryption,
Opt_inlinecrypt,
Opt_checkpoint_disable, Opt_checkpoint_disable,
Opt_checkpoint_disable_cap, Opt_checkpoint_disable_cap,
Opt_checkpoint_disable_cap_perc, Opt_checkpoint_disable_cap_perc,
...@@ -204,6 +205,7 @@ static match_table_t f2fs_tokens = { ...@@ -204,6 +205,7 @@ static match_table_t f2fs_tokens = {
{Opt_fsync, "fsync_mode=%s"}, {Opt_fsync, "fsync_mode=%s"},
{Opt_test_dummy_encryption, "test_dummy_encryption=%s"}, {Opt_test_dummy_encryption, "test_dummy_encryption=%s"},
{Opt_test_dummy_encryption, "test_dummy_encryption"}, {Opt_test_dummy_encryption, "test_dummy_encryption"},
{Opt_inlinecrypt, "inlinecrypt"},
{Opt_checkpoint_disable, "checkpoint=disable"}, {Opt_checkpoint_disable, "checkpoint=disable"},
{Opt_checkpoint_disable_cap, "checkpoint=disable:%u"}, {Opt_checkpoint_disable_cap, "checkpoint=disable:%u"},
{Opt_checkpoint_disable_cap_perc, "checkpoint=disable:%u%%"}, {Opt_checkpoint_disable_cap_perc, "checkpoint=disable:%u%%"},
...@@ -833,6 +835,13 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) ...@@ -833,6 +835,13 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
if (ret) if (ret)
return ret; return ret;
break; break;
case Opt_inlinecrypt:
#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
sb->s_flags |= SB_INLINECRYPT;
#else
f2fs_info(sbi, "inline encryption not supported");
#endif
break;
case Opt_checkpoint_disable_cap_perc: case Opt_checkpoint_disable_cap_perc:
if (args->from && match_int(args, &arg)) if (args->from && match_int(args, &arg))
return -EINVAL; return -EINVAL;
...@@ -1590,6 +1599,9 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root) ...@@ -1590,6 +1599,9 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
fscrypt_show_test_dummy_encryption(seq, ',', sbi->sb); fscrypt_show_test_dummy_encryption(seq, ',', sbi->sb);
if (sbi->sb->s_flags & SB_INLINECRYPT)
seq_puts(seq, ",inlinecrypt");
if (F2FS_OPTION(sbi).alloc_mode == ALLOC_MODE_DEFAULT) if (F2FS_OPTION(sbi).alloc_mode == ALLOC_MODE_DEFAULT)
seq_printf(seq, ",alloc_mode=%s", "default"); seq_printf(seq, ",alloc_mode=%s", "default");
else if (F2FS_OPTION(sbi).alloc_mode == ALLOC_MODE_REUSE) else if (F2FS_OPTION(sbi).alloc_mode == ALLOC_MODE_REUSE)
...@@ -1624,6 +1636,8 @@ static void default_options(struct f2fs_sb_info *sbi) ...@@ -1624,6 +1636,8 @@ static void default_options(struct f2fs_sb_info *sbi)
F2FS_OPTION(sbi).compress_ext_cnt = 0; F2FS_OPTION(sbi).compress_ext_cnt = 0;
F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_ON; F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_ON;
sbi->sb->s_flags &= ~SB_INLINECRYPT;
set_opt(sbi, INLINE_XATTR); set_opt(sbi, INLINE_XATTR);
set_opt(sbi, INLINE_DATA); set_opt(sbi, INLINE_DATA);
set_opt(sbi, INLINE_DENTRY); set_opt(sbi, INLINE_DENTRY);
...@@ -2470,6 +2484,25 @@ static void f2fs_get_ino_and_lblk_bits(struct super_block *sb, ...@@ -2470,6 +2484,25 @@ static void f2fs_get_ino_and_lblk_bits(struct super_block *sb,
*lblk_bits_ret = 8 * sizeof(block_t); *lblk_bits_ret = 8 * sizeof(block_t);
} }
static int f2fs_get_num_devices(struct super_block *sb)
{
struct f2fs_sb_info *sbi = F2FS_SB(sb);
if (f2fs_is_multi_device(sbi))
return sbi->s_ndevs;
return 1;
}
static void f2fs_get_devices(struct super_block *sb,
struct request_queue **devs)
{
struct f2fs_sb_info *sbi = F2FS_SB(sb);
int i;
for (i = 0; i < sbi->s_ndevs; i++)
devs[i] = bdev_get_queue(FDEV(i).bdev);
}
static const struct fscrypt_operations f2fs_cryptops = { static const struct fscrypt_operations f2fs_cryptops = {
.key_prefix = "f2fs:", .key_prefix = "f2fs:",
.get_context = f2fs_get_context, .get_context = f2fs_get_context,
...@@ -2479,6 +2512,8 @@ static const struct fscrypt_operations f2fs_cryptops = { ...@@ -2479,6 +2512,8 @@ static const struct fscrypt_operations f2fs_cryptops = {
.max_namelen = F2FS_NAME_LEN, .max_namelen = F2FS_NAME_LEN,
.has_stable_inodes = f2fs_has_stable_inodes, .has_stable_inodes = f2fs_has_stable_inodes,
.get_ino_and_lblk_bits = f2fs_get_ino_and_lblk_bits, .get_ino_and_lblk_bits = f2fs_get_ino_and_lblk_bits,
.get_num_devices = f2fs_get_num_devices,
.get_devices = f2fs_get_devices,
}; };
#endif #endif
......
...@@ -1381,6 +1381,7 @@ extern int send_sigurg(struct fown_struct *fown); ...@@ -1381,6 +1381,7 @@ extern int send_sigurg(struct fown_struct *fown);
#define SB_NODIRATIME 2048 /* Do not update directory access times */ #define SB_NODIRATIME 2048 /* Do not update directory access times */
#define SB_SILENT 32768 #define SB_SILENT 32768
#define SB_POSIXACL (1<<16) /* VFS does not apply the umask */ #define SB_POSIXACL (1<<16) /* VFS does not apply the umask */
#define SB_INLINECRYPT (1<<17) /* Use blk-crypto for encrypted files */
#define SB_KERNMOUNT (1<<22) /* this is a kern_mount call */ #define SB_KERNMOUNT (1<<22) /* this is a kern_mount call */
#define SB_I_VERSION (1<<23) /* Update inode I_version field */ #define SB_I_VERSION (1<<23) /* Update inode I_version field */
#define SB_LAZYTIME (1<<25) /* Update the on-disk [acm]times lazily */ #define SB_LAZYTIME (1<<25) /* Update the on-disk [acm]times lazily */
......
...@@ -69,12 +69,20 @@ struct fscrypt_operations { ...@@ -69,12 +69,20 @@ struct fscrypt_operations {
bool (*has_stable_inodes)(struct super_block *sb); bool (*has_stable_inodes)(struct super_block *sb);
void (*get_ino_and_lblk_bits)(struct super_block *sb, void (*get_ino_and_lblk_bits)(struct super_block *sb,
int *ino_bits_ret, int *lblk_bits_ret); int *ino_bits_ret, int *lblk_bits_ret);
int (*get_num_devices)(struct super_block *sb);
void (*get_devices)(struct super_block *sb,
struct request_queue **devs);
}; };
static inline bool fscrypt_has_encryption_key(const struct inode *inode) static inline struct fscrypt_info *fscrypt_get_info(const struct inode *inode)
{ {
/* pairs with cmpxchg_release() in fscrypt_get_encryption_info() */ /*
return READ_ONCE(inode->i_crypt_info) != NULL; * Pairs with the cmpxchg_release() in fscrypt_get_encryption_info().
* I.e., another task may publish ->i_crypt_info concurrently, executing
* a RELEASE barrier. We need to use smp_load_acquire() here to safely
* ACQUIRE the memory the other task published.
*/
return smp_load_acquire(&inode->i_crypt_info);
} }
/** /**
...@@ -231,9 +239,9 @@ static inline void fscrypt_set_ops(struct super_block *sb, ...@@ -231,9 +239,9 @@ static inline void fscrypt_set_ops(struct super_block *sb,
} }
#else /* !CONFIG_FS_ENCRYPTION */ #else /* !CONFIG_FS_ENCRYPTION */
static inline bool fscrypt_has_encryption_key(const struct inode *inode) static inline struct fscrypt_info *fscrypt_get_info(const struct inode *inode)
{ {
return false; return NULL;
} }
static inline bool fscrypt_needs_contents_encryption(const struct inode *inode) static inline bool fscrypt_needs_contents_encryption(const struct inode *inode)
...@@ -537,6 +545,99 @@ static inline void fscrypt_set_ops(struct super_block *sb, ...@@ -537,6 +545,99 @@ static inline void fscrypt_set_ops(struct super_block *sb,
#endif /* !CONFIG_FS_ENCRYPTION */ #endif /* !CONFIG_FS_ENCRYPTION */
/* inline_crypt.c */
#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
bool __fscrypt_inode_uses_inline_crypto(const struct inode *inode);
void fscrypt_set_bio_crypt_ctx(struct bio *bio,
const struct inode *inode, u64 first_lblk,
gfp_t gfp_mask);
void fscrypt_set_bio_crypt_ctx_bh(struct bio *bio,
const struct buffer_head *first_bh,
gfp_t gfp_mask);
bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode,
u64 next_lblk);
bool fscrypt_mergeable_bio_bh(struct bio *bio,
const struct buffer_head *next_bh);
#else /* CONFIG_FS_ENCRYPTION_INLINE_CRYPT */
static inline bool __fscrypt_inode_uses_inline_crypto(const struct inode *inode)
{
return false;
}
static inline void fscrypt_set_bio_crypt_ctx(struct bio *bio,
const struct inode *inode,
u64 first_lblk, gfp_t gfp_mask) { }
static inline void fscrypt_set_bio_crypt_ctx_bh(
struct bio *bio,
const struct buffer_head *first_bh,
gfp_t gfp_mask) { }
static inline bool fscrypt_mergeable_bio(struct bio *bio,
const struct inode *inode,
u64 next_lblk)
{
return true;
}
static inline bool fscrypt_mergeable_bio_bh(struct bio *bio,
const struct buffer_head *next_bh)
{
return true;
}
#endif /* !CONFIG_FS_ENCRYPTION_INLINE_CRYPT */
/**
* fscrypt_inode_uses_inline_crypto() - test whether an inode uses inline
* encryption
* @inode: an inode. If encrypted, its key must be set up.
*
* Return: true if the inode requires file contents encryption and if the
* encryption should be done in the block layer via blk-crypto rather
* than in the filesystem layer.
*/
static inline bool fscrypt_inode_uses_inline_crypto(const struct inode *inode)
{
return fscrypt_needs_contents_encryption(inode) &&
__fscrypt_inode_uses_inline_crypto(inode);
}
/**
* fscrypt_inode_uses_fs_layer_crypto() - test whether an inode uses fs-layer
* encryption
* @inode: an inode. If encrypted, its key must be set up.
*
* Return: true if the inode requires file contents encryption and if the
* encryption should be done in the filesystem layer rather than in the
* block layer via blk-crypto.
*/
static inline bool fscrypt_inode_uses_fs_layer_crypto(const struct inode *inode)
{
return fscrypt_needs_contents_encryption(inode) &&
!__fscrypt_inode_uses_inline_crypto(inode);
}
/**
* fscrypt_has_encryption_key() - check whether an inode has had its key set up
* @inode: the inode to check
*
* Return: %true if the inode has had its encryption key set up, else %false.
*
* Usually this should be preceded by fscrypt_get_encryption_info() to try to
* set up the key first.
*/
static inline bool fscrypt_has_encryption_key(const struct inode *inode)
{
return fscrypt_get_info(inode) != NULL;
}
/** /**
* 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 * @inode: the inode we need the key for
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment