Merge 8829687a4a ("Merge tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/linux") into android-mainline
Steps on the way to 6.7-rc1 Resolves merge conflicts in: fs/crypto/fscrypt_private.h fs/crypto/inline_crypt.c Change-Id: I29532d2eca432cfaba3a93c0052539a25ec7f2ac Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -261,9 +261,9 @@ DIRECT_KEY policies
|
||||
|
||||
The Adiantum encryption mode (see `Encryption modes and usage`_) is
|
||||
suitable for both contents and filenames encryption, and it accepts
|
||||
long IVs --- long enough to hold both an 8-byte logical block number
|
||||
and a 16-byte per-file nonce. Also, the overhead of each Adiantum key
|
||||
is greater than that of an AES-256-XTS key.
|
||||
long IVs --- long enough to hold both an 8-byte data unit index and a
|
||||
16-byte per-file nonce. Also, the overhead of each Adiantum key is
|
||||
greater than that of an AES-256-XTS key.
|
||||
|
||||
Therefore, to improve performance and save memory, for Adiantum a
|
||||
"direct key" configuration is supported. When the user has enabled
|
||||
@@ -300,8 +300,8 @@ IV_INO_LBLK_32 policies
|
||||
|
||||
IV_INO_LBLK_32 policies work like IV_INO_LBLK_64, except that for
|
||||
IV_INO_LBLK_32, the inode number is hashed with SipHash-2-4 (where the
|
||||
SipHash key is derived from the master key) and added to the file
|
||||
logical block number mod 2^32 to produce a 32-bit IV.
|
||||
SipHash key is derived from the master key) and added to the file data
|
||||
unit index mod 2^32 to produce a 32-bit IV.
|
||||
|
||||
This format is optimized for use with inline encryption hardware
|
||||
compliant with the eMMC v5.2 standard, which supports only 32 IV bits
|
||||
@@ -451,31 +451,62 @@ acceleration is recommended:
|
||||
Contents encryption
|
||||
-------------------
|
||||
|
||||
For file contents, each filesystem block is encrypted independently.
|
||||
Starting from Linux kernel 5.5, encryption of filesystems with block
|
||||
size less than system's page size is supported.
|
||||
For contents encryption, each file's contents is divided into "data
|
||||
units". Each data unit is encrypted independently. The IV for each
|
||||
data unit incorporates the zero-based index of the data unit within
|
||||
the file. This ensures that each data unit within a file is encrypted
|
||||
differently, which is essential to prevent leaking information.
|
||||
|
||||
Each block's IV is set to the logical block number within the file as
|
||||
a little endian number, except that:
|
||||
Note: the encryption depending on the offset into the file means that
|
||||
operations like "collapse range" and "insert range" that rearrange the
|
||||
extent mapping of files are not supported on encrypted files.
|
||||
|
||||
- With CBC mode encryption, ESSIV is also used. Specifically, each IV
|
||||
is encrypted with AES-256 where the AES-256 key is the SHA-256 hash
|
||||
of the file's data encryption key.
|
||||
There are two cases for the sizes of the data units:
|
||||
|
||||
- With `DIRECT_KEY policies`_, the file's nonce is appended to the IV.
|
||||
Currently this is only allowed with the Adiantum encryption mode.
|
||||
* Fixed-size data units. This is how all filesystems other than UBIFS
|
||||
work. A file's data units are all the same size; the last data unit
|
||||
is zero-padded if needed. By default, the data unit size is equal
|
||||
to the filesystem block size. On some filesystems, users can select
|
||||
a sub-block data unit size via the ``log2_data_unit_size`` field of
|
||||
the encryption policy; see `FS_IOC_SET_ENCRYPTION_POLICY`_.
|
||||
|
||||
- With `IV_INO_LBLK_64 policies`_, the logical block number is limited
|
||||
to 32 bits and is placed in bits 0-31 of the IV. The inode number
|
||||
(which is also limited to 32 bits) is placed in bits 32-63.
|
||||
* Variable-size data units. This is what UBIFS does. Each "UBIFS
|
||||
data node" is treated as a crypto data unit. Each contains variable
|
||||
length, possibly compressed data, zero-padded to the next 16-byte
|
||||
boundary. Users cannot select a sub-block data unit size on UBIFS.
|
||||
|
||||
- With `IV_INO_LBLK_32 policies`_, the logical block number is limited
|
||||
to 32 bits and is placed in bits 0-31 of the IV. The inode number
|
||||
is then hashed and added mod 2^32.
|
||||
In the case of compression + encryption, the compressed data is
|
||||
encrypted. UBIFS compression works as described above. f2fs
|
||||
compression works a bit differently; it compresses a number of
|
||||
filesystem blocks into a smaller number of filesystem blocks.
|
||||
Therefore a f2fs-compressed file still uses fixed-size data units, and
|
||||
it is encrypted in a similar way to a file containing holes.
|
||||
|
||||
Note that because file logical block numbers are included in the IVs,
|
||||
filesystems must enforce that blocks are never shifted around within
|
||||
encrypted files, e.g. via "collapse range" or "insert range".
|
||||
As mentioned in `Key hierarchy`_, the default encryption setting uses
|
||||
per-file keys. In this case, the IV for each data unit is simply the
|
||||
index of the data unit in the file. However, users can select an
|
||||
encryption setting that does not use per-file keys. For these, some
|
||||
kind of file identifier is incorporated into the IVs as follows:
|
||||
|
||||
- With `DIRECT_KEY policies`_, the data unit index is placed in bits
|
||||
0-63 of the IV, and the file's nonce is placed in bits 64-191.
|
||||
|
||||
- With `IV_INO_LBLK_64 policies`_, the data unit index is placed in
|
||||
bits 0-31 of the IV, and the file's inode number is placed in bits
|
||||
32-63. This setting is only allowed when data unit indices and
|
||||
inode numbers fit in 32 bits.
|
||||
|
||||
- With `IV_INO_LBLK_32 policies`_, the file's inode number is hashed
|
||||
and added to the data unit index. The resulting value is truncated
|
||||
to 32 bits and placed in bits 0-31 of the IV. This setting is only
|
||||
allowed when data unit indices and inode numbers fit in 32 bits.
|
||||
|
||||
The byte order of the IV is always little endian.
|
||||
|
||||
If the user selects FSCRYPT_MODE_AES_128_CBC for the contents mode, an
|
||||
ESSIV layer is automatically included. In this case, before the IV is
|
||||
passed to AES-128-CBC, it is encrypted with AES-256 where the AES-256
|
||||
key is the SHA-256 hash of the file's contents encryption key.
|
||||
|
||||
Filenames encryption
|
||||
--------------------
|
||||
@@ -544,7 +575,8 @@ follows::
|
||||
__u8 contents_encryption_mode;
|
||||
__u8 filenames_encryption_mode;
|
||||
__u8 flags;
|
||||
__u8 __reserved[4];
|
||||
__u8 log2_data_unit_size;
|
||||
__u8 __reserved[3];
|
||||
__u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE];
|
||||
};
|
||||
|
||||
@@ -586,6 +618,29 @@ This structure must be initialized as follows:
|
||||
The DIRECT_KEY, IV_INO_LBLK_64, and IV_INO_LBLK_32 flags are
|
||||
mutually exclusive.
|
||||
|
||||
- ``log2_data_unit_size`` is the log2 of the data unit size in bytes,
|
||||
or 0 to select the default data unit size. The data unit size is
|
||||
the granularity of file contents encryption. For example, setting
|
||||
``log2_data_unit_size`` to 12 causes file contents be passed to the
|
||||
underlying encryption algorithm (such as AES-256-XTS) in 4096-byte
|
||||
data units, each with its own IV.
|
||||
|
||||
Not all filesystems support setting ``log2_data_unit_size``. ext4
|
||||
and f2fs support it since Linux v6.7. On filesystems that support
|
||||
it, the supported nonzero values are 9 through the log2 of the
|
||||
filesystem block size, inclusively. The default value of 0 selects
|
||||
the filesystem block size.
|
||||
|
||||
The main use case for ``log2_data_unit_size`` is for selecting a
|
||||
data unit size smaller than the filesystem block size for
|
||||
compatibility with inline encryption hardware that only supports
|
||||
smaller data unit sizes. ``/sys/block/$disk/queue/crypto/`` may be
|
||||
useful for checking which data unit sizes are supported by a
|
||||
particular system's inline encryption hardware.
|
||||
|
||||
Leave this field zeroed unless you are certain you need it. Using
|
||||
an unnecessarily small data unit size reduces performance.
|
||||
|
||||
- For v2 encryption policies, ``__reserved`` must be zeroed.
|
||||
|
||||
- For v1 encryption policies, ``master_key_descriptor`` specifies how
|
||||
@@ -1079,8 +1134,8 @@ The caller must zero all input fields, then fill in ``key_spec``:
|
||||
On success, 0 is returned and the kernel fills in the output fields:
|
||||
|
||||
- ``status`` indicates whether the key is absent, present, or
|
||||
incompletely removed. Incompletely removed means that the master
|
||||
secret has been removed, but some files are still in use; i.e.,
|
||||
incompletely removed. Incompletely removed means that removal has
|
||||
been initiated, but some files are still in use; i.e.,
|
||||
`FS_IOC_REMOVE_ENCRYPTION_KEY`_ returned 0 but set the informational
|
||||
status flag FSCRYPT_KEY_REMOVAL_STATUS_FLAG_FILES_BUSY.
|
||||
|
||||
|
||||
@@ -133,6 +133,7 @@ static const union fscrypt_policy *ceph_get_dummy_policy(struct super_block *sb)
|
||||
}
|
||||
|
||||
static struct fscrypt_operations ceph_fscrypt_ops = {
|
||||
.needs_bounce_pages = 1,
|
||||
.get_context = ceph_crypt_get_context,
|
||||
.set_context = ceph_crypt_set_context,
|
||||
.get_dummy_policy = ceph_get_dummy_policy,
|
||||
|
||||
+22
-17
@@ -111,10 +111,14 @@ out:
|
||||
int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
|
||||
sector_t pblk, unsigned int len)
|
||||
{
|
||||
const unsigned int blockbits = inode->i_blkbits;
|
||||
const unsigned int blocksize = 1 << blockbits;
|
||||
const unsigned int blocks_per_page_bits = PAGE_SHIFT - blockbits;
|
||||
const unsigned int blocks_per_page = 1 << blocks_per_page_bits;
|
||||
const struct fscrypt_inode_info *ci = inode->i_crypt_info;
|
||||
const unsigned int du_bits = ci->ci_data_unit_bits;
|
||||
const unsigned int du_size = 1U << du_bits;
|
||||
const unsigned int du_per_page_bits = PAGE_SHIFT - du_bits;
|
||||
const unsigned int du_per_page = 1U << du_per_page_bits;
|
||||
u64 du_index = (u64)lblk << (inode->i_blkbits - du_bits);
|
||||
u64 du_remaining = (u64)len << (inode->i_blkbits - du_bits);
|
||||
sector_t sector = pblk << (inode->i_blkbits - SECTOR_SHIFT);
|
||||
struct page *pages[16]; /* write up to 16 pages at a time */
|
||||
unsigned int nr_pages;
|
||||
unsigned int i;
|
||||
@@ -130,8 +134,8 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
|
||||
len);
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(pages) > BIO_MAX_VECS);
|
||||
nr_pages = min_t(unsigned int, ARRAY_SIZE(pages),
|
||||
(len + blocks_per_page - 1) >> blocks_per_page_bits);
|
||||
nr_pages = min_t(u64, ARRAY_SIZE(pages),
|
||||
(du_remaining + du_per_page - 1) >> du_per_page_bits);
|
||||
|
||||
/*
|
||||
* We need at least one page for ciphertext. Allocate the first one
|
||||
@@ -154,21 +158,22 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
|
||||
bio = bio_alloc(inode->i_sb->s_bdev, nr_pages, REQ_OP_WRITE, GFP_NOFS);
|
||||
|
||||
do {
|
||||
bio->bi_iter.bi_sector = pblk << (blockbits - 9);
|
||||
bio->bi_iter.bi_sector = sector;
|
||||
|
||||
i = 0;
|
||||
offset = 0;
|
||||
do {
|
||||
err = fscrypt_crypt_block(inode, FS_ENCRYPT, lblk,
|
||||
ZERO_PAGE(0), pages[i],
|
||||
blocksize, offset, GFP_NOFS);
|
||||
err = fscrypt_crypt_data_unit(ci, FS_ENCRYPT, du_index,
|
||||
ZERO_PAGE(0), pages[i],
|
||||
du_size, offset,
|
||||
GFP_NOFS);
|
||||
if (err)
|
||||
goto out;
|
||||
lblk++;
|
||||
pblk++;
|
||||
len--;
|
||||
offset += blocksize;
|
||||
if (offset == PAGE_SIZE || len == 0) {
|
||||
du_index++;
|
||||
sector += 1U << (du_bits - SECTOR_SHIFT);
|
||||
du_remaining--;
|
||||
offset += du_size;
|
||||
if (offset == PAGE_SIZE || du_remaining == 0) {
|
||||
ret = bio_add_page(bio, pages[i++], offset, 0);
|
||||
if (WARN_ON_ONCE(ret != offset)) {
|
||||
err = -EIO;
|
||||
@@ -176,13 +181,13 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
|
||||
}
|
||||
offset = 0;
|
||||
}
|
||||
} while (i != nr_pages && len != 0);
|
||||
} while (i != nr_pages && du_remaining != 0);
|
||||
|
||||
err = submit_bio_wait(bio);
|
||||
if (err)
|
||||
goto out;
|
||||
bio_reset(bio, inode->i_sb->s_bdev, REQ_OP_WRITE);
|
||||
} while (len != 0);
|
||||
} while (du_remaining != 0);
|
||||
err = 0;
|
||||
out:
|
||||
bio_put(bio);
|
||||
|
||||
+91
-72
@@ -39,7 +39,7 @@ static mempool_t *fscrypt_bounce_page_pool = NULL;
|
||||
static struct workqueue_struct *fscrypt_read_workqueue;
|
||||
static DEFINE_MUTEX(fscrypt_init_mutex);
|
||||
|
||||
struct kmem_cache *fscrypt_info_cachep;
|
||||
struct kmem_cache *fscrypt_inode_info_cachep;
|
||||
|
||||
void fscrypt_enqueue_decrypt_work(struct work_struct *work)
|
||||
{
|
||||
@@ -49,6 +49,13 @@ EXPORT_SYMBOL(fscrypt_enqueue_decrypt_work);
|
||||
|
||||
struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags)
|
||||
{
|
||||
if (WARN_ON_ONCE(!fscrypt_bounce_page_pool)) {
|
||||
/*
|
||||
* Oops, the filesystem called a function that uses the bounce
|
||||
* page pool, but it didn't set needs_bounce_pages.
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
return mempool_alloc(fscrypt_bounce_page_pool, gfp_flags);
|
||||
}
|
||||
|
||||
@@ -70,44 +77,44 @@ void fscrypt_free_bounce_page(struct page *bounce_page)
|
||||
EXPORT_SYMBOL(fscrypt_free_bounce_page);
|
||||
|
||||
/*
|
||||
* Generate the IV for the given logical block number within the given file.
|
||||
* For filenames encryption, lblk_num == 0.
|
||||
* Generate the IV for the given data unit index within the given file.
|
||||
* For filenames encryption, index == 0.
|
||||
*
|
||||
* Keep this in sync with fscrypt_limit_io_blocks(). fscrypt_limit_io_blocks()
|
||||
* needs to know about any IV generation methods where the low bits of IV don't
|
||||
* simply contain the lblk_num (e.g., IV_INO_LBLK_32).
|
||||
* simply contain the data unit index (e.g., IV_INO_LBLK_32).
|
||||
*/
|
||||
void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num,
|
||||
const struct fscrypt_info *ci)
|
||||
void fscrypt_generate_iv(union fscrypt_iv *iv, u64 index,
|
||||
const struct fscrypt_inode_info *ci)
|
||||
{
|
||||
u8 flags = fscrypt_policy_flags(&ci->ci_policy);
|
||||
|
||||
memset(iv, 0, ci->ci_mode->ivsize);
|
||||
|
||||
if (flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) {
|
||||
WARN_ON_ONCE(lblk_num > U32_MAX);
|
||||
WARN_ON_ONCE(index > U32_MAX);
|
||||
WARN_ON_ONCE(ci->ci_inode->i_ino > U32_MAX);
|
||||
lblk_num |= (u64)ci->ci_inode->i_ino << 32;
|
||||
index |= (u64)ci->ci_inode->i_ino << 32;
|
||||
} else if (flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) {
|
||||
WARN_ON_ONCE(lblk_num > U32_MAX);
|
||||
lblk_num = (u32)(ci->ci_hashed_ino + lblk_num);
|
||||
WARN_ON_ONCE(index > U32_MAX);
|
||||
index = (u32)(ci->ci_hashed_ino + index);
|
||||
} else if (flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) {
|
||||
memcpy(iv->nonce, ci->ci_nonce, FSCRYPT_FILE_NONCE_SIZE);
|
||||
}
|
||||
iv->lblk_num = cpu_to_le64(lblk_num);
|
||||
iv->index = cpu_to_le64(index);
|
||||
}
|
||||
|
||||
/* Encrypt or decrypt a single filesystem block of file contents */
|
||||
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)
|
||||
/* Encrypt or decrypt a single "data unit" of file contents. */
|
||||
int fscrypt_crypt_data_unit(const struct fscrypt_inode_info *ci,
|
||||
fscrypt_direction_t rw, u64 index,
|
||||
struct page *src_page, struct page *dest_page,
|
||||
unsigned int len, unsigned int offs,
|
||||
gfp_t gfp_flags)
|
||||
{
|
||||
union fscrypt_iv iv;
|
||||
struct skcipher_request *req = NULL;
|
||||
DECLARE_CRYPTO_WAIT(wait);
|
||||
struct scatterlist dst, src;
|
||||
struct fscrypt_info *ci = inode->i_crypt_info;
|
||||
struct crypto_skcipher *tfm = ci->ci_enc_key.tfm;
|
||||
int res = 0;
|
||||
|
||||
@@ -116,7 +123,7 @@ int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw,
|
||||
if (WARN_ON_ONCE(len % FSCRYPT_CONTENTS_ALIGNMENT != 0))
|
||||
return -EINVAL;
|
||||
|
||||
fscrypt_generate_iv(&iv, lblk_num, ci);
|
||||
fscrypt_generate_iv(&iv, index, ci);
|
||||
|
||||
req = skcipher_request_alloc(tfm, gfp_flags);
|
||||
if (!req)
|
||||
@@ -137,28 +144,29 @@ int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw,
|
||||
res = crypto_wait_req(crypto_skcipher_encrypt(req), &wait);
|
||||
skcipher_request_free(req);
|
||||
if (res) {
|
||||
fscrypt_err(inode, "%scryption failed for block %llu: %d",
|
||||
(rw == FS_DECRYPT ? "De" : "En"), lblk_num, res);
|
||||
fscrypt_err(ci->ci_inode,
|
||||
"%scryption failed for data unit %llu: %d",
|
||||
(rw == FS_DECRYPT ? "De" : "En"), index, res);
|
||||
return res;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @offs: Byte offset within @page of the first block to encrypt. Must be
|
||||
* a multiple of the filesystem's block size.
|
||||
* @gfp_flags: Memory allocation flags. See details below.
|
||||
* fscrypt_encrypt_pagecache_blocks() - Encrypt data from a pagecache page
|
||||
* @page: the locked pagecache page containing the data to encrypt
|
||||
* @len: size of the data to encrypt, in bytes
|
||||
* @offs: offset within @page of the data to encrypt, in bytes
|
||||
* @gfp_flags: memory allocation flags; see details below
|
||||
*
|
||||
* A new bounce page is allocated, and the specified block(s) are encrypted into
|
||||
* it. In the bounce page, the ciphertext block(s) will be located at the same
|
||||
* offsets at which the plaintext block(s) were located in the source page; any
|
||||
* other parts of the bounce page will be left uninitialized. However, normally
|
||||
* blocksize == PAGE_SIZE and the whole page is encrypted at once.
|
||||
* This allocates a new bounce page and encrypts the given data into it. The
|
||||
* length and offset of the data must be aligned to the file's crypto data unit
|
||||
* size. Alignment to the filesystem block size fulfills this requirement, as
|
||||
* the filesystem block size is always a multiple of the data unit size.
|
||||
*
|
||||
* In the bounce page, the ciphertext data will be located at the same offset at
|
||||
* which the plaintext data was located in the source page. Any other parts of
|
||||
* the bounce page will be left uninitialized.
|
||||
*
|
||||
* This is for use by the filesystem's ->writepages() method.
|
||||
*
|
||||
@@ -176,28 +184,29 @@ struct page *fscrypt_encrypt_pagecache_blocks(struct page *page,
|
||||
|
||||
{
|
||||
const struct inode *inode = page->mapping->host;
|
||||
const unsigned int blockbits = inode->i_blkbits;
|
||||
const unsigned int blocksize = 1 << blockbits;
|
||||
const struct fscrypt_inode_info *ci = inode->i_crypt_info;
|
||||
const unsigned int du_bits = ci->ci_data_unit_bits;
|
||||
const unsigned int du_size = 1U << du_bits;
|
||||
struct page *ciphertext_page;
|
||||
u64 lblk_num = ((u64)page->index << (PAGE_SHIFT - blockbits)) +
|
||||
(offs >> blockbits);
|
||||
u64 index = ((u64)page->index << (PAGE_SHIFT - du_bits)) +
|
||||
(offs >> du_bits);
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
if (WARN_ON_ONCE(!PageLocked(page)))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (WARN_ON_ONCE(len <= 0 || !IS_ALIGNED(len | offs, blocksize)))
|
||||
if (WARN_ON_ONCE(len <= 0 || !IS_ALIGNED(len | offs, du_size)))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
ciphertext_page = fscrypt_alloc_bounce_page(gfp_flags);
|
||||
if (!ciphertext_page)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
for (i = offs; i < offs + len; i += blocksize, lblk_num++) {
|
||||
err = fscrypt_crypt_block(inode, FS_ENCRYPT, lblk_num,
|
||||
page, ciphertext_page,
|
||||
blocksize, i, gfp_flags);
|
||||
for (i = offs; i < offs + len; i += du_size, index++) {
|
||||
err = fscrypt_crypt_data_unit(ci, FS_ENCRYPT, index,
|
||||
page, ciphertext_page,
|
||||
du_size, i, gfp_flags);
|
||||
if (err) {
|
||||
fscrypt_free_bounce_page(ciphertext_page);
|
||||
return ERR_PTR(err);
|
||||
@@ -224,30 +233,33 @@ EXPORT_SYMBOL(fscrypt_encrypt_pagecache_blocks);
|
||||
* arbitrary page, not necessarily in the original pagecache page. The @inode
|
||||
* and @lblk_num must be specified, as they can't be determined from @page.
|
||||
*
|
||||
* This is not compatible with fscrypt_operations::supports_subblock_data_units.
|
||||
*
|
||||
* Return: 0 on success; -errno on failure
|
||||
*/
|
||||
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)
|
||||
{
|
||||
return fscrypt_crypt_block(inode, FS_ENCRYPT, lblk_num, page, page,
|
||||
len, offs, gfp_flags);
|
||||
if (WARN_ON_ONCE(inode->i_sb->s_cop->supports_subblock_data_units))
|
||||
return -EOPNOTSUPP;
|
||||
return fscrypt_crypt_data_unit(inode->i_crypt_info, FS_ENCRYPT,
|
||||
lblk_num, page, page, len, offs,
|
||||
gfp_flags);
|
||||
}
|
||||
EXPORT_SYMBOL(fscrypt_encrypt_block_inplace);
|
||||
|
||||
/**
|
||||
* fscrypt_decrypt_pagecache_blocks() - Decrypt filesystem blocks in a
|
||||
* pagecache folio
|
||||
* @folio: The locked pagecache folio 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.
|
||||
* @offs: Byte offset within @folio of the first block to decrypt. Must be
|
||||
* a multiple of the filesystem's block size.
|
||||
* fscrypt_decrypt_pagecache_blocks() - Decrypt data from a pagecache folio
|
||||
* @folio: the pagecache folio containing the data to decrypt
|
||||
* @len: size of the data to decrypt, in bytes
|
||||
* @offs: offset within @folio of the data to decrypt, in bytes
|
||||
*
|
||||
* The specified block(s) are decrypted in-place within the pagecache folio,
|
||||
* which must still be locked and not uptodate.
|
||||
*
|
||||
* This is for use by the filesystem's ->readahead() method.
|
||||
* Decrypt data that has just been read from an encrypted file. The data must
|
||||
* be located in a pagecache folio that is still locked and not yet uptodate.
|
||||
* The length and offset of the data must be aligned to the file's crypto data
|
||||
* unit size. Alignment to the filesystem block size fulfills this requirement,
|
||||
* as the filesystem block size is always a multiple of the data unit size.
|
||||
*
|
||||
* Return: 0 on success; -errno on failure
|
||||
*/
|
||||
@@ -255,25 +267,26 @@ int fscrypt_decrypt_pagecache_blocks(struct folio *folio, size_t len,
|
||||
size_t offs)
|
||||
{
|
||||
const struct inode *inode = folio->mapping->host;
|
||||
const unsigned int blockbits = inode->i_blkbits;
|
||||
const unsigned int blocksize = 1 << blockbits;
|
||||
u64 lblk_num = ((u64)folio->index << (PAGE_SHIFT - blockbits)) +
|
||||
(offs >> blockbits);
|
||||
const struct fscrypt_inode_info *ci = inode->i_crypt_info;
|
||||
const unsigned int du_bits = ci->ci_data_unit_bits;
|
||||
const unsigned int du_size = 1U << du_bits;
|
||||
u64 index = ((u64)folio->index << (PAGE_SHIFT - du_bits)) +
|
||||
(offs >> du_bits);
|
||||
size_t i;
|
||||
int err;
|
||||
|
||||
if (WARN_ON_ONCE(!folio_test_locked(folio)))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON_ONCE(len <= 0 || !IS_ALIGNED(len | offs, blocksize)))
|
||||
if (WARN_ON_ONCE(len <= 0 || !IS_ALIGNED(len | offs, du_size)))
|
||||
return -EINVAL;
|
||||
|
||||
for (i = offs; i < offs + len; i += blocksize, lblk_num++) {
|
||||
for (i = offs; i < offs + len; i += du_size, index++) {
|
||||
struct page *page = folio_page(folio, i >> PAGE_SHIFT);
|
||||
|
||||
err = fscrypt_crypt_block(inode, FS_DECRYPT, lblk_num, page,
|
||||
page, blocksize, i & ~PAGE_MASK,
|
||||
GFP_NOFS);
|
||||
err = fscrypt_crypt_data_unit(ci, FS_DECRYPT, index, page,
|
||||
page, du_size, i & ~PAGE_MASK,
|
||||
GFP_NOFS);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@@ -295,14 +308,19 @@ EXPORT_SYMBOL(fscrypt_decrypt_pagecache_blocks);
|
||||
* arbitrary page, not necessarily in the original pagecache page. The @inode
|
||||
* and @lblk_num must be specified, as they can't be determined from @page.
|
||||
*
|
||||
* This is not compatible with fscrypt_operations::supports_subblock_data_units.
|
||||
*
|
||||
* Return: 0 on success; -errno on failure
|
||||
*/
|
||||
int fscrypt_decrypt_block_inplace(const struct inode *inode, struct page *page,
|
||||
unsigned int len, unsigned int offs,
|
||||
u64 lblk_num)
|
||||
{
|
||||
return fscrypt_crypt_block(inode, FS_DECRYPT, lblk_num, page, page,
|
||||
len, offs, GFP_NOFS);
|
||||
if (WARN_ON_ONCE(inode->i_sb->s_cop->supports_subblock_data_units))
|
||||
return -EOPNOTSUPP;
|
||||
return fscrypt_crypt_data_unit(inode->i_crypt_info, FS_DECRYPT,
|
||||
lblk_num, page, page, len, offs,
|
||||
GFP_NOFS);
|
||||
}
|
||||
EXPORT_SYMBOL(fscrypt_decrypt_block_inplace);
|
||||
|
||||
@@ -325,7 +343,7 @@ int fscrypt_initialize(struct super_block *sb)
|
||||
return 0;
|
||||
|
||||
/* No need to allocate a bounce page pool if this FS won't use it. */
|
||||
if (sb->s_cop->flags & FS_CFLG_OWN_PAGES)
|
||||
if (!sb->s_cop->needs_bounce_pages)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&fscrypt_init_mutex);
|
||||
@@ -391,18 +409,19 @@ static int __init fscrypt_init(void)
|
||||
if (!fscrypt_read_workqueue)
|
||||
goto fail;
|
||||
|
||||
fscrypt_info_cachep = KMEM_CACHE(fscrypt_info, SLAB_RECLAIM_ACCOUNT);
|
||||
if (!fscrypt_info_cachep)
|
||||
fscrypt_inode_info_cachep = KMEM_CACHE(fscrypt_inode_info,
|
||||
SLAB_RECLAIM_ACCOUNT);
|
||||
if (!fscrypt_inode_info_cachep)
|
||||
goto fail_free_queue;
|
||||
|
||||
err = fscrypt_init_keyring();
|
||||
if (err)
|
||||
goto fail_free_info;
|
||||
goto fail_free_inode_info;
|
||||
|
||||
return 0;
|
||||
|
||||
fail_free_info:
|
||||
kmem_cache_destroy(fscrypt_info_cachep);
|
||||
fail_free_inode_info:
|
||||
kmem_cache_destroy(fscrypt_inode_info_cachep);
|
||||
fail_free_queue:
|
||||
destroy_workqueue(fscrypt_read_workqueue);
|
||||
fail:
|
||||
|
||||
+3
-3
@@ -100,7 +100,7 @@ int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
|
||||
{
|
||||
struct skcipher_request *req = NULL;
|
||||
DECLARE_CRYPTO_WAIT(wait);
|
||||
const struct fscrypt_info *ci = inode->i_crypt_info;
|
||||
const struct fscrypt_inode_info *ci = inode->i_crypt_info;
|
||||
struct crypto_skcipher *tfm = ci->ci_enc_key.tfm;
|
||||
union fscrypt_iv iv;
|
||||
struct scatterlist sg;
|
||||
@@ -157,7 +157,7 @@ static int fname_decrypt(const struct inode *inode,
|
||||
struct skcipher_request *req = NULL;
|
||||
DECLARE_CRYPTO_WAIT(wait);
|
||||
struct scatterlist src_sg, dst_sg;
|
||||
const struct fscrypt_info *ci = inode->i_crypt_info;
|
||||
const struct fscrypt_inode_info *ci = inode->i_crypt_info;
|
||||
struct crypto_skcipher *tfm = ci->ci_enc_key.tfm;
|
||||
union fscrypt_iv iv;
|
||||
int res;
|
||||
@@ -568,7 +568,7 @@ EXPORT_SYMBOL_GPL(fscrypt_match_name);
|
||||
*/
|
||||
u64 fscrypt_fname_siphash(const struct inode *dir, const struct qstr *name)
|
||||
{
|
||||
const struct fscrypt_info *ci = dir->i_crypt_info;
|
||||
const struct fscrypt_inode_info *ci = dir->i_crypt_info;
|
||||
|
||||
WARN_ON_ONCE(!ci->ci_dirhash_key_initialized);
|
||||
|
||||
|
||||
+109
-55
@@ -68,7 +68,8 @@ struct fscrypt_context_v2 {
|
||||
u8 contents_encryption_mode;
|
||||
u8 filenames_encryption_mode;
|
||||
u8 flags;
|
||||
u8 __reserved[4];
|
||||
u8 log2_data_unit_size;
|
||||
u8 __reserved[3];
|
||||
u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE];
|
||||
u8 nonce[FSCRYPT_FILE_NONCE_SIZE];
|
||||
};
|
||||
@@ -186,6 +187,26 @@ fscrypt_policy_flags(const union fscrypt_policy *policy)
|
||||
BUG();
|
||||
}
|
||||
|
||||
static inline int
|
||||
fscrypt_policy_v2_du_bits(const struct fscrypt_policy_v2 *policy,
|
||||
const struct inode *inode)
|
||||
{
|
||||
return policy->log2_data_unit_size ?: inode->i_blkbits;
|
||||
}
|
||||
|
||||
static inline int
|
||||
fscrypt_policy_du_bits(const union fscrypt_policy *policy,
|
||||
const struct inode *inode)
|
||||
{
|
||||
switch (policy->version) {
|
||||
case FSCRYPT_POLICY_V1:
|
||||
return inode->i_blkbits;
|
||||
case FSCRYPT_POLICY_V2:
|
||||
return fscrypt_policy_v2_du_bits(&policy->v2, inode);
|
||||
}
|
||||
BUG();
|
||||
}
|
||||
|
||||
/*
|
||||
* For encrypted symlinks, the ciphertext length is stored at the beginning
|
||||
* of the string in little-endian format.
|
||||
@@ -210,18 +231,18 @@ struct fscrypt_prepared_key {
|
||||
};
|
||||
|
||||
/*
|
||||
* fscrypt_info - the "encryption key" for an inode
|
||||
* fscrypt_inode_info - the "encryption key" for an inode
|
||||
*
|
||||
* When an encrypted file's key is made available, an instance of this struct is
|
||||
* allocated and stored in ->i_crypt_info. Once created, it remains until the
|
||||
* inode is evicted.
|
||||
*/
|
||||
struct fscrypt_info {
|
||||
struct fscrypt_inode_info {
|
||||
|
||||
/* The key in a form prepared for actual encryption/decryption */
|
||||
struct fscrypt_prepared_key ci_enc_key;
|
||||
|
||||
/* True if ci_enc_key should be freed when this fscrypt_info is freed */
|
||||
/* True if ci_enc_key should be freed when this struct is freed */
|
||||
bool ci_owns_key;
|
||||
|
||||
#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
|
||||
@@ -232,6 +253,16 @@ struct fscrypt_info {
|
||||
bool ci_inlinecrypt;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* log2 of the data unit size (granularity of contents encryption) of
|
||||
* this file. This is computable from ci_policy and ci_inode but is
|
||||
* cached here for efficiency. Only used for regular files.
|
||||
*/
|
||||
u8 ci_data_unit_bits;
|
||||
|
||||
/* Cached value: log2 of number of data units per FS block */
|
||||
u8 ci_data_units_per_block_bits;
|
||||
|
||||
/*
|
||||
* Encryption mode used for this inode. It corresponds to either the
|
||||
* contents or filenames encryption mode, depending on the inode type.
|
||||
@@ -284,12 +315,13 @@ typedef enum {
|
||||
} fscrypt_direction_t;
|
||||
|
||||
/* crypto.c */
|
||||
extern struct kmem_cache *fscrypt_info_cachep;
|
||||
extern struct kmem_cache *fscrypt_inode_info_cachep;
|
||||
int fscrypt_initialize(struct super_block *sb);
|
||||
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);
|
||||
int fscrypt_crypt_data_unit(const struct fscrypt_inode_info *ci,
|
||||
fscrypt_direction_t rw, u64 index,
|
||||
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);
|
||||
|
||||
void __printf(3, 4) __cold
|
||||
@@ -304,8 +336,8 @@ fscrypt_msg(const struct inode *inode, const char *level, const char *fmt, ...);
|
||||
|
||||
union fscrypt_iv {
|
||||
struct {
|
||||
/* logical block number within the file */
|
||||
__le64 lblk_num;
|
||||
/* zero-based index of data unit within the file */
|
||||
__le64 index;
|
||||
|
||||
/* per-file nonce; only set in DIRECT_KEY mode */
|
||||
u8 nonce[FSCRYPT_FILE_NONCE_SIZE];
|
||||
@@ -314,8 +346,18 @@ union fscrypt_iv {
|
||||
__le64 dun[FSCRYPT_MAX_IV_SIZE / sizeof(__le64)];
|
||||
};
|
||||
|
||||
void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num,
|
||||
const struct fscrypt_info *ci);
|
||||
void fscrypt_generate_iv(union fscrypt_iv *iv, u64 index,
|
||||
const struct fscrypt_inode_info *ci);
|
||||
|
||||
/*
|
||||
* Return the number of bits used by the maximum file data unit index that is
|
||||
* possible on the given filesystem, using the given log2 data unit size.
|
||||
*/
|
||||
static inline int
|
||||
fscrypt_max_file_dun_bits(const struct super_block *sb, int du_bits)
|
||||
{
|
||||
return fls64(sb->s_maxbytes - 1) - du_bits;
|
||||
}
|
||||
|
||||
/* fname.c */
|
||||
bool __fscrypt_fname_encrypted_size(const union fscrypt_policy *policy,
|
||||
@@ -353,11 +395,11 @@ 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,
|
||||
int fscrypt_select_encryption_impl(struct fscrypt_inode_info *ci,
|
||||
bool is_hw_wrapped_key);
|
||||
|
||||
static inline bool
|
||||
fscrypt_using_inline_encryption(const struct fscrypt_info *ci)
|
||||
fscrypt_using_inline_encryption(const struct fscrypt_inode_info *ci)
|
||||
{
|
||||
return ci->ci_inlinecrypt;
|
||||
}
|
||||
@@ -365,7 +407,7 @@ fscrypt_using_inline_encryption(const struct fscrypt_info *ci)
|
||||
int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
|
||||
const u8 *raw_key, size_t raw_key_size,
|
||||
bool is_hw_wrapped,
|
||||
const struct fscrypt_info *ci);
|
||||
const struct fscrypt_inode_info *ci);
|
||||
|
||||
void fscrypt_destroy_inline_crypt_key(struct super_block *sb,
|
||||
struct fscrypt_prepared_key *prep_key);
|
||||
@@ -380,7 +422,7 @@ int fscrypt_derive_sw_secret(struct super_block *sb,
|
||||
*/
|
||||
static inline bool
|
||||
fscrypt_is_key_prepared(struct fscrypt_prepared_key *prep_key,
|
||||
const struct fscrypt_info *ci)
|
||||
const struct fscrypt_inode_info *ci)
|
||||
{
|
||||
/*
|
||||
* The two smp_load_acquire()'s here pair with the smp_store_release()'s
|
||||
@@ -397,14 +439,14 @@ fscrypt_is_key_prepared(struct fscrypt_prepared_key *prep_key,
|
||||
|
||||
#else /* CONFIG_FS_ENCRYPTION_INLINE_CRYPT */
|
||||
|
||||
static inline int fscrypt_select_encryption_impl(struct fscrypt_info *ci,
|
||||
static inline int fscrypt_select_encryption_impl(struct fscrypt_inode_info *ci,
|
||||
bool is_hw_wrapped_key)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
fscrypt_using_inline_encryption(const struct fscrypt_info *ci)
|
||||
fscrypt_using_inline_encryption(const struct fscrypt_inode_info *ci)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -413,7 +455,7 @@ static inline int
|
||||
fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
|
||||
const u8 *raw_key, size_t raw_key_size,
|
||||
bool is_hw_wrapped,
|
||||
const struct fscrypt_info *ci)
|
||||
const struct fscrypt_inode_info *ci)
|
||||
{
|
||||
WARN_ON_ONCE(1);
|
||||
return -EOPNOTSUPP;
|
||||
@@ -436,7 +478,7 @@ fscrypt_derive_sw_secret(struct super_block *sb,
|
||||
|
||||
static inline bool
|
||||
fscrypt_is_key_prepared(struct fscrypt_prepared_key *prep_key,
|
||||
const struct fscrypt_info *ci)
|
||||
const struct fscrypt_inode_info *ci)
|
||||
{
|
||||
return smp_load_acquire(&prep_key->tfm) != NULL;
|
||||
}
|
||||
@@ -489,8 +531,28 @@ struct fscrypt_master_key_secret {
|
||||
* fscrypt_master_key - an in-use master key
|
||||
*
|
||||
* This represents a master encryption key which has been added to the
|
||||
* filesystem and can be used to "unlock" the encrypted files which were
|
||||
* encrypted with it.
|
||||
* filesystem. There are three high-level states that a key can be in:
|
||||
*
|
||||
* FSCRYPT_KEY_STATUS_PRESENT
|
||||
* Key is fully usable; it can be used to unlock inodes that are encrypted
|
||||
* with it (this includes being able to create new inodes). ->mk_present
|
||||
* indicates whether the key is in this state. ->mk_secret exists, the key
|
||||
* is in the keyring, and ->mk_active_refs > 0 due to ->mk_present.
|
||||
*
|
||||
* FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED
|
||||
* Removal of this key has been initiated, but some inodes that were
|
||||
* unlocked with it are still in-use. Like ABSENT, ->mk_secret is wiped,
|
||||
* and the key can no longer be used to unlock inodes. Unlike ABSENT, the
|
||||
* key is still in the keyring; ->mk_decrypted_inodes is nonempty; and
|
||||
* ->mk_active_refs > 0, being equal to the size of ->mk_decrypted_inodes.
|
||||
*
|
||||
* This state transitions to ABSENT if ->mk_decrypted_inodes becomes empty,
|
||||
* or to PRESENT if FS_IOC_ADD_ENCRYPTION_KEY is called again for this key.
|
||||
*
|
||||
* FSCRYPT_KEY_STATUS_ABSENT
|
||||
* Key is fully removed. The key is no longer in the keyring,
|
||||
* ->mk_decrypted_inodes is empty, ->mk_active_refs == 0, ->mk_secret is
|
||||
* wiped, and the key can no longer be used to unlock inodes.
|
||||
*/
|
||||
struct fscrypt_master_key {
|
||||
|
||||
@@ -500,7 +562,7 @@ struct fscrypt_master_key {
|
||||
*/
|
||||
struct hlist_node mk_node;
|
||||
|
||||
/* Semaphore that protects ->mk_secret and ->mk_users */
|
||||
/* Semaphore that protects ->mk_secret, ->mk_users, and ->mk_present */
|
||||
struct rw_semaphore mk_sem;
|
||||
|
||||
/*
|
||||
@@ -510,8 +572,8 @@ struct fscrypt_master_key {
|
||||
* ->mk_direct_keys) that have been prepared continue to exist.
|
||||
* A structural ref only guarantees that the struct continues to exist.
|
||||
*
|
||||
* There is one active ref associated with ->mk_secret being present,
|
||||
* and one active ref for each inode in ->mk_decrypted_inodes.
|
||||
* There is one active ref associated with ->mk_present being true, and
|
||||
* one active ref for each inode in ->mk_decrypted_inodes.
|
||||
*
|
||||
* There is one structural ref associated with the active refcount being
|
||||
* nonzero. Finding a key in the keyring also takes a structural ref,
|
||||
@@ -523,17 +585,10 @@ struct fscrypt_master_key {
|
||||
struct rcu_head mk_rcu_head;
|
||||
|
||||
/*
|
||||
* The secret key material. After FS_IOC_REMOVE_ENCRYPTION_KEY is
|
||||
* executed, this is wiped and no new inodes can be unlocked with this
|
||||
* key; however, there may still be inodes in ->mk_decrypted_inodes
|
||||
* which could not be evicted. As long as some inodes still remain,
|
||||
* FS_IOC_REMOVE_ENCRYPTION_KEY can be retried, or
|
||||
* FS_IOC_ADD_ENCRYPTION_KEY can add the secret again.
|
||||
* The secret key material. Wiped as soon as it is no longer needed;
|
||||
* for details, see the fscrypt_master_key struct comment.
|
||||
*
|
||||
* While ->mk_secret is present, one ref in ->mk_active_refs is held.
|
||||
*
|
||||
* Locking: protected by ->mk_sem. The manipulation of ->mk_active_refs
|
||||
* associated with this field is protected by ->mk_sem as well.
|
||||
* Locking: protected by ->mk_sem.
|
||||
*/
|
||||
struct fscrypt_master_key_secret mk_secret;
|
||||
|
||||
@@ -556,7 +611,7 @@ struct fscrypt_master_key {
|
||||
*
|
||||
* Locking: protected by ->mk_sem. (We don't just rely on the keyrings
|
||||
* subsystem semaphore ->mk_users->sem, as we need support for atomic
|
||||
* search+insert along with proper synchronization with ->mk_secret.)
|
||||
* search+insert along with proper synchronization with other fields.)
|
||||
*/
|
||||
struct key *mk_users;
|
||||
|
||||
@@ -579,20 +634,17 @@ struct fscrypt_master_key {
|
||||
siphash_key_t mk_ino_hash_key;
|
||||
bool mk_ino_hash_key_initialized;
|
||||
|
||||
} __randomize_layout;
|
||||
|
||||
static inline bool
|
||||
is_master_key_secret_present(const struct fscrypt_master_key_secret *secret)
|
||||
{
|
||||
/*
|
||||
* The READ_ONCE() is only necessary for fscrypt_drop_inode().
|
||||
* fscrypt_drop_inode() runs in atomic context, so it can't take the key
|
||||
* semaphore and thus 'secret' can change concurrently which would be a
|
||||
* data race. But fscrypt_drop_inode() only need to know whether the
|
||||
* secret *was* present at the time of check, so READ_ONCE() suffices.
|
||||
* Whether this key is in the "present" state, i.e. fully usable. For
|
||||
* details, see the fscrypt_master_key struct comment.
|
||||
*
|
||||
* Locking: protected by ->mk_sem, but can be read locklessly using
|
||||
* READ_ONCE(). Writers must use WRITE_ONCE() when concurrent readers
|
||||
* are possible.
|
||||
*/
|
||||
return READ_ONCE(secret->size) != 0;
|
||||
}
|
||||
bool mk_present;
|
||||
|
||||
} __randomize_layout;
|
||||
|
||||
static inline const char *master_key_spec_type(
|
||||
const struct fscrypt_key_specifier *spec)
|
||||
@@ -654,17 +706,18 @@ struct fscrypt_mode {
|
||||
extern struct fscrypt_mode fscrypt_modes[];
|
||||
|
||||
int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key,
|
||||
const u8 *raw_key, const struct fscrypt_info *ci);
|
||||
const u8 *raw_key, const struct fscrypt_inode_info *ci);
|
||||
|
||||
void fscrypt_destroy_prepared_key(struct super_block *sb,
|
||||
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_inode_info *ci,
|
||||
const u8 *raw_key);
|
||||
|
||||
int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
|
||||
int fscrypt_derive_dirhash_key(struct fscrypt_inode_info *ci,
|
||||
const struct fscrypt_master_key *mk);
|
||||
|
||||
void fscrypt_hash_inode_number(struct fscrypt_info *ci,
|
||||
void fscrypt_hash_inode_number(struct fscrypt_inode_info *ci,
|
||||
const struct fscrypt_master_key *mk);
|
||||
|
||||
int fscrypt_get_encryption_info(struct inode *inode, bool allow_unsupported);
|
||||
@@ -699,10 +752,11 @@ static inline int fscrypt_require_key(struct inode *inode)
|
||||
|
||||
void fscrypt_put_direct_key(struct fscrypt_direct_key *dk);
|
||||
|
||||
int fscrypt_setup_v1_file_key(struct fscrypt_info *ci,
|
||||
int fscrypt_setup_v1_file_key(struct fscrypt_inode_info *ci,
|
||||
const u8 *raw_master_key);
|
||||
|
||||
int fscrypt_setup_v1_file_key_via_subscribed_keyrings(struct fscrypt_info *ci);
|
||||
int fscrypt_setup_v1_file_key_via_subscribed_keyrings(
|
||||
struct fscrypt_inode_info *ci);
|
||||
|
||||
/* policy.c */
|
||||
|
||||
|
||||
+2
-2
@@ -169,7 +169,7 @@ EXPORT_SYMBOL_GPL(__fscrypt_prepare_setattr);
|
||||
int fscrypt_prepare_setflags(struct inode *inode,
|
||||
unsigned int oldflags, unsigned int flags)
|
||||
{
|
||||
struct fscrypt_info *ci;
|
||||
struct fscrypt_inode_info *ci;
|
||||
struct fscrypt_master_key *mk;
|
||||
int err;
|
||||
|
||||
@@ -187,7 +187,7 @@ int fscrypt_prepare_setflags(struct inode *inode,
|
||||
return -EINVAL;
|
||||
mk = ci->ci_master_key;
|
||||
down_read(&mk->mk_sem);
|
||||
if (is_master_key_secret_present(&mk->mk_secret))
|
||||
if (mk->mk_present)
|
||||
err = fscrypt_derive_dirhash_key(ci, mk);
|
||||
else
|
||||
err = -ENOKEY;
|
||||
|
||||
+16
-15
@@ -39,11 +39,11 @@ static struct block_device **fscrypt_get_devices(struct super_block *sb,
|
||||
return devs;
|
||||
}
|
||||
|
||||
static unsigned int fscrypt_get_dun_bytes(const struct fscrypt_info *ci)
|
||||
static unsigned int fscrypt_get_dun_bytes(const struct fscrypt_inode_info *ci)
|
||||
{
|
||||
struct super_block *sb = ci->ci_inode->i_sb;
|
||||
const struct super_block *sb = ci->ci_inode->i_sb;
|
||||
unsigned int flags = fscrypt_policy_flags(&ci->ci_policy);
|
||||
int ino_bits = 64, lblk_bits = 64;
|
||||
int dun_bits;
|
||||
|
||||
if (flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY)
|
||||
return offsetofend(union fscrypt_iv, nonce);
|
||||
@@ -54,10 +54,9 @@ static unsigned int fscrypt_get_dun_bytes(const struct fscrypt_info *ci)
|
||||
if (flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)
|
||||
return sizeof(__le32);
|
||||
|
||||
/* Default case: IVs are just the file logical block number */
|
||||
if (sb->s_cop->get_ino_and_lblk_bits)
|
||||
sb->s_cop->get_ino_and_lblk_bits(sb, &ino_bits, &lblk_bits);
|
||||
return DIV_ROUND_UP(lblk_bits, 8);
|
||||
/* Default case: IVs are just the file data unit index */
|
||||
dun_bits = fscrypt_max_file_dun_bits(sb, ci->ci_data_unit_bits);
|
||||
return DIV_ROUND_UP(dun_bits, 8);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -90,7 +89,7 @@ static void fscrypt_log_blk_crypto_impl(struct fscrypt_mode *mode,
|
||||
}
|
||||
|
||||
/* Enable inline encryption for this file if supported. */
|
||||
int fscrypt_select_encryption_impl(struct fscrypt_info *ci,
|
||||
int fscrypt_select_encryption_impl(struct fscrypt_inode_info *ci,
|
||||
bool is_hw_wrapped_key)
|
||||
{
|
||||
const struct inode *inode = ci->ci_inode;
|
||||
@@ -130,7 +129,7 @@ int fscrypt_select_encryption_impl(struct fscrypt_info *ci,
|
||||
* crypto configuration that the file would use.
|
||||
*/
|
||||
crypto_cfg.crypto_mode = ci->ci_mode->blk_crypto_mode;
|
||||
crypto_cfg.data_unit_size = sb->s_blocksize;
|
||||
crypto_cfg.data_unit_size = 1U << ci->ci_data_unit_bits;
|
||||
crypto_cfg.dun_bytes = fscrypt_get_dun_bytes(ci);
|
||||
crypto_cfg.key_type =
|
||||
is_hw_wrapped_key ? BLK_CRYPTO_KEY_TYPE_HW_WRAPPED :
|
||||
@@ -157,7 +156,7 @@ out_free_devs:
|
||||
int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
|
||||
const u8 *raw_key, size_t raw_key_size,
|
||||
bool is_hw_wrapped,
|
||||
const struct fscrypt_info *ci)
|
||||
const struct fscrypt_inode_info *ci)
|
||||
{
|
||||
const struct inode *inode = ci->ci_inode;
|
||||
struct super_block *sb = inode->i_sb;
|
||||
@@ -176,7 +175,7 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
|
||||
|
||||
err = blk_crypto_init_key(blk_key, raw_key, raw_key_size, key_type,
|
||||
crypto_mode, fscrypt_get_dun_bytes(ci),
|
||||
sb->s_blocksize);
|
||||
1U << ci->ci_data_unit_bits);
|
||||
if (err) {
|
||||
fscrypt_err(inode, "error %d initializing blk-crypto key", err);
|
||||
goto fail;
|
||||
@@ -268,13 +267,15 @@ bool __fscrypt_inode_uses_inline_crypto(const struct inode *inode)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__fscrypt_inode_uses_inline_crypto);
|
||||
|
||||
static void fscrypt_generate_dun(const struct fscrypt_info *ci, u64 lblk_num,
|
||||
static void fscrypt_generate_dun(const struct fscrypt_inode_info *ci,
|
||||
u64 lblk_num,
|
||||
u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE])
|
||||
{
|
||||
u64 index = lblk_num << ci->ci_data_units_per_block_bits;
|
||||
union fscrypt_iv iv;
|
||||
int i;
|
||||
|
||||
fscrypt_generate_iv(&iv, lblk_num, ci);
|
||||
fscrypt_generate_iv(&iv, index, ci);
|
||||
|
||||
BUILD_BUG_ON(FSCRYPT_MAX_IV_SIZE > BLK_CRYPTO_MAX_IV_SIZE);
|
||||
memset(dun, 0, BLK_CRYPTO_MAX_IV_SIZE);
|
||||
@@ -303,7 +304,7 @@ static void fscrypt_generate_dun(const struct fscrypt_info *ci, u64 lblk_num,
|
||||
void fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode,
|
||||
u64 first_lblk, gfp_t gfp_mask)
|
||||
{
|
||||
const struct fscrypt_info *ci;
|
||||
const struct fscrypt_inode_info *ci;
|
||||
u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE];
|
||||
|
||||
if (fscrypt_inode_should_skip_dm_default_key(inode))
|
||||
@@ -504,7 +505,7 @@ EXPORT_SYMBOL_GPL(fscrypt_dio_supported);
|
||||
*/
|
||||
u64 fscrypt_limit_io_blocks(const struct inode *inode, u64 lblk, u64 nr_blocks)
|
||||
{
|
||||
const struct fscrypt_info *ci;
|
||||
const struct fscrypt_inode_info *ci;
|
||||
u32 dun;
|
||||
|
||||
if (!fscrypt_inode_uses_inline_crypto(inode))
|
||||
|
||||
+49
-33
@@ -99,10 +99,10 @@ void fscrypt_put_master_key_activeref(struct super_block *sb,
|
||||
spin_unlock(&sb->s_master_keys->lock);
|
||||
|
||||
/*
|
||||
* ->mk_active_refs == 0 implies that ->mk_secret is not present and
|
||||
* that ->mk_decrypted_inodes is empty.
|
||||
* ->mk_active_refs == 0 implies that ->mk_present is false and
|
||||
* ->mk_decrypted_inodes is empty.
|
||||
*/
|
||||
WARN_ON_ONCE(is_master_key_secret_present(&mk->mk_secret));
|
||||
WARN_ON_ONCE(mk->mk_present);
|
||||
WARN_ON_ONCE(!list_empty(&mk->mk_decrypted_inodes));
|
||||
|
||||
for (i = 0; i <= FSCRYPT_MODE_MAX; i++) {
|
||||
@@ -121,6 +121,18 @@ void fscrypt_put_master_key_activeref(struct super_block *sb,
|
||||
fscrypt_put_master_key(mk);
|
||||
}
|
||||
|
||||
/*
|
||||
* This transitions the key state from present to incompletely removed, and then
|
||||
* potentially to absent (depending on whether inodes remain).
|
||||
*/
|
||||
static void fscrypt_initiate_key_removal(struct super_block *sb,
|
||||
struct fscrypt_master_key *mk)
|
||||
{
|
||||
WRITE_ONCE(mk->mk_present, false);
|
||||
wipe_master_key_secret(&mk->mk_secret);
|
||||
fscrypt_put_master_key_activeref(sb, mk);
|
||||
}
|
||||
|
||||
static inline bool valid_key_spec(const struct fscrypt_key_specifier *spec)
|
||||
{
|
||||
if (spec->__reserved)
|
||||
@@ -234,14 +246,13 @@ void fscrypt_destroy_keyring(struct super_block *sb)
|
||||
* evicted, every key remaining in the keyring should
|
||||
* have an empty inode list, and should only still be in
|
||||
* the keyring due to the single active ref associated
|
||||
* with ->mk_secret. There should be no structural refs
|
||||
* beyond the one associated with the active ref.
|
||||
* with ->mk_present. There should be no structural
|
||||
* refs beyond the one associated with the active ref.
|
||||
*/
|
||||
WARN_ON_ONCE(refcount_read(&mk->mk_active_refs) != 1);
|
||||
WARN_ON_ONCE(refcount_read(&mk->mk_struct_refs) != 1);
|
||||
WARN_ON_ONCE(!is_master_key_secret_present(&mk->mk_secret));
|
||||
wipe_master_key_secret(&mk->mk_secret);
|
||||
fscrypt_put_master_key_activeref(sb, mk);
|
||||
WARN_ON_ONCE(!mk->mk_present);
|
||||
fscrypt_initiate_key_removal(sb, mk);
|
||||
}
|
||||
}
|
||||
kfree_sensitive(keyring);
|
||||
@@ -439,7 +450,8 @@ static int add_new_master_key(struct super_block *sb,
|
||||
}
|
||||
|
||||
move_master_key_secret(&mk->mk_secret, secret);
|
||||
refcount_set(&mk->mk_active_refs, 1); /* ->mk_secret is present */
|
||||
mk->mk_present = true;
|
||||
refcount_set(&mk->mk_active_refs, 1); /* ->mk_present is true */
|
||||
|
||||
spin_lock(&keyring->lock);
|
||||
hlist_add_head_rcu(&mk->mk_node,
|
||||
@@ -478,11 +490,18 @@ static int add_existing_master_key(struct fscrypt_master_key *mk,
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Re-add the secret if needed. */
|
||||
if (!is_master_key_secret_present(&mk->mk_secret)) {
|
||||
if (!refcount_inc_not_zero(&mk->mk_active_refs))
|
||||
/* If the key is incompletely removed, make it present again. */
|
||||
if (!mk->mk_present) {
|
||||
if (!refcount_inc_not_zero(&mk->mk_active_refs)) {
|
||||
/*
|
||||
* Raced with the last active ref being dropped, so the
|
||||
* key has become, or is about to become, "absent".
|
||||
* Therefore, we need to allocate a new key struct.
|
||||
*/
|
||||
return KEY_DEAD;
|
||||
}
|
||||
move_master_key_secret(&mk->mk_secret, secret);
|
||||
WRITE_ONCE(mk->mk_present, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -506,8 +525,8 @@ static int do_add_master_key(struct super_block *sb,
|
||||
err = add_new_master_key(sb, secret, mk_spec);
|
||||
} else {
|
||||
/*
|
||||
* Found the key in ->s_master_keys. Re-add the secret if
|
||||
* needed, and add the user to ->mk_users if needed.
|
||||
* Found the key in ->s_master_keys. Add the user to ->mk_users
|
||||
* if needed, and make the key "present" again if possible.
|
||||
*/
|
||||
down_write(&mk->mk_sem);
|
||||
err = add_existing_master_key(mk, secret);
|
||||
@@ -898,7 +917,7 @@ static void shrink_dcache_inode(struct inode *inode)
|
||||
|
||||
static void evict_dentries_for_decrypted_inodes(struct fscrypt_master_key *mk)
|
||||
{
|
||||
struct fscrypt_info *ci;
|
||||
struct fscrypt_inode_info *ci;
|
||||
struct inode *inode;
|
||||
struct inode *toput_inode = NULL;
|
||||
|
||||
@@ -948,7 +967,7 @@ static int check_for_busy_inodes(struct super_block *sb,
|
||||
/* select an example file to show for debugging purposes */
|
||||
struct inode *inode =
|
||||
list_first_entry(&mk->mk_decrypted_inodes,
|
||||
struct fscrypt_info,
|
||||
struct fscrypt_inode_info,
|
||||
ci_master_key_link)->ci_inode;
|
||||
ino = inode->i_ino;
|
||||
}
|
||||
@@ -1020,9 +1039,8 @@ static int try_to_lock_encrypted_files(struct super_block *sb,
|
||||
*
|
||||
* If all inodes were evicted, then we unlink the fscrypt_master_key from the
|
||||
* keyring. Otherwise it remains in the keyring in the "incompletely removed"
|
||||
* state (without the actual secret key) where it tracks the list of remaining
|
||||
* inodes. Userspace can execute the ioctl again later to retry eviction, or
|
||||
* alternatively can re-add the secret key again.
|
||||
* state where it tracks the list of remaining inodes. Userspace can execute
|
||||
* the ioctl again later to retry eviction, or alternatively can re-add the key.
|
||||
*
|
||||
* For more details, see the "Removing keys" section of
|
||||
* Documentation/filesystems/fscrypt.rst.
|
||||
@@ -1084,11 +1102,10 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
|
||||
}
|
||||
}
|
||||
|
||||
/* No user claims remaining. Go ahead and wipe the secret. */
|
||||
/* No user claims remaining. Initiate removal of the key. */
|
||||
err = -ENOKEY;
|
||||
if (is_master_key_secret_present(&mk->mk_secret)) {
|
||||
wipe_master_key_secret(&mk->mk_secret);
|
||||
fscrypt_put_master_key_activeref(sb, mk);
|
||||
if (mk->mk_present) {
|
||||
fscrypt_initiate_key_removal(sb, mk);
|
||||
err = 0;
|
||||
}
|
||||
inodes_remain = refcount_read(&mk->mk_active_refs) > 0;
|
||||
@@ -1105,9 +1122,9 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
|
||||
}
|
||||
/*
|
||||
* We return 0 if we successfully did something: removed a claim to the
|
||||
* key, wiped the secret, or tried locking the files again. Users need
|
||||
* to check the informational status flags if they care whether the key
|
||||
* has been fully removed including all files locked.
|
||||
* key, initiated removal of the key, or tried locking the files again.
|
||||
* Users need to check the informational status flags if they care
|
||||
* whether the key has been fully removed including all files locked.
|
||||
*/
|
||||
out_put_key:
|
||||
fscrypt_put_master_key(mk);
|
||||
@@ -1134,12 +1151,11 @@ EXPORT_SYMBOL_GPL(fscrypt_ioctl_remove_key_all_users);
|
||||
* Retrieve the status of an fscrypt master encryption key.
|
||||
*
|
||||
* We set ->status to indicate whether the key is absent, present, or
|
||||
* incompletely removed. "Incompletely removed" means that the master key
|
||||
* secret has been removed, but some files which had been unlocked with it are
|
||||
* still in use. This field allows applications to easily determine the state
|
||||
* of an encrypted directory without using a hack such as trying to open a
|
||||
* regular file in it (which can confuse the "incompletely removed" state with
|
||||
* absent or present).
|
||||
* incompletely removed. (For an explanation of what these statuses mean and
|
||||
* how they are represented internally, see struct fscrypt_master_key.) This
|
||||
* field allows applications to easily determine the status of an encrypted
|
||||
* directory without using a hack such as trying to open a regular file in it
|
||||
* (which can confuse the "incompletely removed" status with absent or present).
|
||||
*
|
||||
* In addition, for v2 policy keys we allow applications to determine, via
|
||||
* ->status_flags and ->user_count, whether the key has been added by the
|
||||
@@ -1181,7 +1197,7 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg)
|
||||
}
|
||||
down_read(&mk->mk_sem);
|
||||
|
||||
if (!is_master_key_secret_present(&mk->mk_secret)) {
|
||||
if (!mk->mk_present) {
|
||||
arg.status = refcount_read(&mk->mk_active_refs) > 0 ?
|
||||
FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED :
|
||||
FSCRYPT_KEY_STATUS_ABSENT /* raced with full removal */;
|
||||
|
||||
+35
-27
@@ -148,7 +148,7 @@ err_free_tfm:
|
||||
* and IV generation method (@ci->ci_policy.flags).
|
||||
*/
|
||||
int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key,
|
||||
const u8 *raw_key, const struct fscrypt_info *ci)
|
||||
const u8 *raw_key, const struct fscrypt_inode_info *ci)
|
||||
{
|
||||
struct crypto_skcipher *tfm;
|
||||
|
||||
@@ -180,13 +180,14 @@ void fscrypt_destroy_prepared_key(struct super_block *sb,
|
||||
}
|
||||
|
||||
/* 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)
|
||||
int fscrypt_set_per_file_enc_key(struct fscrypt_inode_info *ci,
|
||||
const u8 *raw_key)
|
||||
{
|
||||
ci->ci_owns_key = true;
|
||||
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_inode_info *ci,
|
||||
struct fscrypt_master_key *mk,
|
||||
struct fscrypt_prepared_key *keys,
|
||||
u8 hkdf_context, bool include_fs_uuid)
|
||||
@@ -292,7 +293,7 @@ static int fscrypt_derive_siphash_key(const struct fscrypt_master_key *mk,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
|
||||
int fscrypt_derive_dirhash_key(struct fscrypt_inode_info *ci,
|
||||
const struct fscrypt_master_key *mk)
|
||||
{
|
||||
int err;
|
||||
@@ -306,7 +307,7 @@ int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fscrypt_hash_inode_number(struct fscrypt_info *ci,
|
||||
void fscrypt_hash_inode_number(struct fscrypt_inode_info *ci,
|
||||
const struct fscrypt_master_key *mk)
|
||||
{
|
||||
WARN_ON_ONCE(ci->ci_inode->i_ino == 0);
|
||||
@@ -316,7 +317,7 @@ void fscrypt_hash_inode_number(struct fscrypt_info *ci,
|
||||
&mk->mk_ino_hash_key);
|
||||
}
|
||||
|
||||
static int fscrypt_setup_iv_ino_lblk_32_key(struct fscrypt_info *ci,
|
||||
static int fscrypt_setup_iv_ino_lblk_32_key(struct fscrypt_inode_info *ci,
|
||||
struct fscrypt_master_key *mk)
|
||||
{
|
||||
int err;
|
||||
@@ -356,7 +357,7 @@ unlock:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci,
|
||||
static int fscrypt_setup_v2_file_key(struct fscrypt_inode_info *ci,
|
||||
struct fscrypt_master_key *mk,
|
||||
bool need_dirhash_key)
|
||||
{
|
||||
@@ -439,7 +440,7 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci,
|
||||
* still allow 512-bit master keys if the user chooses to use them, though.)
|
||||
*/
|
||||
static bool fscrypt_valid_master_key_size(const struct fscrypt_master_key *mk,
|
||||
const struct fscrypt_info *ci)
|
||||
const struct fscrypt_inode_info *ci)
|
||||
{
|
||||
unsigned int min_keysize;
|
||||
|
||||
@@ -465,11 +466,12 @@ static bool fscrypt_valid_master_key_size(const struct fscrypt_master_key *mk,
|
||||
*
|
||||
* If the master key is found in the filesystem-level keyring, then it is
|
||||
* returned in *mk_ret with its semaphore read-locked. This is needed to ensure
|
||||
* that only one task links the fscrypt_info into ->mk_decrypted_inodes (as
|
||||
* multiple tasks may race to create an fscrypt_info for the same inode), and to
|
||||
* synchronize the master key being removed with a new inode starting to use it.
|
||||
* that only one task links the fscrypt_inode_info into ->mk_decrypted_inodes
|
||||
* (as multiple tasks may race to create an fscrypt_inode_info for the same
|
||||
* inode), and to synchronize the master key being removed with a new inode
|
||||
* starting to use it.
|
||||
*/
|
||||
static int setup_file_encryption_key(struct fscrypt_info *ci,
|
||||
static int setup_file_encryption_key(struct fscrypt_inode_info *ci,
|
||||
bool need_dirhash_key,
|
||||
struct fscrypt_master_key **mk_ret)
|
||||
{
|
||||
@@ -519,8 +521,8 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
|
||||
}
|
||||
down_read(&mk->mk_sem);
|
||||
|
||||
/* Has the secret been removed (via FS_IOC_REMOVE_ENCRYPTION_KEY)? */
|
||||
if (!is_master_key_secret_present(&mk->mk_secret)) {
|
||||
if (!mk->mk_present) {
|
||||
/* FS_IOC_REMOVE_ENCRYPTION_KEY has been executed on this key */
|
||||
err = -ENOKEY;
|
||||
goto out_release_key;
|
||||
}
|
||||
@@ -566,7 +568,7 @@ out_release_key:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void put_crypt_info(struct fscrypt_info *ci)
|
||||
static void put_crypt_info(struct fscrypt_inode_info *ci)
|
||||
{
|
||||
struct fscrypt_master_key *mk;
|
||||
|
||||
@@ -584,8 +586,8 @@ static void put_crypt_info(struct fscrypt_info *ci)
|
||||
/*
|
||||
* Remove this inode from the list of inodes that were unlocked
|
||||
* with the master key. In addition, if we're removing the last
|
||||
* inode from a master key struct that already had its secret
|
||||
* removed, then complete the full removal of the struct.
|
||||
* inode from an incompletely removed key, then complete the
|
||||
* full removal of the key.
|
||||
*/
|
||||
spin_lock(&mk->mk_decrypted_inodes_lock);
|
||||
list_del(&ci->ci_master_key_link);
|
||||
@@ -593,7 +595,7 @@ static void put_crypt_info(struct fscrypt_info *ci)
|
||||
fscrypt_put_master_key_activeref(ci->ci_inode->i_sb, mk);
|
||||
}
|
||||
memzero_explicit(ci, sizeof(*ci));
|
||||
kmem_cache_free(fscrypt_info_cachep, ci);
|
||||
kmem_cache_free(fscrypt_inode_info_cachep, ci);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -602,7 +604,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
|
||||
const u8 nonce[FSCRYPT_FILE_NONCE_SIZE],
|
||||
bool need_dirhash_key)
|
||||
{
|
||||
struct fscrypt_info *crypt_info;
|
||||
struct fscrypt_inode_info *crypt_info;
|
||||
struct fscrypt_mode *mode;
|
||||
struct fscrypt_master_key *mk = NULL;
|
||||
int res;
|
||||
@@ -611,7 +613,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
crypt_info = kmem_cache_zalloc(fscrypt_info_cachep, GFP_KERNEL);
|
||||
crypt_info = kmem_cache_zalloc(fscrypt_inode_info_cachep, GFP_KERNEL);
|
||||
if (!crypt_info)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -627,6 +629,11 @@ fscrypt_setup_encryption_info(struct inode *inode,
|
||||
WARN_ON_ONCE(mode->ivsize > FSCRYPT_MAX_IV_SIZE);
|
||||
crypt_info->ci_mode = mode;
|
||||
|
||||
crypt_info->ci_data_unit_bits =
|
||||
fscrypt_policy_du_bits(&crypt_info->ci_policy, inode);
|
||||
crypt_info->ci_data_units_per_block_bits =
|
||||
inode->i_blkbits - crypt_info->ci_data_unit_bits;
|
||||
|
||||
res = setup_file_encryption_key(crypt_info, need_dirhash_key, &mk);
|
||||
if (res)
|
||||
goto out;
|
||||
@@ -634,8 +641,8 @@ fscrypt_setup_encryption_info(struct inode *inode,
|
||||
/*
|
||||
* For existing inodes, 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.
|
||||
* fscrypt_get_inode_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) {
|
||||
/*
|
||||
@@ -782,8 +789,8 @@ EXPORT_SYMBOL_GPL(fscrypt_prepare_new_inode);
|
||||
* 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.
|
||||
* Free the inode's fscrypt_inode_info. Filesystems must call this when the
|
||||
* inode is being evicted. An RCU grace period need not have elapsed yet.
|
||||
*/
|
||||
void fscrypt_put_encryption_info(struct inode *inode)
|
||||
{
|
||||
@@ -820,7 +827,7 @@ EXPORT_SYMBOL(fscrypt_free_inode);
|
||||
*/
|
||||
int fscrypt_drop_inode(struct inode *inode)
|
||||
{
|
||||
const struct fscrypt_info *ci = fscrypt_get_info(inode);
|
||||
const struct fscrypt_inode_info *ci = fscrypt_get_inode_info(inode);
|
||||
|
||||
/*
|
||||
* If ci is NULL, then the inode doesn't have an encryption key set up
|
||||
@@ -841,13 +848,14 @@ int fscrypt_drop_inode(struct inode *inode)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Note: since we aren't holding the key semaphore, the result here can
|
||||
* We can't take ->mk_sem here, since this runs in atomic context.
|
||||
* Therefore, ->mk_present can change concurrently, and our result may
|
||||
* immediately become outdated. But there's no correctness problem with
|
||||
* unnecessarily evicting. Nor is there a correctness problem with not
|
||||
* evicting while iput() is racing with the key being removed, since
|
||||
* then the thread removing the key will either evict the inode itself
|
||||
* or will correctly detect that it wasn't evicted due to the race.
|
||||
*/
|
||||
return !is_master_key_secret_present(&ci->ci_master_key->mk_secret);
|
||||
return !READ_ONCE(ci->ci_master_key->mk_present);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fscrypt_drop_inode);
|
||||
|
||||
+12
-8
@@ -179,7 +179,8 @@ void fscrypt_put_direct_key(struct fscrypt_direct_key *dk)
|
||||
*/
|
||||
static struct fscrypt_direct_key *
|
||||
find_or_insert_direct_key(struct fscrypt_direct_key *to_insert,
|
||||
const u8 *raw_key, const struct fscrypt_info *ci)
|
||||
const u8 *raw_key,
|
||||
const struct fscrypt_inode_info *ci)
|
||||
{
|
||||
unsigned long hash_key;
|
||||
struct fscrypt_direct_key *dk;
|
||||
@@ -219,7 +220,7 @@ find_or_insert_direct_key(struct fscrypt_direct_key *to_insert,
|
||||
|
||||
/* Prepare to encrypt directly using the master key in the given mode */
|
||||
static struct fscrypt_direct_key *
|
||||
fscrypt_get_direct_key(const struct fscrypt_info *ci, const u8 *raw_key)
|
||||
fscrypt_get_direct_key(const struct fscrypt_inode_info *ci, const u8 *raw_key)
|
||||
{
|
||||
struct fscrypt_direct_key *dk;
|
||||
int err;
|
||||
@@ -251,7 +252,7 @@ err_free_dk:
|
||||
}
|
||||
|
||||
/* v1 policy, DIRECT_KEY: use the master key directly */
|
||||
static int setup_v1_file_key_direct(struct fscrypt_info *ci,
|
||||
static int setup_v1_file_key_direct(struct fscrypt_inode_info *ci,
|
||||
const u8 *raw_master_key)
|
||||
{
|
||||
struct fscrypt_direct_key *dk;
|
||||
@@ -265,7 +266,7 @@ static int setup_v1_file_key_direct(struct fscrypt_info *ci,
|
||||
}
|
||||
|
||||
/* v1 policy, !DIRECT_KEY: derive the file's encryption key */
|
||||
static int setup_v1_file_key_derived(struct fscrypt_info *ci,
|
||||
static int setup_v1_file_key_derived(struct fscrypt_inode_info *ci,
|
||||
const u8 *raw_master_key)
|
||||
{
|
||||
u8 *derived_key;
|
||||
@@ -290,7 +291,8 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
int fscrypt_setup_v1_file_key(struct fscrypt_info *ci, const u8 *raw_master_key)
|
||||
int fscrypt_setup_v1_file_key(struct fscrypt_inode_info *ci,
|
||||
const u8 *raw_master_key)
|
||||
{
|
||||
if (ci->ci_policy.v1.flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY)
|
||||
return setup_v1_file_key_direct(ci, raw_master_key);
|
||||
@@ -298,8 +300,10 @@ int fscrypt_setup_v1_file_key(struct fscrypt_info *ci, const u8 *raw_master_key)
|
||||
return setup_v1_file_key_derived(ci, raw_master_key);
|
||||
}
|
||||
|
||||
int fscrypt_setup_v1_file_key_via_subscribed_keyrings(struct fscrypt_info *ci)
|
||||
int
|
||||
fscrypt_setup_v1_file_key_via_subscribed_keyrings(struct fscrypt_inode_info *ci)
|
||||
{
|
||||
const struct super_block *sb = ci->ci_inode->i_sb;
|
||||
struct key *key;
|
||||
const struct fscrypt_key *payload;
|
||||
int err;
|
||||
@@ -307,8 +311,8 @@ int fscrypt_setup_v1_file_key_via_subscribed_keyrings(struct fscrypt_info *ci)
|
||||
key = find_and_lock_process_key(FSCRYPT_KEY_DESC_PREFIX,
|
||||
ci->ci_policy.v1.master_key_descriptor,
|
||||
ci->ci_mode->keysize, &payload);
|
||||
if (key == ERR_PTR(-ENOKEY) && ci->ci_inode->i_sb->s_cop->key_prefix) {
|
||||
key = find_and_lock_process_key(ci->ci_inode->i_sb->s_cop->key_prefix,
|
||||
if (key == ERR_PTR(-ENOKEY) && sb->s_cop->legacy_key_prefix) {
|
||||
key = find_and_lock_process_key(sb->s_cop->legacy_key_prefix,
|
||||
ci->ci_policy.v1.master_key_descriptor,
|
||||
ci->ci_mode->keysize, &payload);
|
||||
}
|
||||
|
||||
+55
-28
@@ -118,12 +118,11 @@ static bool supported_direct_key_modes(const struct inode *inode,
|
||||
}
|
||||
|
||||
static bool supported_iv_ino_lblk_policy(const struct fscrypt_policy_v2 *policy,
|
||||
const struct inode *inode,
|
||||
const char *type,
|
||||
int max_ino_bits, int max_lblk_bits)
|
||||
const struct inode *inode)
|
||||
{
|
||||
const char *type = (policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64)
|
||||
? "IV_INO_LBLK_64" : "IV_INO_LBLK_32";
|
||||
struct super_block *sb = inode->i_sb;
|
||||
int ino_bits = 64, lblk_bits = 64;
|
||||
|
||||
/*
|
||||
* IV_INO_LBLK_* exist only because of hardware limitations, and
|
||||
@@ -150,17 +149,29 @@ static bool supported_iv_ino_lblk_policy(const struct fscrypt_policy_v2 *policy,
|
||||
type, sb->s_id);
|
||||
return false;
|
||||
}
|
||||
if (sb->s_cop->get_ino_and_lblk_bits)
|
||||
sb->s_cop->get_ino_and_lblk_bits(sb, &ino_bits, &lblk_bits);
|
||||
if (ino_bits > max_ino_bits) {
|
||||
|
||||
/*
|
||||
* IV_INO_LBLK_64 and IV_INO_LBLK_32 both require that inode numbers fit
|
||||
* in 32 bits. In principle, IV_INO_LBLK_32 could support longer inode
|
||||
* numbers because it hashes the inode number; however, currently the
|
||||
* inode number is gotten from inode::i_ino which is 'unsigned long'.
|
||||
* So for now the implementation limit is 32 bits.
|
||||
*/
|
||||
if (!sb->s_cop->has_32bit_inodes) {
|
||||
fscrypt_warn(inode,
|
||||
"Can't use %s policy on filesystem '%s' because its inode numbers are too long",
|
||||
type, sb->s_id);
|
||||
return false;
|
||||
}
|
||||
if (lblk_bits > max_lblk_bits) {
|
||||
|
||||
/*
|
||||
* IV_INO_LBLK_64 and IV_INO_LBLK_32 both require that file data unit
|
||||
* indices fit in 32 bits.
|
||||
*/
|
||||
if (fscrypt_max_file_dun_bits(sb,
|
||||
fscrypt_policy_v2_du_bits(policy, inode)) > 32) {
|
||||
fscrypt_warn(inode,
|
||||
"Can't use %s policy on filesystem '%s' because its block numbers are too long",
|
||||
"Can't use %s policy on filesystem '%s' because its maximum file size is too large",
|
||||
type, sb->s_id);
|
||||
return false;
|
||||
}
|
||||
@@ -233,25 +244,39 @@ static bool fscrypt_supported_v2_policy(const struct fscrypt_policy_v2 *policy,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (policy->log2_data_unit_size) {
|
||||
if (!inode->i_sb->s_cop->supports_subblock_data_units) {
|
||||
fscrypt_warn(inode,
|
||||
"Filesystem does not support configuring crypto data unit size");
|
||||
return false;
|
||||
}
|
||||
if (policy->log2_data_unit_size > inode->i_blkbits ||
|
||||
policy->log2_data_unit_size < SECTOR_SHIFT /* 9 */) {
|
||||
fscrypt_warn(inode,
|
||||
"Unsupported log2_data_unit_size in encryption policy: %d",
|
||||
policy->log2_data_unit_size);
|
||||
return false;
|
||||
}
|
||||
if (policy->log2_data_unit_size != inode->i_blkbits &&
|
||||
(policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) {
|
||||
/*
|
||||
* Not safe to enable yet, as we need to ensure that DUN
|
||||
* wraparound can only occur on a FS block boundary.
|
||||
*/
|
||||
fscrypt_warn(inode,
|
||||
"Sub-block data units not yet supported with IV_INO_LBLK_32");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((policy->flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) &&
|
||||
!supported_direct_key_modes(inode, policy->contents_encryption_mode,
|
||||
policy->filenames_encryption_mode))
|
||||
return false;
|
||||
|
||||
if ((policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) &&
|
||||
!supported_iv_ino_lblk_policy(policy, inode, "IV_INO_LBLK_64",
|
||||
32, 32))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* IV_INO_LBLK_32 hashes the inode number, so in principle it can
|
||||
* support any ino_bits. However, currently the inode number is gotten
|
||||
* from inode::i_ino which is 'unsigned long'. So for now the
|
||||
* implementation limit is 32 bits.
|
||||
*/
|
||||
if ((policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) &&
|
||||
!supported_iv_ino_lblk_policy(policy, inode, "IV_INO_LBLK_32",
|
||||
32, 32))
|
||||
if ((policy->flags & (FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64 |
|
||||
FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) &&
|
||||
!supported_iv_ino_lblk_policy(policy, inode))
|
||||
return false;
|
||||
|
||||
if (memchr_inv(policy->__reserved, 0, sizeof(policy->__reserved))) {
|
||||
@@ -330,6 +355,7 @@ static int fscrypt_new_context(union fscrypt_context *ctx_u,
|
||||
ctx->filenames_encryption_mode =
|
||||
policy->filenames_encryption_mode;
|
||||
ctx->flags = policy->flags;
|
||||
ctx->log2_data_unit_size = policy->log2_data_unit_size;
|
||||
memcpy(ctx->master_key_identifier,
|
||||
policy->master_key_identifier,
|
||||
sizeof(ctx->master_key_identifier));
|
||||
@@ -390,6 +416,7 @@ int fscrypt_policy_from_context(union fscrypt_policy *policy_u,
|
||||
policy->filenames_encryption_mode =
|
||||
ctx->filenames_encryption_mode;
|
||||
policy->flags = ctx->flags;
|
||||
policy->log2_data_unit_size = ctx->log2_data_unit_size;
|
||||
memcpy(policy->__reserved, ctx->__reserved,
|
||||
sizeof(policy->__reserved));
|
||||
memcpy(policy->master_key_identifier,
|
||||
@@ -405,11 +432,11 @@ int fscrypt_policy_from_context(union fscrypt_policy *policy_u,
|
||||
/* Retrieve an inode's encryption policy */
|
||||
static int fscrypt_get_policy(struct inode *inode, union fscrypt_policy *policy)
|
||||
{
|
||||
const struct fscrypt_info *ci;
|
||||
const struct fscrypt_inode_info *ci;
|
||||
union fscrypt_context ctx;
|
||||
int ret;
|
||||
|
||||
ci = fscrypt_get_info(inode);
|
||||
ci = fscrypt_get_inode_info(inode);
|
||||
if (ci) {
|
||||
/* key available, use the cached policy */
|
||||
*policy = ci->ci_policy;
|
||||
@@ -647,7 +674,7 @@ int fscrypt_has_permitted_context(struct inode *parent, struct inode *child)
|
||||
|
||||
/*
|
||||
* Both parent and child are encrypted, so verify they use the same
|
||||
* encryption policy. Compare the fscrypt_info structs if the keys are
|
||||
* encryption policy. Compare the cached policies if the keys are
|
||||
* available, otherwise retrieve and compare the fscrypt_contexts.
|
||||
*
|
||||
* Note that the fscrypt_context retrieval will be required frequently
|
||||
@@ -717,7 +744,7 @@ const union fscrypt_policy *fscrypt_policy_to_inherit(struct inode *dir)
|
||||
*/
|
||||
int fscrypt_context_for_new_inode(void *ctx, struct inode *inode)
|
||||
{
|
||||
struct fscrypt_info *ci = inode->i_crypt_info;
|
||||
struct fscrypt_inode_info *ci = inode->i_crypt_info;
|
||||
|
||||
BUILD_BUG_ON(sizeof(union fscrypt_context) !=
|
||||
FSCRYPT_SET_CONTEXT_MAX_SIZE);
|
||||
@@ -742,7 +769,7 @@ EXPORT_SYMBOL_GPL(fscrypt_context_for_new_inode);
|
||||
*/
|
||||
int fscrypt_set_context(struct inode *inode, void *fs_data)
|
||||
{
|
||||
struct fscrypt_info *ci = inode->i_crypt_info;
|
||||
struct fscrypt_inode_info *ci = inode->i_crypt_info;
|
||||
union fscrypt_context ctx;
|
||||
int ctxsize;
|
||||
|
||||
|
||||
+4
-9
@@ -232,19 +232,14 @@ static bool ext4_has_stable_inodes(struct super_block *sb)
|
||||
return ext4_has_feature_stable_inodes(sb);
|
||||
}
|
||||
|
||||
static void ext4_get_ino_and_lblk_bits(struct super_block *sb,
|
||||
int *ino_bits_ret, int *lblk_bits_ret)
|
||||
{
|
||||
*ino_bits_ret = 8 * sizeof(EXT4_SB(sb)->s_es->s_inodes_count);
|
||||
*lblk_bits_ret = 8 * sizeof(ext4_lblk_t);
|
||||
}
|
||||
|
||||
const struct fscrypt_operations ext4_cryptops = {
|
||||
.key_prefix = "ext4:",
|
||||
.needs_bounce_pages = 1,
|
||||
.has_32bit_inodes = 1,
|
||||
.supports_subblock_data_units = 1,
|
||||
.legacy_key_prefix = "ext4:",
|
||||
.get_context = ext4_get_context,
|
||||
.set_context = ext4_set_context,
|
||||
.get_dummy_policy = ext4_get_dummy_policy,
|
||||
.empty_dir = ext4_empty_dir,
|
||||
.has_stable_inodes = ext4_has_stable_inodes,
|
||||
.get_ino_and_lblk_bits = ext4_get_ino_and_lblk_bits,
|
||||
};
|
||||
|
||||
+4
-9
@@ -3203,13 +3203,6 @@ static bool f2fs_has_stable_inodes(struct super_block *sb)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void f2fs_get_ino_and_lblk_bits(struct super_block *sb,
|
||||
int *ino_bits_ret, int *lblk_bits_ret)
|
||||
{
|
||||
*ino_bits_ret = 8 * sizeof(nid_t);
|
||||
*lblk_bits_ret = 8 * sizeof(block_t);
|
||||
}
|
||||
|
||||
static struct block_device **f2fs_get_devices(struct super_block *sb,
|
||||
unsigned int *num_devs)
|
||||
{
|
||||
@@ -3231,13 +3224,15 @@ static struct block_device **f2fs_get_devices(struct super_block *sb,
|
||||
}
|
||||
|
||||
static const struct fscrypt_operations f2fs_cryptops = {
|
||||
.key_prefix = "f2fs:",
|
||||
.needs_bounce_pages = 1,
|
||||
.has_32bit_inodes = 1,
|
||||
.supports_subblock_data_units = 1,
|
||||
.legacy_key_prefix = "f2fs:",
|
||||
.get_context = f2fs_get_context,
|
||||
.set_context = f2fs_set_context,
|
||||
.get_dummy_policy = f2fs_get_dummy_policy,
|
||||
.empty_dir = f2fs_empty_dir,
|
||||
.has_stable_inodes = f2fs_has_stable_inodes,
|
||||
.get_ino_and_lblk_bits = f2fs_get_ino_and_lblk_bits,
|
||||
.get_devices = f2fs_get_devices,
|
||||
};
|
||||
#endif
|
||||
|
||||
+1
-2
@@ -88,8 +88,7 @@ int ubifs_decrypt(const struct inode *inode, struct ubifs_data_node *dn,
|
||||
}
|
||||
|
||||
const struct fscrypt_operations ubifs_crypt_operations = {
|
||||
.flags = FS_CFLG_OWN_PAGES,
|
||||
.key_prefix = "ubifs:",
|
||||
.legacy_key_prefix = "ubifs:",
|
||||
.get_context = ubifs_crypt_get_context,
|
||||
.set_context = ubifs_crypt_set_context,
|
||||
.empty_dir = ubifs_crypt_empty_dir,
|
||||
|
||||
+2
-2
@@ -67,7 +67,7 @@ struct swap_info_struct;
|
||||
struct seq_file;
|
||||
struct workqueue_struct;
|
||||
struct iov_iter;
|
||||
struct fscrypt_info;
|
||||
struct fscrypt_inode_info;
|
||||
struct fscrypt_operations;
|
||||
struct fsverity_info;
|
||||
struct fsverity_operations;
|
||||
@@ -738,7 +738,7 @@ struct inode {
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
struct fscrypt_info *i_crypt_info;
|
||||
struct fscrypt_inode_info *i_crypt_info;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FS_VERITY
|
||||
|
||||
+49
-33
@@ -31,7 +31,7 @@
|
||||
#define FSCRYPT_CONTENTS_ALIGNMENT 16
|
||||
|
||||
union fscrypt_policy;
|
||||
struct fscrypt_info;
|
||||
struct fscrypt_inode_info;
|
||||
struct fs_parameter;
|
||||
struct seq_file;
|
||||
|
||||
@@ -59,26 +59,55 @@ struct fscrypt_name {
|
||||
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
|
||||
/*
|
||||
* If set, the fscrypt bounce page pool won't be allocated (unless another
|
||||
* filesystem needs it). Set this if the filesystem always uses its own bounce
|
||||
* pages for writes and therefore won't need the fscrypt bounce page pool.
|
||||
*/
|
||||
#define FS_CFLG_OWN_PAGES (1U << 1)
|
||||
|
||||
/* Crypto operations for filesystems */
|
||||
struct fscrypt_operations {
|
||||
|
||||
/* Set of optional flags; see above for allowed flags */
|
||||
unsigned int flags;
|
||||
/*
|
||||
* If set, then fs/crypto/ will allocate a global bounce page pool the
|
||||
* first time an encryption key is set up for a file. The bounce page
|
||||
* pool is required by the following functions:
|
||||
*
|
||||
* - fscrypt_encrypt_pagecache_blocks()
|
||||
* - fscrypt_zeroout_range() for files not using inline crypto
|
||||
*
|
||||
* If the filesystem doesn't use those, it doesn't need to set this.
|
||||
*/
|
||||
unsigned int needs_bounce_pages : 1;
|
||||
|
||||
/*
|
||||
* If set, this is a filesystem-specific key description prefix that
|
||||
* will be accepted for "logon" keys for v1 fscrypt policies, in
|
||||
* addition to the generic prefix "fscrypt:". This functionality is
|
||||
* deprecated, so new filesystems shouldn't set this field.
|
||||
* If set, then fs/crypto/ will allow the use of encryption settings
|
||||
* that assume inode numbers fit in 32 bits (i.e.
|
||||
* FSCRYPT_POLICY_FLAG_IV_INO_LBLK_{32,64}), provided that the other
|
||||
* prerequisites for these settings are also met. This is only useful
|
||||
* if the filesystem wants to support inline encryption hardware that is
|
||||
* limited to 32-bit or 64-bit data unit numbers and where programming
|
||||
* keyslots is very slow.
|
||||
*/
|
||||
const char *key_prefix;
|
||||
unsigned int has_32bit_inodes : 1;
|
||||
|
||||
/*
|
||||
* If set, then fs/crypto/ will allow users to select a crypto data unit
|
||||
* size that is less than the filesystem block size. This is done via
|
||||
* the log2_data_unit_size field of the fscrypt policy. This flag is
|
||||
* not compatible with filesystems that encrypt variable-length blocks
|
||||
* (i.e. blocks that aren't all equal to filesystem's block size), for
|
||||
* example as a result of compression. It's also not compatible with
|
||||
* the fscrypt_encrypt_block_inplace() and
|
||||
* fscrypt_decrypt_block_inplace() functions.
|
||||
*/
|
||||
unsigned int supports_subblock_data_units : 1;
|
||||
|
||||
/*
|
||||
* This field exists only for backwards compatibility reasons and should
|
||||
* only be set by the filesystems that are setting it already. It
|
||||
* contains the filesystem-specific key description prefix that is
|
||||
* accepted for "logon" keys for v1 fscrypt policies. This
|
||||
* functionality is deprecated in favor of the generic prefix
|
||||
* "fscrypt:", which itself is deprecated in favor of the filesystem
|
||||
* keyring ioctls such as FS_IOC_ADD_ENCRYPTION_KEY. Filesystems that
|
||||
* are newly adding fscrypt support should not set this field.
|
||||
*/
|
||||
const char *legacy_key_prefix;
|
||||
|
||||
/*
|
||||
* Get the fscrypt context of the given inode.
|
||||
@@ -145,21 +174,6 @@ struct fscrypt_operations {
|
||||
*/
|
||||
bool (*has_stable_inodes)(struct super_block *sb);
|
||||
|
||||
/*
|
||||
* Get the number of bits that the filesystem uses to represent inode
|
||||
* numbers and file logical block numbers.
|
||||
*
|
||||
* By default, both of these are assumed to be 64-bit. This function
|
||||
* can be implemented to declare that either or both of these numbers is
|
||||
* shorter, which may allow the use of the
|
||||
* FSCRYPT_POLICY_FLAG_IV_INO_LBLK_{32,64} flags and/or the use of
|
||||
* inline crypto hardware whose maximum DUN length is less than 64 bits
|
||||
* (e.g., eMMC v5.2 spec compliant hardware). This function only needs
|
||||
* to be implemented if support for one of these features is needed.
|
||||
*/
|
||||
void (*get_ino_and_lblk_bits)(struct super_block *sb,
|
||||
int *ino_bits_ret, int *lblk_bits_ret);
|
||||
|
||||
/*
|
||||
* Return an array of pointers to the block devices to which the
|
||||
* filesystem may write encrypted file contents, NULL if the filesystem
|
||||
@@ -178,7 +192,8 @@ struct fscrypt_operations {
|
||||
unsigned int *num_devs);
|
||||
};
|
||||
|
||||
static inline struct fscrypt_info *fscrypt_get_info(const struct inode *inode)
|
||||
static inline struct fscrypt_inode_info *
|
||||
fscrypt_get_inode_info(const struct inode *inode)
|
||||
{
|
||||
/*
|
||||
* Pairs with the cmpxchg_release() in fscrypt_setup_encryption_info().
|
||||
@@ -390,7 +405,8 @@ static inline void fscrypt_set_ops(struct super_block *sb,
|
||||
}
|
||||
#else /* !CONFIG_FS_ENCRYPTION */
|
||||
|
||||
static inline struct fscrypt_info *fscrypt_get_info(const struct inode *inode)
|
||||
static inline struct fscrypt_inode_info *
|
||||
fscrypt_get_inode_info(const struct inode *inode)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -882,7 +898,7 @@ static inline bool fscrypt_inode_uses_fs_layer_crypto(const struct inode *inode)
|
||||
*/
|
||||
static inline bool fscrypt_has_encryption_key(const struct inode *inode)
|
||||
{
|
||||
return fscrypt_get_info(inode) != NULL;
|
||||
return fscrypt_get_inode_info(inode) != NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -71,7 +71,8 @@ struct fscrypt_policy_v2 {
|
||||
__u8 contents_encryption_mode;
|
||||
__u8 filenames_encryption_mode;
|
||||
__u8 flags;
|
||||
__u8 __reserved[4];
|
||||
__u8 log2_data_unit_size;
|
||||
__u8 __reserved[3];
|
||||
__u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE];
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user