forked from luck/tmp_suning_uos_patched
fscrypt updates for 5.8
- Add the IV_INO_LBLK_32 encryption policy flag which modifies the encryption to be optimized for eMMC inline encryption hardware. - Make the test_dummy_encryption mount option for ext4 and f2fs support v2 encryption policies. - Fix kerneldoc warnings and some coding style inconsistencies. There will be merge conflicts with the ext4 and f2fs trees due to the test_dummy_encryption change, but the resolutions are straightforward. -----BEGIN PGP SIGNATURE----- iIoEABYIADIWIQSacvsUNc7UX4ntmEPzXCl4vpKOKwUCXtScMBQcZWJpZ2dlcnNA Z29vZ2xlLmNvbQAKCRDzXCl4vpKOKxC6AP0eOEkMrc9e10YftdN6xsyRjvqiPyFg oMjuU+SvQ+/sVgEAo0mBFITnl75ZGb8PyqXCNMDAy6uHaxcEjVGufx5q2QE= =dbxy -----END PGP SIGNATURE----- Merge tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt Pull fscrypt updates from Eric Biggers: - Add the IV_INO_LBLK_32 encryption policy flag which modifies the encryption to be optimized for eMMC inline encryption hardware. - Make the test_dummy_encryption mount option for ext4 and f2fs support v2 encryption policies. - Fix kerneldoc warnings and some coding style inconsistencies. * tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt: fscrypt: add support for IV_INO_LBLK_32 policies fscrypt: make test_dummy_encryption use v2 by default fscrypt: support test_dummy_encryption=v2 fscrypt: add fscrypt_add_test_dummy_key() linux/parser.h: add include guards fscrypt: remove unnecessary extern keywords fscrypt: name all function parameters fscrypt: fix all kerneldoc warnings
This commit is contained in:
commit
afdb0f2ec5
|
@ -225,8 +225,12 @@ fsync_mode=%s Control the policy of fsync. Currently supports "posix",
|
|||
pass, but the performance will regress. "nobarrier" is
|
||||
based on "posix", but doesn't issue flush command for
|
||||
non-atomic files likewise "nobarrier" mount option.
|
||||
test_dummy_encryption Enable dummy encryption, which provides a fake fscrypt
|
||||
test_dummy_encryption
|
||||
test_dummy_encryption=%s
|
||||
Enable dummy encryption, which provides a fake fscrypt
|
||||
context. The fake fscrypt context is used by xfstests.
|
||||
The argument may be either "v1" or "v2", in order to
|
||||
select the corresponding fscrypt policy version.
|
||||
checkpoint=%s[:%u[%]] Set to "disable" to turn off checkpointing. Set to "enable"
|
||||
to reenable checkpointing. Is enabled by default. While
|
||||
disabled, any unmounting or unexpected shutdowns will cause
|
||||
|
|
|
@ -292,8 +292,22 @@ files' data differently, inode numbers are included in the IVs.
|
|||
Consequently, shrinking the filesystem may not be allowed.
|
||||
|
||||
This format is optimized for use with inline encryption hardware
|
||||
compliant with the UFS or eMMC standards, which support only 64 IV
|
||||
bits per I/O request and may have only a small number of keyslots.
|
||||
compliant with the UFS standard, which supports only 64 IV bits per
|
||||
I/O request and may have only a small number of keyslots.
|
||||
|
||||
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.
|
||||
|
||||
This format is optimized for use with inline encryption hardware
|
||||
compliant with the eMMC v5.2 standard, which supports only 32 IV bits
|
||||
per I/O request and may have only a small number of keyslots. This
|
||||
format results in some level of IV reuse, so it should only be used
|
||||
when necessary due to hardware limitations.
|
||||
|
||||
Key identifiers
|
||||
---------------
|
||||
|
@ -369,6 +383,10 @@ a little endian number, except that:
|
|||
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.
|
||||
|
||||
- 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.
|
||||
|
||||
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".
|
||||
|
@ -465,8 +483,15 @@ This structure must be initialized as follows:
|
|||
(0x3).
|
||||
- FSCRYPT_POLICY_FLAG_DIRECT_KEY: See `DIRECT_KEY policies`_.
|
||||
- FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64: See `IV_INO_LBLK_64
|
||||
policies`_. This is mutually exclusive with DIRECT_KEY and is not
|
||||
supported on v1 policies.
|
||||
policies`_.
|
||||
- FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32: See `IV_INO_LBLK_32
|
||||
policies`_.
|
||||
|
||||
v1 encryption policies only support the PAD_* and DIRECT_KEY flags.
|
||||
The other flags are only supported by v2 encryption policies.
|
||||
|
||||
The DIRECT_KEY, IV_INO_LBLK_64, and IV_INO_LBLK_32 flags are
|
||||
mutually exclusive.
|
||||
|
||||
- For v2 encryption policies, ``__reserved`` must be zeroed.
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags)
|
|||
|
||||
/**
|
||||
* fscrypt_free_bounce_page() - free a ciphertext bounce page
|
||||
* @bounce_page: the bounce page to free, or NULL
|
||||
*
|
||||
* Free a bounce page that was allocated by fscrypt_encrypt_pagecache_blocks(),
|
||||
* or by fscrypt_alloc_bounce_page() directly.
|
||||
|
@ -76,8 +77,12 @@ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num,
|
|||
memset(iv, 0, ci->ci_mode->ivsize);
|
||||
|
||||
if (flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) {
|
||||
WARN_ON_ONCE((u32)lblk_num != lblk_num);
|
||||
WARN_ON_ONCE(lblk_num > U32_MAX);
|
||||
WARN_ON_ONCE(ci->ci_inode->i_ino > U32_MAX);
|
||||
lblk_num |= (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);
|
||||
} else if (flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) {
|
||||
memcpy(iv->nonce, ci->ci_nonce, FS_KEY_DERIVATION_NONCE_SIZE);
|
||||
}
|
||||
|
@ -132,7 +137,8 @@ int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw,
|
|||
}
|
||||
|
||||
/**
|
||||
* fscrypt_encrypt_pagecache_blocks() - Encrypt filesystem blocks from a pagecache page
|
||||
* fscrypt_encrypt_pagecache_blocks() - Encrypt filesystem blocks from a
|
||||
* pagecache page
|
||||
* @page: The locked pagecache page containing the block(s) to encrypt
|
||||
* @len: Total size of the block(s) to encrypt. Must be a nonzero
|
||||
* multiple of the filesystem's block size.
|
||||
|
@ -222,7 +228,8 @@ int fscrypt_encrypt_block_inplace(const struct inode *inode, struct page *page,
|
|||
EXPORT_SYMBOL(fscrypt_encrypt_block_inplace);
|
||||
|
||||
/**
|
||||
* fscrypt_decrypt_pagecache_blocks() - Decrypt filesystem blocks in a pagecache page
|
||||
* fscrypt_decrypt_pagecache_blocks() - Decrypt filesystem blocks in a
|
||||
* pagecache page
|
||||
* @page: The locked pagecache page containing the block(s) to decrypt
|
||||
* @len: Total size of the block(s) to decrypt. Must be a nonzero
|
||||
* multiple of the filesystem's block size.
|
||||
|
@ -346,6 +353,8 @@ void fscrypt_msg(const struct inode *inode, const char *level,
|
|||
|
||||
/**
|
||||
* fscrypt_init() - Set up for fs encryption.
|
||||
*
|
||||
* Return: 0 on success; -errno on failure
|
||||
*/
|
||||
static int __init fscrypt_init(void)
|
||||
{
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include <crypto/skcipher.h>
|
||||
#include "fscrypt_private.h"
|
||||
|
||||
/**
|
||||
/*
|
||||
* struct fscrypt_nokey_name - identifier for directory entry when key is absent
|
||||
*
|
||||
* When userspace lists an encrypted directory without access to the key, the
|
||||
|
@ -100,8 +100,11 @@ static inline bool fscrypt_is_dot_dotdot(const struct qstr *str)
|
|||
|
||||
/**
|
||||
* fscrypt_fname_encrypt() - encrypt a filename
|
||||
*
|
||||
* The output buffer must be at least as large as the input buffer.
|
||||
* @inode: inode of the parent directory (for regular filenames)
|
||||
* or of the symlink (for symlink targets)
|
||||
* @iname: the filename to encrypt
|
||||
* @out: (output) the encrypted filename
|
||||
* @olen: size of the encrypted filename. It must be at least @iname->len.
|
||||
* Any extra space is filled with NUL padding before encryption.
|
||||
*
|
||||
* Return: 0 on success, -errno on failure
|
||||
|
@ -152,8 +155,11 @@ int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
|
|||
|
||||
/**
|
||||
* fname_decrypt() - decrypt a filename
|
||||
*
|
||||
* The caller must have allocated sufficient memory for the @oname string.
|
||||
* @inode: inode of the parent directory (for regular filenames)
|
||||
* or of the symlink (for symlink targets)
|
||||
* @iname: the encrypted filename to decrypt
|
||||
* @oname: (output) the decrypted filename. The caller must have allocated
|
||||
* enough space for this, e.g. using fscrypt_fname_alloc_buffer().
|
||||
*
|
||||
* Return: 0 on success, -errno on failure
|
||||
*/
|
||||
|
@ -201,7 +207,10 @@ static const char lookup_table[65] =
|
|||
#define BASE64_CHARS(nbytes) DIV_ROUND_UP((nbytes) * 4, 3)
|
||||
|
||||
/**
|
||||
* base64_encode() -
|
||||
* base64_encode() - base64-encode some bytes
|
||||
* @src: the bytes to encode
|
||||
* @len: number of bytes to encode
|
||||
* @dst: (output) the base64-encoded string. Not NUL-terminated.
|
||||
*
|
||||
* Encodes the input string using characters from the set [A-Za-z0-9+,].
|
||||
* The encoded string is roughly 4/3 times the size of the input string.
|
||||
|
@ -267,7 +276,12 @@ bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len,
|
|||
}
|
||||
|
||||
/**
|
||||
* fscrypt_fname_alloc_buffer - allocate a buffer for presented filenames
|
||||
* fscrypt_fname_alloc_buffer() - allocate a buffer for presented filenames
|
||||
* @inode: inode of the parent directory (for regular filenames)
|
||||
* or of the symlink (for symlink targets)
|
||||
* @max_encrypted_len: maximum length of encrypted filenames the buffer will be
|
||||
* used to present
|
||||
* @crypto_str: (output) buffer to allocate
|
||||
*
|
||||
* Allocate a buffer that is large enough to hold any decrypted or encoded
|
||||
* filename (null-terminated), for the given maximum encrypted filename length.
|
||||
|
@ -292,9 +306,10 @@ int fscrypt_fname_alloc_buffer(const struct inode *inode,
|
|||
EXPORT_SYMBOL(fscrypt_fname_alloc_buffer);
|
||||
|
||||
/**
|
||||
* fscrypt_fname_free_buffer - free the buffer for presented filenames
|
||||
* fscrypt_fname_free_buffer() - free a buffer for presented filenames
|
||||
* @crypto_str: the buffer to free
|
||||
*
|
||||
* Free the buffer allocated by fscrypt_fname_alloc_buffer().
|
||||
* Free a buffer that was allocated by fscrypt_fname_alloc_buffer().
|
||||
*/
|
||||
void fscrypt_fname_free_buffer(struct fscrypt_str *crypto_str)
|
||||
{
|
||||
|
@ -306,10 +321,19 @@ void fscrypt_fname_free_buffer(struct fscrypt_str *crypto_str)
|
|||
EXPORT_SYMBOL(fscrypt_fname_free_buffer);
|
||||
|
||||
/**
|
||||
* fscrypt_fname_disk_to_usr() - converts a filename from disk space to user
|
||||
* space
|
||||
*
|
||||
* The caller must have allocated sufficient memory for the @oname string.
|
||||
* fscrypt_fname_disk_to_usr() - convert an encrypted filename to
|
||||
* user-presentable form
|
||||
* @inode: inode of the parent directory (for regular filenames)
|
||||
* or of the symlink (for symlink targets)
|
||||
* @hash: first part of the name's dirhash, if applicable. This only needs to
|
||||
* be provided if the filename is located in an indexed directory whose
|
||||
* encryption key may be unavailable. Not needed for symlink targets.
|
||||
* @minor_hash: second part of the name's dirhash, if applicable
|
||||
* @iname: encrypted filename to convert. May also be "." or "..", which
|
||||
* aren't actually encrypted.
|
||||
* @oname: output buffer for the user-presentable filename. The caller must
|
||||
* have allocated enough space for this, e.g. using
|
||||
* fscrypt_fname_alloc_buffer().
|
||||
*
|
||||
* If the key is available, we'll decrypt the disk name. Otherwise, we'll
|
||||
* encode it for presentation in fscrypt_nokey_name format.
|
||||
|
|
|
@ -43,7 +43,7 @@ struct fscrypt_context_v2 {
|
|||
u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* fscrypt_context - the encryption context of an inode
|
||||
*
|
||||
* This is the on-disk equivalent of an fscrypt_policy, stored alongside each
|
||||
|
@ -157,7 +157,7 @@ fscrypt_policy_flags(const union fscrypt_policy *policy)
|
|||
BUG();
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* For encrypted symlinks, the ciphertext length is stored at the beginning
|
||||
* of the string in little-endian format.
|
||||
*/
|
||||
|
@ -222,6 +222,9 @@ struct fscrypt_info {
|
|||
|
||||
/* This inode's nonce, copied from the fscrypt_context */
|
||||
u8 ci_nonce[FS_KEY_DERIVATION_NONCE_SIZE];
|
||||
|
||||
/* Hashed inode number. Only set for IV_INO_LBLK_32 */
|
||||
u32 ci_hashed_ino;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
|
@ -231,15 +234,14 @@ typedef enum {
|
|||
|
||||
/* crypto.c */
|
||||
extern struct kmem_cache *fscrypt_info_cachep;
|
||||
extern int fscrypt_initialize(unsigned int cop_flags);
|
||||
extern int fscrypt_crypt_block(const struct inode *inode,
|
||||
fscrypt_direction_t rw, u64 lblk_num,
|
||||
struct page *src_page, struct page *dest_page,
|
||||
unsigned int len, unsigned int offs,
|
||||
gfp_t gfp_flags);
|
||||
extern struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags);
|
||||
int fscrypt_initialize(unsigned int cop_flags);
|
||||
int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw,
|
||||
u64 lblk_num, struct page *src_page,
|
||||
struct page *dest_page, unsigned int len,
|
||||
unsigned int offs, gfp_t gfp_flags);
|
||||
struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags);
|
||||
|
||||
extern void __printf(3, 4) __cold
|
||||
void __printf(3, 4) __cold
|
||||
fscrypt_msg(const struct inode *inode, const char *level, const char *fmt, ...);
|
||||
|
||||
#define fscrypt_warn(inode, fmt, ...) \
|
||||
|
@ -264,12 +266,10 @@ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num,
|
|||
const struct fscrypt_info *ci);
|
||||
|
||||
/* fname.c */
|
||||
extern int fscrypt_fname_encrypt(const struct inode *inode,
|
||||
const struct qstr *iname,
|
||||
int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
|
||||
u8 *out, unsigned int olen);
|
||||
extern bool fscrypt_fname_encrypted_size(const struct inode *inode,
|
||||
u32 orig_len, u32 max_len,
|
||||
u32 *encrypted_len_ret);
|
||||
bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len,
|
||||
u32 max_len, u32 *encrypted_len_ret);
|
||||
extern const struct dentry_operations fscrypt_d_ops;
|
||||
|
||||
/* hkdf.c */
|
||||
|
@ -278,7 +278,7 @@ struct fscrypt_hkdf {
|
|||
struct crypto_shash *hmac_tfm;
|
||||
};
|
||||
|
||||
extern int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key,
|
||||
int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key,
|
||||
unsigned int master_key_size);
|
||||
|
||||
/*
|
||||
|
@ -293,12 +293,14 @@ extern int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key,
|
|||
#define HKDF_CONTEXT_DIRECT_KEY 3
|
||||
#define HKDF_CONTEXT_IV_INO_LBLK_64_KEY 4
|
||||
#define HKDF_CONTEXT_DIRHASH_KEY 5
|
||||
#define HKDF_CONTEXT_IV_INO_LBLK_32_KEY 6
|
||||
#define HKDF_CONTEXT_INODE_HASH_KEY 7
|
||||
|
||||
extern int fscrypt_hkdf_expand(const struct fscrypt_hkdf *hkdf, u8 context,
|
||||
int fscrypt_hkdf_expand(const struct fscrypt_hkdf *hkdf, u8 context,
|
||||
const u8 *info, unsigned int infolen,
|
||||
u8 *okm, unsigned int okmlen);
|
||||
|
||||
extern void fscrypt_destroy_hkdf(struct fscrypt_hkdf *hkdf);
|
||||
void fscrypt_destroy_hkdf(struct fscrypt_hkdf *hkdf);
|
||||
|
||||
/* keyring.c */
|
||||
|
||||
|
@ -389,14 +391,17 @@ struct fscrypt_master_key {
|
|||
struct list_head mk_decrypted_inodes;
|
||||
spinlock_t mk_decrypted_inodes_lock;
|
||||
|
||||
/* Crypto API transforms for DIRECT_KEY policies, allocated on-demand */
|
||||
struct crypto_skcipher *mk_direct_tfms[__FSCRYPT_MODE_MAX + 1];
|
||||
|
||||
/*
|
||||
* Crypto API transforms for filesystem-layer implementation of
|
||||
* IV_INO_LBLK_64 policies, allocated on-demand.
|
||||
* Per-mode encryption keys for the various types of encryption policies
|
||||
* that use them. Allocated and derived on-demand.
|
||||
*/
|
||||
struct crypto_skcipher *mk_iv_ino_lblk_64_tfms[__FSCRYPT_MODE_MAX + 1];
|
||||
struct crypto_skcipher *mk_direct_keys[__FSCRYPT_MODE_MAX + 1];
|
||||
struct crypto_skcipher *mk_iv_ino_lblk_64_keys[__FSCRYPT_MODE_MAX + 1];
|
||||
struct crypto_skcipher *mk_iv_ino_lblk_32_keys[__FSCRYPT_MODE_MAX + 1];
|
||||
|
||||
/* Hash key for inode numbers. Initialized only when needed. */
|
||||
siphash_key_t mk_ino_hash_key;
|
||||
bool mk_ino_hash_key_initialized;
|
||||
|
||||
} __randomize_layout;
|
||||
|
||||
|
@ -436,14 +441,17 @@ static inline int master_key_spec_len(const struct fscrypt_key_specifier *spec)
|
|||
return 0;
|
||||
}
|
||||
|
||||
extern struct key *
|
||||
struct key *
|
||||
fscrypt_find_master_key(struct super_block *sb,
|
||||
const struct fscrypt_key_specifier *mk_spec);
|
||||
|
||||
extern int fscrypt_verify_key_added(struct super_block *sb,
|
||||
int fscrypt_add_test_dummy_key(struct super_block *sb,
|
||||
struct fscrypt_key_specifier *key_spec);
|
||||
|
||||
int fscrypt_verify_key_added(struct super_block *sb,
|
||||
const u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]);
|
||||
|
||||
extern int __init fscrypt_init_keyring(void);
|
||||
int __init fscrypt_init_keyring(void);
|
||||
|
||||
/* keysetup.c */
|
||||
|
||||
|
@ -457,32 +465,31 @@ struct fscrypt_mode {
|
|||
|
||||
extern struct fscrypt_mode fscrypt_modes[];
|
||||
|
||||
extern struct crypto_skcipher *
|
||||
fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key,
|
||||
struct crypto_skcipher *fscrypt_allocate_skcipher(struct fscrypt_mode *mode,
|
||||
const u8 *raw_key,
|
||||
const struct inode *inode);
|
||||
|
||||
extern int fscrypt_set_per_file_enc_key(struct fscrypt_info *ci,
|
||||
const u8 *raw_key);
|
||||
int fscrypt_set_per_file_enc_key(struct fscrypt_info *ci, const u8 *raw_key);
|
||||
|
||||
extern int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
|
||||
int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
|
||||
const struct fscrypt_master_key *mk);
|
||||
|
||||
/* keysetup_v1.c */
|
||||
|
||||
extern void fscrypt_put_direct_key(struct fscrypt_direct_key *dk);
|
||||
void fscrypt_put_direct_key(struct fscrypt_direct_key *dk);
|
||||
|
||||
extern int fscrypt_setup_v1_file_key(struct fscrypt_info *ci,
|
||||
int fscrypt_setup_v1_file_key(struct fscrypt_info *ci,
|
||||
const u8 *raw_master_key);
|
||||
|
||||
extern int fscrypt_setup_v1_file_key_via_subscribed_keyrings(
|
||||
struct fscrypt_info *ci);
|
||||
int fscrypt_setup_v1_file_key_via_subscribed_keyrings(struct fscrypt_info *ci);
|
||||
|
||||
/* policy.c */
|
||||
|
||||
extern bool fscrypt_policies_equal(const union fscrypt_policy *policy1,
|
||||
bool fscrypt_policies_equal(const union fscrypt_policy *policy1,
|
||||
const union fscrypt_policy *policy2);
|
||||
extern bool fscrypt_supported_policy(const union fscrypt_policy *policy_u,
|
||||
bool fscrypt_supported_policy(const union fscrypt_policy *policy_u,
|
||||
const struct inode *inode);
|
||||
extern int fscrypt_policy_from_context(union fscrypt_policy *policy_u,
|
||||
int fscrypt_policy_from_context(union fscrypt_policy *policy_u,
|
||||
const union fscrypt_context *ctx_u,
|
||||
int ctx_size);
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "fscrypt_private.h"
|
||||
|
||||
/**
|
||||
* fscrypt_file_open - prepare to open a possibly-encrypted regular file
|
||||
* fscrypt_file_open() - prepare to open a possibly-encrypted regular file
|
||||
* @inode: the inode being opened
|
||||
* @filp: the struct file being set up
|
||||
*
|
||||
|
@ -262,7 +262,7 @@ int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
|
|||
EXPORT_SYMBOL_GPL(__fscrypt_encrypt_symlink);
|
||||
|
||||
/**
|
||||
* fscrypt_get_symlink - get the target of an encrypted symlink
|
||||
* fscrypt_get_symlink() - get the target of an encrypted symlink
|
||||
* @inode: the symlink inode
|
||||
* @caddr: the on-disk contents of the symlink
|
||||
* @max_size: size of @caddr buffer
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include <crypto/skcipher.h>
|
||||
#include <linux/key-type.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#include "fscrypt_private.h"
|
||||
|
@ -44,8 +45,9 @@ static void free_master_key(struct fscrypt_master_key *mk)
|
|||
wipe_master_key_secret(&mk->mk_secret);
|
||||
|
||||
for (i = 0; i <= __FSCRYPT_MODE_MAX; i++) {
|
||||
crypto_free_skcipher(mk->mk_direct_tfms[i]);
|
||||
crypto_free_skcipher(mk->mk_iv_ino_lblk_64_tfms[i]);
|
||||
crypto_free_skcipher(mk->mk_direct_keys[i]);
|
||||
crypto_free_skcipher(mk->mk_iv_ino_lblk_64_keys[i]);
|
||||
crypto_free_skcipher(mk->mk_iv_ino_lblk_32_keys[i]);
|
||||
}
|
||||
|
||||
key_put(mk->mk_users);
|
||||
|
@ -424,7 +426,7 @@ static int add_existing_master_key(struct fscrypt_master_key *mk,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int add_master_key(struct super_block *sb,
|
||||
static int do_add_master_key(struct super_block *sb,
|
||||
struct fscrypt_master_key_secret *secret,
|
||||
const struct fscrypt_key_specifier *mk_spec)
|
||||
{
|
||||
|
@ -465,6 +467,35 @@ static int add_master_key(struct super_block *sb,
|
|||
return err;
|
||||
}
|
||||
|
||||
static int add_master_key(struct super_block *sb,
|
||||
struct fscrypt_master_key_secret *secret,
|
||||
struct fscrypt_key_specifier *key_spec)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (key_spec->type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) {
|
||||
err = fscrypt_init_hkdf(&secret->hkdf, secret->raw,
|
||||
secret->size);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/*
|
||||
* Now that the HKDF context is initialized, the raw key is no
|
||||
* longer needed.
|
||||
*/
|
||||
memzero_explicit(secret->raw, secret->size);
|
||||
|
||||
/* Calculate the key identifier */
|
||||
err = fscrypt_hkdf_expand(&secret->hkdf,
|
||||
HKDF_CONTEXT_KEY_IDENTIFIER, NULL, 0,
|
||||
key_spec->u.identifier,
|
||||
FSCRYPT_KEY_IDENTIFIER_SIZE);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
return do_add_master_key(sb, secret, key_spec);
|
||||
}
|
||||
|
||||
static int fscrypt_provisioning_key_preparse(struct key_preparsed_payload *prep)
|
||||
{
|
||||
const struct fscrypt_provisioning_key_payload *payload = prep->data;
|
||||
|
@ -609,6 +640,15 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg)
|
|||
if (memchr_inv(arg.__reserved, 0, sizeof(arg.__reserved)))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Only root can add keys that are identified by an arbitrary descriptor
|
||||
* rather than by a cryptographic hash --- since otherwise a malicious
|
||||
* user could add the wrong key.
|
||||
*/
|
||||
if (arg.key_spec.type == FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR &&
|
||||
!capable(CAP_SYS_ADMIN))
|
||||
return -EACCES;
|
||||
|
||||
memset(&secret, 0, sizeof(secret));
|
||||
if (arg.key_id) {
|
||||
if (arg.raw_size != 0)
|
||||
|
@ -626,54 +666,46 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg)
|
|||
goto out_wipe_secret;
|
||||
}
|
||||
|
||||
switch (arg.key_spec.type) {
|
||||
case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR:
|
||||
/*
|
||||
* Only root can add keys that are identified by an arbitrary
|
||||
* descriptor rather than by a cryptographic hash --- since
|
||||
* otherwise a malicious user could add the wrong key.
|
||||
*/
|
||||
err = -EACCES;
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
goto out_wipe_secret;
|
||||
break;
|
||||
case FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER:
|
||||
err = fscrypt_init_hkdf(&secret.hkdf, secret.raw, secret.size);
|
||||
err = add_master_key(sb, &secret, &arg.key_spec);
|
||||
if (err)
|
||||
goto out_wipe_secret;
|
||||
|
||||
/*
|
||||
* Now that the HKDF context is initialized, the raw key is no
|
||||
* longer needed.
|
||||
*/
|
||||
memzero_explicit(secret.raw, secret.size);
|
||||
|
||||
/* Calculate the key identifier and return it to userspace. */
|
||||
err = fscrypt_hkdf_expand(&secret.hkdf,
|
||||
HKDF_CONTEXT_KEY_IDENTIFIER,
|
||||
NULL, 0, arg.key_spec.u.identifier,
|
||||
FSCRYPT_KEY_IDENTIFIER_SIZE);
|
||||
if (err)
|
||||
goto out_wipe_secret;
|
||||
/* Return the key identifier to userspace, if applicable */
|
||||
err = -EFAULT;
|
||||
if (copy_to_user(uarg->key_spec.u.identifier,
|
||||
arg.key_spec.u.identifier,
|
||||
if (arg.key_spec.type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER &&
|
||||
copy_to_user(uarg->key_spec.u.identifier, arg.key_spec.u.identifier,
|
||||
FSCRYPT_KEY_IDENTIFIER_SIZE))
|
||||
goto out_wipe_secret;
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
err = -EINVAL;
|
||||
goto out_wipe_secret;
|
||||
}
|
||||
|
||||
err = add_master_key(sb, &secret, &arg.key_spec);
|
||||
err = 0;
|
||||
out_wipe_secret:
|
||||
wipe_master_key_secret(&secret);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fscrypt_ioctl_add_key);
|
||||
|
||||
/*
|
||||
* Add the key for '-o test_dummy_encryption' to the filesystem keyring.
|
||||
*
|
||||
* Use a per-boot random key to prevent people from misusing this option.
|
||||
*/
|
||||
int fscrypt_add_test_dummy_key(struct super_block *sb,
|
||||
struct fscrypt_key_specifier *key_spec)
|
||||
{
|
||||
static u8 test_key[FSCRYPT_MAX_KEY_SIZE];
|
||||
struct fscrypt_master_key_secret secret;
|
||||
int err;
|
||||
|
||||
get_random_once(test_key, FSCRYPT_MAX_KEY_SIZE);
|
||||
|
||||
memset(&secret, 0, sizeof(secret));
|
||||
secret.size = FSCRYPT_MAX_KEY_SIZE;
|
||||
memcpy(secret.raw, test_key, FSCRYPT_MAX_KEY_SIZE);
|
||||
|
||||
err = add_master_key(sb, &secret, key_spec);
|
||||
wipe_master_key_secret(&secret);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that the current user has added a master key with the given identifier
|
||||
* (returns -ENOKEY if not). This is needed to prevent a user from encrypting
|
||||
|
|
|
@ -46,6 +46,8 @@ struct fscrypt_mode fscrypt_modes[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(fscrypt_mode_key_setup_mutex);
|
||||
|
||||
static struct fscrypt_mode *
|
||||
select_encryption_mode(const union fscrypt_policy *policy,
|
||||
const struct inode *inode)
|
||||
|
@ -130,7 +132,7 @@ static int setup_per_mode_enc_key(struct fscrypt_info *ci,
|
|||
const struct super_block *sb = inode->i_sb;
|
||||
struct fscrypt_mode *mode = ci->ci_mode;
|
||||
const u8 mode_num = mode - fscrypt_modes;
|
||||
struct crypto_skcipher *tfm, *prev_tfm;
|
||||
struct crypto_skcipher *tfm;
|
||||
u8 mode_key[FSCRYPT_MAX_KEY_SIZE];
|
||||
u8 hkdf_info[sizeof(mode_num) + sizeof(sb->s_uuid)];
|
||||
unsigned int hkdf_infolen = 0;
|
||||
|
@ -139,10 +141,17 @@ static int setup_per_mode_enc_key(struct fscrypt_info *ci,
|
|||
if (WARN_ON(mode_num > __FSCRYPT_MODE_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
/* pairs with cmpxchg() below */
|
||||
/* pairs with smp_store_release() below */
|
||||
tfm = READ_ONCE(tfms[mode_num]);
|
||||
if (likely(tfm != NULL))
|
||||
goto done;
|
||||
if (likely(tfm != NULL)) {
|
||||
ci->ci_ctfm = tfm;
|
||||
return 0;
|
||||
}
|
||||
|
||||
mutex_lock(&fscrypt_mode_key_setup_mutex);
|
||||
|
||||
if (tfms[mode_num])
|
||||
goto done_unlock;
|
||||
|
||||
BUILD_BUG_ON(sizeof(mode_num) != 1);
|
||||
BUILD_BUG_ON(sizeof(sb->s_uuid) != 16);
|
||||
|
@ -157,21 +166,21 @@ static int setup_per_mode_enc_key(struct fscrypt_info *ci,
|
|||
hkdf_context, hkdf_info, hkdf_infolen,
|
||||
mode_key, mode->keysize);
|
||||
if (err)
|
||||
return err;
|
||||
goto out_unlock;
|
||||
tfm = fscrypt_allocate_skcipher(mode, mode_key, inode);
|
||||
memzero_explicit(mode_key, mode->keysize);
|
||||
if (IS_ERR(tfm))
|
||||
return PTR_ERR(tfm);
|
||||
|
||||
/* pairs with READ_ONCE() above */
|
||||
prev_tfm = cmpxchg(&tfms[mode_num], NULL, tfm);
|
||||
if (prev_tfm != NULL) {
|
||||
crypto_free_skcipher(tfm);
|
||||
tfm = prev_tfm;
|
||||
if (IS_ERR(tfm)) {
|
||||
err = PTR_ERR(tfm);
|
||||
goto out_unlock;
|
||||
}
|
||||
done:
|
||||
/* pairs with READ_ONCE() above */
|
||||
smp_store_release(&tfms[mode_num], tfm);
|
||||
done_unlock:
|
||||
ci->ci_ctfm = tfm;
|
||||
return 0;
|
||||
err = 0;
|
||||
out_unlock:
|
||||
mutex_unlock(&fscrypt_mode_key_setup_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
|
||||
|
@ -189,6 +198,43 @@ int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int fscrypt_setup_iv_ino_lblk_32_key(struct fscrypt_info *ci,
|
||||
struct fscrypt_master_key *mk)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = setup_per_mode_enc_key(ci, mk, mk->mk_iv_ino_lblk_32_keys,
|
||||
HKDF_CONTEXT_IV_INO_LBLK_32_KEY, true);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* pairs with smp_store_release() below */
|
||||
if (!smp_load_acquire(&mk->mk_ino_hash_key_initialized)) {
|
||||
|
||||
mutex_lock(&fscrypt_mode_key_setup_mutex);
|
||||
|
||||
if (mk->mk_ino_hash_key_initialized)
|
||||
goto unlock;
|
||||
|
||||
err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf,
|
||||
HKDF_CONTEXT_INODE_HASH_KEY, NULL, 0,
|
||||
(u8 *)&mk->mk_ino_hash_key,
|
||||
sizeof(mk->mk_ino_hash_key));
|
||||
if (err)
|
||||
goto unlock;
|
||||
/* pairs with smp_load_acquire() above */
|
||||
smp_store_release(&mk->mk_ino_hash_key_initialized, true);
|
||||
unlock:
|
||||
mutex_unlock(&fscrypt_mode_key_setup_mutex);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
ci->ci_hashed_ino = (u32)siphash_1u64(ci->ci_inode->i_ino,
|
||||
&mk->mk_ino_hash_key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci,
|
||||
struct fscrypt_master_key *mk)
|
||||
{
|
||||
|
@ -203,7 +249,7 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci,
|
|||
* encryption key. This ensures that the master key is
|
||||
* consistently used only for HKDF, avoiding key reuse issues.
|
||||
*/
|
||||
err = setup_per_mode_enc_key(ci, mk, mk->mk_direct_tfms,
|
||||
err = setup_per_mode_enc_key(ci, mk, mk->mk_direct_keys,
|
||||
HKDF_CONTEXT_DIRECT_KEY, false);
|
||||
} else if (ci->ci_policy.v2.flags &
|
||||
FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) {
|
||||
|
@ -211,11 +257,14 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci,
|
|||
* IV_INO_LBLK_64: encryption keys are derived from (master_key,
|
||||
* mode_num, filesystem_uuid), and inode number is included in
|
||||
* the IVs. This format is optimized for use with inline
|
||||
* encryption hardware compliant with the UFS or eMMC standards.
|
||||
* encryption hardware compliant with the UFS standard.
|
||||
*/
|
||||
err = setup_per_mode_enc_key(ci, mk, mk->mk_iv_ino_lblk_64_tfms,
|
||||
err = setup_per_mode_enc_key(ci, mk, mk->mk_iv_ino_lblk_64_keys,
|
||||
HKDF_CONTEXT_IV_INO_LBLK_64_KEY,
|
||||
true);
|
||||
} else if (ci->ci_policy.v2.flags &
|
||||
FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) {
|
||||
err = fscrypt_setup_iv_ino_lblk_32_key(ci, mk);
|
||||
} else {
|
||||
u8 derived_key[FSCRYPT_MAX_KEY_SIZE];
|
||||
|
||||
|
@ -395,21 +444,18 @@ int fscrypt_get_encryption_info(struct inode *inode)
|
|||
|
||||
res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx));
|
||||
if (res < 0) {
|
||||
if (!fscrypt_dummy_context_enabled(inode) ||
|
||||
IS_ENCRYPTED(inode)) {
|
||||
const union fscrypt_context *dummy_ctx =
|
||||
fscrypt_get_dummy_context(inode->i_sb);
|
||||
|
||||
if (IS_ENCRYPTED(inode) || !dummy_ctx) {
|
||||
fscrypt_warn(inode,
|
||||
"Error %d getting encryption context",
|
||||
res);
|
||||
return res;
|
||||
}
|
||||
/* Fake up a context for an unencrypted directory */
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
ctx.version = FSCRYPT_CONTEXT_V1;
|
||||
ctx.v1.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS;
|
||||
ctx.v1.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS;
|
||||
memset(ctx.v1.master_key_descriptor, 0x42,
|
||||
FSCRYPT_KEY_DESCRIPTOR_SIZE);
|
||||
res = sizeof(ctx.v1);
|
||||
res = fscrypt_context_size(dummy_ctx);
|
||||
memcpy(&ctx, dummy_ctx, res);
|
||||
}
|
||||
|
||||
crypt_info = kmem_cache_zalloc(fscrypt_info_cachep, GFP_NOFS);
|
||||
|
@ -475,7 +521,8 @@ int fscrypt_get_encryption_info(struct inode *inode)
|
|||
EXPORT_SYMBOL(fscrypt_get_encryption_info);
|
||||
|
||||
/**
|
||||
* fscrypt_put_encryption_info - free most of an inode's fscrypt data
|
||||
* fscrypt_put_encryption_info() - free most of an inode's fscrypt data
|
||||
* @inode: an inode being evicted
|
||||
*
|
||||
* Free the inode's fscrypt_info. Filesystems must call this when the inode is
|
||||
* being evicted. An RCU grace period need not have elapsed yet.
|
||||
|
@ -488,7 +535,8 @@ void fscrypt_put_encryption_info(struct inode *inode)
|
|||
EXPORT_SYMBOL(fscrypt_put_encryption_info);
|
||||
|
||||
/**
|
||||
* fscrypt_free_inode - free an inode's fscrypt data requiring RCU delay
|
||||
* fscrypt_free_inode() - free an inode's fscrypt data requiring RCU delay
|
||||
* @inode: an inode being freed
|
||||
*
|
||||
* Free the inode's cached decrypted symlink target, if any. Filesystems must
|
||||
* call this after an RCU grace period, just before they free the inode.
|
||||
|
@ -503,7 +551,8 @@ void fscrypt_free_inode(struct inode *inode)
|
|||
EXPORT_SYMBOL(fscrypt_free_inode);
|
||||
|
||||
/**
|
||||
* fscrypt_drop_inode - check whether the inode's master key has been removed
|
||||
* fscrypt_drop_inode() - check whether the inode's master key has been removed
|
||||
* @inode: an inode being considered for eviction
|
||||
*
|
||||
* Filesystems supporting fscrypt must call this from their ->drop_inode()
|
||||
* method so that encrypted inodes are evicted as soon as they're no longer in
|
||||
|
|
|
@ -11,12 +11,15 @@
|
|||
*/
|
||||
|
||||
#include <linux/random.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mount.h>
|
||||
#include "fscrypt_private.h"
|
||||
|
||||
/**
|
||||
* fscrypt_policies_equal - check whether two encryption policies are the same
|
||||
* fscrypt_policies_equal() - check whether two encryption policies are the same
|
||||
* @policy1: the first policy
|
||||
* @policy2: the second policy
|
||||
*
|
||||
* Return: %true if equal, else %false
|
||||
*/
|
||||
|
@ -66,18 +69,14 @@ static bool supported_direct_key_modes(const struct inode *inode,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool supported_iv_ino_lblk_64_policy(
|
||||
const struct fscrypt_policy_v2 *policy,
|
||||
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)
|
||||
{
|
||||
struct super_block *sb = inode->i_sb;
|
||||
int ino_bits = 64, lblk_bits = 64;
|
||||
|
||||
if (policy->flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) {
|
||||
fscrypt_warn(inode,
|
||||
"The DIRECT_KEY and IV_INO_LBLK_64 flags are mutually exclusive");
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* It's unsafe to include inode numbers in the IVs if the filesystem can
|
||||
* potentially renumber inodes, e.g. via filesystem shrinking.
|
||||
|
@ -85,16 +84,22 @@ static bool supported_iv_ino_lblk_64_policy(
|
|||
if (!sb->s_cop->has_stable_inodes ||
|
||||
!sb->s_cop->has_stable_inodes(sb)) {
|
||||
fscrypt_warn(inode,
|
||||
"Can't use IV_INO_LBLK_64 policy on filesystem '%s' because it doesn't have stable inode numbers",
|
||||
sb->s_id);
|
||||
"Can't use %s policy on filesystem '%s' because it doesn't have stable inode numbers",
|
||||
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 > 32 || lblk_bits > 32) {
|
||||
if (ino_bits > max_ino_bits) {
|
||||
fscrypt_warn(inode,
|
||||
"Can't use IV_INO_LBLK_64 policy on filesystem '%s' because it doesn't use 32-bit inode and block numbers",
|
||||
sb->s_id);
|
||||
"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) {
|
||||
fscrypt_warn(inode,
|
||||
"Can't use %s policy on filesystem '%s' because its block numbers are too long",
|
||||
type, sb->s_id);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -137,6 +142,8 @@ static bool fscrypt_supported_v1_policy(const struct fscrypt_policy_v1 *policy,
|
|||
static bool fscrypt_supported_v2_policy(const struct fscrypt_policy_v2 *policy,
|
||||
const struct inode *inode)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
if (!fscrypt_valid_enc_modes(policy->contents_encryption_mode,
|
||||
policy->filenames_encryption_mode)) {
|
||||
fscrypt_warn(inode,
|
||||
|
@ -152,13 +159,29 @@ static bool fscrypt_supported_v2_policy(const struct fscrypt_policy_v2 *policy,
|
|||
return false;
|
||||
}
|
||||
|
||||
count += !!(policy->flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY);
|
||||
count += !!(policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64);
|
||||
count += !!(policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32);
|
||||
if (count > 1) {
|
||||
fscrypt_warn(inode, "Mutually exclusive encryption flags (0x%02x)",
|
||||
policy->flags);
|
||||
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_64_policy(policy, inode))
|
||||
!supported_iv_ino_lblk_policy(policy, inode, "IV_INO_LBLK_64",
|
||||
32, 32))
|
||||
return false;
|
||||
|
||||
if ((policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) &&
|
||||
/* This uses hashed inode numbers, so ino_bits doesn't matter. */
|
||||
!supported_iv_ino_lblk_policy(policy, inode, "IV_INO_LBLK_32",
|
||||
INT_MAX, 32))
|
||||
return false;
|
||||
|
||||
if (memchr_inv(policy->__reserved, 0, sizeof(policy->__reserved))) {
|
||||
|
@ -170,7 +193,9 @@ static bool fscrypt_supported_v2_policy(const struct fscrypt_policy_v2 *policy,
|
|||
}
|
||||
|
||||
/**
|
||||
* fscrypt_supported_policy - check whether an encryption policy is supported
|
||||
* fscrypt_supported_policy() - check whether an encryption policy is supported
|
||||
* @policy_u: the encryption policy
|
||||
* @inode: the inode on which the policy will be used
|
||||
*
|
||||
* Given an encryption policy, check whether all its encryption modes and other
|
||||
* settings are supported by this kernel on the given inode. (But we don't
|
||||
|
@ -192,7 +217,10 @@ bool fscrypt_supported_policy(const union fscrypt_policy *policy_u,
|
|||
}
|
||||
|
||||
/**
|
||||
* fscrypt_new_context_from_policy - create a new fscrypt_context from a policy
|
||||
* fscrypt_new_context_from_policy() - create a new fscrypt_context from
|
||||
* an fscrypt_policy
|
||||
* @ctx_u: output context
|
||||
* @policy_u: input policy
|
||||
*
|
||||
* Create an fscrypt_context for an inode that is being assigned the given
|
||||
* encryption policy. A new nonce is randomly generated.
|
||||
|
@ -242,7 +270,11 @@ static int fscrypt_new_context_from_policy(union fscrypt_context *ctx_u,
|
|||
}
|
||||
|
||||
/**
|
||||
* fscrypt_policy_from_context - convert an fscrypt_context to an fscrypt_policy
|
||||
* fscrypt_policy_from_context() - convert an fscrypt_context to
|
||||
* an fscrypt_policy
|
||||
* @policy_u: output policy
|
||||
* @ctx_u: input context
|
||||
* @ctx_size: size of input context in bytes
|
||||
*
|
||||
* Given an fscrypt_context, build the corresponding fscrypt_policy.
|
||||
*
|
||||
|
@ -354,6 +386,9 @@ static int set_encryption_policy(struct inode *inode,
|
|||
policy->v2.master_key_identifier);
|
||||
if (err)
|
||||
return err;
|
||||
if (policy->v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)
|
||||
pr_warn_once("%s (pid %d) is setting an IV_INO_LBLK_32 encryption policy. This should only be used if there are certain hardware limitations.\n",
|
||||
current->comm, current->pid);
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
|
@ -605,3 +640,127 @@ int fscrypt_inherit_context(struct inode *parent, struct inode *child,
|
|||
return preload ? fscrypt_get_encryption_info(child): 0;
|
||||
}
|
||||
EXPORT_SYMBOL(fscrypt_inherit_context);
|
||||
|
||||
/**
|
||||
* fscrypt_set_test_dummy_encryption() - handle '-o test_dummy_encryption'
|
||||
* @sb: the filesystem on which test_dummy_encryption is being specified
|
||||
* @arg: the argument to the test_dummy_encryption option.
|
||||
* If no argument was specified, then @arg->from == NULL.
|
||||
* @dummy_ctx: the filesystem's current dummy context (input/output, see below)
|
||||
*
|
||||
* Handle the test_dummy_encryption mount option by creating a dummy encryption
|
||||
* context, saving it in @dummy_ctx, and adding the corresponding dummy
|
||||
* encryption key to the filesystem. If the @dummy_ctx is already set, then
|
||||
* instead validate that it matches @arg. Don't support changing it via
|
||||
* remount, as that is difficult to do safely.
|
||||
*
|
||||
* The reason we use an fscrypt_context rather than an fscrypt_policy is because
|
||||
* we mustn't generate a new nonce each time we access a dummy-encrypted
|
||||
* directory, as that would change the way filenames are encrypted.
|
||||
*
|
||||
* Return: 0 on success (dummy context set, or the same context is already set);
|
||||
* -EEXIST if a different dummy context is already set;
|
||||
* or another -errno value.
|
||||
*/
|
||||
int fscrypt_set_test_dummy_encryption(struct super_block *sb,
|
||||
const substring_t *arg,
|
||||
struct fscrypt_dummy_context *dummy_ctx)
|
||||
{
|
||||
const char *argstr = "v2";
|
||||
const char *argstr_to_free = NULL;
|
||||
struct fscrypt_key_specifier key_spec = { 0 };
|
||||
int version;
|
||||
union fscrypt_context *ctx = NULL;
|
||||
int err;
|
||||
|
||||
if (arg->from) {
|
||||
argstr = argstr_to_free = match_strdup(arg);
|
||||
if (!argstr)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (!strcmp(argstr, "v1")) {
|
||||
version = FSCRYPT_CONTEXT_V1;
|
||||
key_spec.type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR;
|
||||
memset(key_spec.u.descriptor, 0x42,
|
||||
FSCRYPT_KEY_DESCRIPTOR_SIZE);
|
||||
} else if (!strcmp(argstr, "v2")) {
|
||||
version = FSCRYPT_CONTEXT_V2;
|
||||
key_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
|
||||
/* key_spec.u.identifier gets filled in when adding the key */
|
||||
} else {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (dummy_ctx->ctx) {
|
||||
/*
|
||||
* Note: if we ever make test_dummy_encryption support
|
||||
* specifying other encryption settings, such as the encryption
|
||||
* modes, we'll need to compare those settings here.
|
||||
*/
|
||||
if (dummy_ctx->ctx->version == version)
|
||||
err = 0;
|
||||
else
|
||||
err = -EEXIST;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = fscrypt_add_test_dummy_key(sb, &key_spec);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
ctx->version = version;
|
||||
switch (ctx->version) {
|
||||
case FSCRYPT_CONTEXT_V1:
|
||||
ctx->v1.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS;
|
||||
ctx->v1.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS;
|
||||
memcpy(ctx->v1.master_key_descriptor, key_spec.u.descriptor,
|
||||
FSCRYPT_KEY_DESCRIPTOR_SIZE);
|
||||
break;
|
||||
case FSCRYPT_CONTEXT_V2:
|
||||
ctx->v2.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS;
|
||||
ctx->v2.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS;
|
||||
memcpy(ctx->v2.master_key_identifier, key_spec.u.identifier,
|
||||
FSCRYPT_KEY_IDENTIFIER_SIZE);
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
dummy_ctx->ctx = ctx;
|
||||
ctx = NULL;
|
||||
err = 0;
|
||||
out:
|
||||
kfree(ctx);
|
||||
kfree(argstr_to_free);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fscrypt_set_test_dummy_encryption);
|
||||
|
||||
/**
|
||||
* fscrypt_show_test_dummy_encryption() - show '-o test_dummy_encryption'
|
||||
* @seq: the seq_file to print the option to
|
||||
* @sep: the separator character to use
|
||||
* @sb: the filesystem whose options are being shown
|
||||
*
|
||||
* Show the test_dummy_encryption mount option, if it was specified.
|
||||
* This is mainly used for /proc/mounts.
|
||||
*/
|
||||
void fscrypt_show_test_dummy_encryption(struct seq_file *seq, char sep,
|
||||
struct super_block *sb)
|
||||
{
|
||||
const union fscrypt_context *ctx = fscrypt_get_dummy_context(sb);
|
||||
|
||||
if (!ctx)
|
||||
return;
|
||||
seq_printf(seq, "%ctest_dummy_encryption=v%d", sep, ctx->version);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fscrypt_show_test_dummy_encryption);
|
||||
|
|
|
@ -1357,11 +1357,9 @@ struct ext4_super_block {
|
|||
*/
|
||||
#define EXT4_MF_MNTDIR_SAMPLED 0x0001
|
||||
#define EXT4_MF_FS_ABORTED 0x0002 /* Fatal error detected */
|
||||
#define EXT4_MF_TEST_DUMMY_ENCRYPTION 0x0004
|
||||
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
#define DUMMY_ENCRYPTION_ENABLED(sbi) (unlikely((sbi)->s_mount_flags & \
|
||||
EXT4_MF_TEST_DUMMY_ENCRYPTION))
|
||||
#define DUMMY_ENCRYPTION_ENABLED(sbi) ((sbi)->s_dummy_enc_ctx.ctx != NULL)
|
||||
#else
|
||||
#define DUMMY_ENCRYPTION_ENABLED(sbi) (0)
|
||||
#endif
|
||||
|
@ -1551,6 +1549,9 @@ struct ext4_sb_info {
|
|||
struct ratelimit_state s_warning_ratelimit_state;
|
||||
struct ratelimit_state s_msg_ratelimit_state;
|
||||
|
||||
/* Encryption context for '-o test_dummy_encryption' */
|
||||
struct fscrypt_dummy_context s_dummy_enc_ctx;
|
||||
|
||||
/*
|
||||
* Barrier between writepages ops and changing any inode's JOURNAL_DATA
|
||||
* or EXTENTS flag.
|
||||
|
|
|
@ -1106,6 +1106,7 @@ static void ext4_put_super(struct super_block *sb)
|
|||
crypto_free_shash(sbi->s_chksum_driver);
|
||||
kfree(sbi->s_blockgroup_lock);
|
||||
fs_put_dax(sbi->s_daxdev);
|
||||
fscrypt_free_dummy_context(&sbi->s_dummy_enc_ctx);
|
||||
#ifdef CONFIG_UNICODE
|
||||
utf8_unload(sbi->s_encoding);
|
||||
#endif
|
||||
|
@ -1389,9 +1390,10 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
|
|||
return res;
|
||||
}
|
||||
|
||||
static bool ext4_dummy_context(struct inode *inode)
|
||||
static const union fscrypt_context *
|
||||
ext4_get_dummy_context(struct super_block *sb)
|
||||
{
|
||||
return DUMMY_ENCRYPTION_ENABLED(EXT4_SB(inode->i_sb));
|
||||
return EXT4_SB(sb)->s_dummy_enc_ctx.ctx;
|
||||
}
|
||||
|
||||
static bool ext4_has_stable_inodes(struct super_block *sb)
|
||||
|
@ -1410,7 +1412,7 @@ static const struct fscrypt_operations ext4_cryptops = {
|
|||
.key_prefix = "ext4:",
|
||||
.get_context = ext4_get_context,
|
||||
.set_context = ext4_set_context,
|
||||
.dummy_context = ext4_dummy_context,
|
||||
.get_dummy_context = ext4_get_dummy_context,
|
||||
.empty_dir = ext4_empty_dir,
|
||||
.max_namelen = EXT4_NAME_LEN,
|
||||
.has_stable_inodes = ext4_has_stable_inodes,
|
||||
|
@ -1605,6 +1607,7 @@ static const match_table_t tokens = {
|
|||
{Opt_init_itable, "init_itable"},
|
||||
{Opt_noinit_itable, "noinit_itable"},
|
||||
{Opt_max_dir_size_kb, "max_dir_size_kb=%u"},
|
||||
{Opt_test_dummy_encryption, "test_dummy_encryption=%s"},
|
||||
{Opt_test_dummy_encryption, "test_dummy_encryption"},
|
||||
{Opt_nombcache, "nombcache"},
|
||||
{Opt_nombcache, "no_mbcache"}, /* for backward compatibility */
|
||||
|
@ -1816,7 +1819,7 @@ static const struct mount_opts {
|
|||
{Opt_jqfmt_vfsv0, QFMT_VFS_V0, MOPT_QFMT},
|
||||
{Opt_jqfmt_vfsv1, QFMT_VFS_V1, MOPT_QFMT},
|
||||
{Opt_max_dir_size_kb, 0, MOPT_GTE0},
|
||||
{Opt_test_dummy_encryption, 0, MOPT_GTE0},
|
||||
{Opt_test_dummy_encryption, 0, MOPT_STRING},
|
||||
{Opt_nombcache, EXT4_MOUNT_NO_MBCACHE, MOPT_SET},
|
||||
{Opt_err, 0, 0}
|
||||
};
|
||||
|
@ -1851,6 +1854,48 @@ static int ext4_sb_read_encoding(const struct ext4_super_block *es,
|
|||
}
|
||||
#endif
|
||||
|
||||
static int ext4_set_test_dummy_encryption(struct super_block *sb,
|
||||
const char *opt,
|
||||
const substring_t *arg,
|
||||
bool is_remount)
|
||||
{
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||
int err;
|
||||
|
||||
/*
|
||||
* This mount option is just for testing, and it's not worthwhile to
|
||||
* implement the extra complexity (e.g. RCU protection) that would be
|
||||
* needed to allow it to be set or changed during remount. We do allow
|
||||
* it to be specified during remount, but only if there is no change.
|
||||
*/
|
||||
if (is_remount && !sbi->s_dummy_enc_ctx.ctx) {
|
||||
ext4_msg(sb, KERN_WARNING,
|
||||
"Can't set test_dummy_encryption on remount");
|
||||
return -1;
|
||||
}
|
||||
err = fscrypt_set_test_dummy_encryption(sb, arg, &sbi->s_dummy_enc_ctx);
|
||||
if (err) {
|
||||
if (err == -EEXIST)
|
||||
ext4_msg(sb, KERN_WARNING,
|
||||
"Can't change test_dummy_encryption on remount");
|
||||
else if (err == -EINVAL)
|
||||
ext4_msg(sb, KERN_WARNING,
|
||||
"Value of option \"%s\" is unrecognized", opt);
|
||||
else
|
||||
ext4_msg(sb, KERN_WARNING,
|
||||
"Error processing option \"%s\" [%d]",
|
||||
opt, err);
|
||||
return -1;
|
||||
}
|
||||
ext4_msg(sb, KERN_WARNING, "Test dummy encryption mode enabled");
|
||||
#else
|
||||
ext4_msg(sb, KERN_WARNING,
|
||||
"Test dummy encryption mount option ignored");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int handle_mount_opt(struct super_block *sb, char *opt, int token,
|
||||
substring_t *args, unsigned long *journal_devnum,
|
||||
unsigned int *journal_ioprio, int is_remount)
|
||||
|
@ -2047,14 +2092,8 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
|
|||
*journal_ioprio =
|
||||
IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, arg);
|
||||
} else if (token == Opt_test_dummy_encryption) {
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
sbi->s_mount_flags |= EXT4_MF_TEST_DUMMY_ENCRYPTION;
|
||||
ext4_msg(sb, KERN_WARNING,
|
||||
"Test dummy encryption mode enabled");
|
||||
#else
|
||||
ext4_msg(sb, KERN_WARNING,
|
||||
"Test dummy encryption mount option ignored");
|
||||
#endif
|
||||
return ext4_set_test_dummy_encryption(sb, opt, &args[0],
|
||||
is_remount);
|
||||
} else if (m->flags & MOPT_DATAJ) {
|
||||
if (is_remount) {
|
||||
if (!sbi->s_journal)
|
||||
|
@ -2311,8 +2350,8 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
|
|||
SEQ_OPTS_PRINT("max_dir_size_kb=%u", sbi->s_max_dir_size_kb);
|
||||
if (test_opt(sb, DATA_ERR_ABORT))
|
||||
SEQ_OPTS_PUTS("data_err=abort");
|
||||
if (DUMMY_ENCRYPTION_ENABLED(sbi))
|
||||
SEQ_OPTS_PUTS("test_dummy_encryption");
|
||||
|
||||
fscrypt_show_test_dummy_encryption(seq, sep, sb);
|
||||
|
||||
ext4_show_quota_options(seq, sb);
|
||||
return 0;
|
||||
|
@ -4780,6 +4819,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|||
for (i = 0; i < EXT4_MAXQUOTAS; i++)
|
||||
kfree(get_qf_name(sb, sbi, i));
|
||||
#endif
|
||||
fscrypt_free_dummy_context(&sbi->s_dummy_enc_ctx);
|
||||
ext4_blkdev_remove(sbi);
|
||||
brelse(bh);
|
||||
out_fail:
|
||||
|
|
|
@ -293,6 +293,7 @@ EXT4_ATTR_FEATURE(batched_discard);
|
|||
EXT4_ATTR_FEATURE(meta_bg_resize);
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
EXT4_ATTR_FEATURE(encryption);
|
||||
EXT4_ATTR_FEATURE(test_dummy_encryption_v2);
|
||||
#endif
|
||||
#ifdef CONFIG_UNICODE
|
||||
EXT4_ATTR_FEATURE(casefold);
|
||||
|
@ -308,6 +309,7 @@ static struct attribute *ext4_feat_attrs[] = {
|
|||
ATTR_LIST(meta_bg_resize),
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
ATTR_LIST(encryption),
|
||||
ATTR_LIST(test_dummy_encryption_v2),
|
||||
#endif
|
||||
#ifdef CONFIG_UNICODE
|
||||
ATTR_LIST(casefold),
|
||||
|
|
|
@ -138,7 +138,7 @@ struct f2fs_mount_info {
|
|||
int fsync_mode; /* fsync policy */
|
||||
int fs_mode; /* fs mode: LFS or ADAPTIVE */
|
||||
int bggc_mode; /* bggc mode: off, on or sync */
|
||||
bool test_dummy_encryption; /* test dummy encryption */
|
||||
struct fscrypt_dummy_context dummy_enc_ctx; /* test dummy encryption */
|
||||
block_t unusable_cap; /* Amount of space allowed to be
|
||||
* unusable when disabling checkpoint
|
||||
*/
|
||||
|
@ -1259,7 +1259,7 @@ enum fsync_mode {
|
|||
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
#define DUMMY_ENCRYPTION_ENABLED(sbi) \
|
||||
(unlikely(F2FS_OPTION(sbi).test_dummy_encryption))
|
||||
(unlikely(F2FS_OPTION(sbi).dummy_enc_ctx.ctx != NULL))
|
||||
#else
|
||||
#define DUMMY_ENCRYPTION_ENABLED(sbi) (0)
|
||||
#endif
|
||||
|
|
|
@ -202,6 +202,7 @@ static match_table_t f2fs_tokens = {
|
|||
{Opt_whint, "whint_mode=%s"},
|
||||
{Opt_alloc, "alloc_mode=%s"},
|
||||
{Opt_fsync, "fsync_mode=%s"},
|
||||
{Opt_test_dummy_encryption, "test_dummy_encryption=%s"},
|
||||
{Opt_test_dummy_encryption, "test_dummy_encryption"},
|
||||
{Opt_checkpoint_disable, "checkpoint=disable"},
|
||||
{Opt_checkpoint_disable_cap, "checkpoint=disable:%u"},
|
||||
|
@ -394,7 +395,52 @@ static int f2fs_check_quota_options(struct f2fs_sb_info *sbi)
|
|||
}
|
||||
#endif
|
||||
|
||||
static int parse_options(struct super_block *sb, char *options)
|
||||
static int f2fs_set_test_dummy_encryption(struct super_block *sb,
|
||||
const char *opt,
|
||||
const substring_t *arg,
|
||||
bool is_remount)
|
||||
{
|
||||
struct f2fs_sb_info *sbi = F2FS_SB(sb);
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
int err;
|
||||
|
||||
if (!f2fs_sb_has_encrypt(sbi)) {
|
||||
f2fs_err(sbi, "Encrypt feature is off");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This mount option is just for testing, and it's not worthwhile to
|
||||
* implement the extra complexity (e.g. RCU protection) that would be
|
||||
* needed to allow it to be set or changed during remount. We do allow
|
||||
* it to be specified during remount, but only if there is no change.
|
||||
*/
|
||||
if (is_remount && !F2FS_OPTION(sbi).dummy_enc_ctx.ctx) {
|
||||
f2fs_warn(sbi, "Can't set test_dummy_encryption on remount");
|
||||
return -EINVAL;
|
||||
}
|
||||
err = fscrypt_set_test_dummy_encryption(
|
||||
sb, arg, &F2FS_OPTION(sbi).dummy_enc_ctx);
|
||||
if (err) {
|
||||
if (err == -EEXIST)
|
||||
f2fs_warn(sbi,
|
||||
"Can't change test_dummy_encryption on remount");
|
||||
else if (err == -EINVAL)
|
||||
f2fs_warn(sbi, "Value of option \"%s\" is unrecognized",
|
||||
opt);
|
||||
else
|
||||
f2fs_warn(sbi, "Error processing option \"%s\" [%d]",
|
||||
opt, err);
|
||||
return -EINVAL;
|
||||
}
|
||||
f2fs_warn(sbi, "Test dummy encryption mode enabled");
|
||||
#else
|
||||
f2fs_warn(sbi, "Test dummy encryption mount option ignored");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_options(struct super_block *sb, char *options, bool is_remount)
|
||||
{
|
||||
struct f2fs_sb_info *sbi = F2FS_SB(sb);
|
||||
substring_t args[MAX_OPT_ARGS];
|
||||
|
@ -403,9 +449,7 @@ static int parse_options(struct super_block *sb, char *options)
|
|||
int arg = 0, ext_cnt;
|
||||
kuid_t uid;
|
||||
kgid_t gid;
|
||||
#ifdef CONFIG_QUOTA
|
||||
int ret;
|
||||
#endif
|
||||
|
||||
if (!options)
|
||||
return 0;
|
||||
|
@ -778,17 +822,10 @@ static int parse_options(struct super_block *sb, char *options)
|
|||
kvfree(name);
|
||||
break;
|
||||
case Opt_test_dummy_encryption:
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
if (!f2fs_sb_has_encrypt(sbi)) {
|
||||
f2fs_err(sbi, "Encrypt feature is off");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
F2FS_OPTION(sbi).test_dummy_encryption = true;
|
||||
f2fs_info(sbi, "Test dummy encryption mode enabled");
|
||||
#else
|
||||
f2fs_info(sbi, "Test dummy encryption mount option ignored");
|
||||
#endif
|
||||
ret = f2fs_set_test_dummy_encryption(sb, p, &args[0],
|
||||
is_remount);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case Opt_checkpoint_disable_cap_perc:
|
||||
if (args->from && match_int(args, &arg))
|
||||
|
@ -1213,6 +1250,7 @@ static void f2fs_put_super(struct super_block *sb)
|
|||
for (i = 0; i < MAXQUOTAS; i++)
|
||||
kvfree(F2FS_OPTION(sbi).s_qf_names[i]);
|
||||
#endif
|
||||
fscrypt_free_dummy_context(&F2FS_OPTION(sbi).dummy_enc_ctx);
|
||||
destroy_percpu_info(sbi);
|
||||
for (i = 0; i < NR_PAGE_TYPE; i++)
|
||||
kvfree(sbi->write_io[i]);
|
||||
|
@ -1543,10 +1581,8 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
|
|||
seq_printf(seq, ",whint_mode=%s", "user-based");
|
||||
else if (F2FS_OPTION(sbi).whint_mode == WHINT_MODE_FS)
|
||||
seq_printf(seq, ",whint_mode=%s", "fs-based");
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
if (F2FS_OPTION(sbi).test_dummy_encryption)
|
||||
seq_puts(seq, ",test_dummy_encryption");
|
||||
#endif
|
||||
|
||||
fscrypt_show_test_dummy_encryption(seq, ',', sbi->sb);
|
||||
|
||||
if (F2FS_OPTION(sbi).alloc_mode == ALLOC_MODE_DEFAULT)
|
||||
seq_printf(seq, ",alloc_mode=%s", "default");
|
||||
|
@ -1575,7 +1611,6 @@ static void default_options(struct f2fs_sb_info *sbi)
|
|||
F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
|
||||
F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
|
||||
F2FS_OPTION(sbi).fsync_mode = FSYNC_MODE_POSIX;
|
||||
F2FS_OPTION(sbi).test_dummy_encryption = false;
|
||||
F2FS_OPTION(sbi).s_resuid = make_kuid(&init_user_ns, F2FS_DEF_RESUID);
|
||||
F2FS_OPTION(sbi).s_resgid = make_kgid(&init_user_ns, F2FS_DEF_RESGID);
|
||||
F2FS_OPTION(sbi).compress_algorithm = COMPRESS_LZ4;
|
||||
|
@ -1734,7 +1769,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
|
|||
default_options(sbi);
|
||||
|
||||
/* parse mount options */
|
||||
err = parse_options(sb, data);
|
||||
err = parse_options(sb, data, true);
|
||||
if (err)
|
||||
goto restore_opts;
|
||||
checkpoint_changed =
|
||||
|
@ -2410,9 +2445,10 @@ static int f2fs_set_context(struct inode *inode, const void *ctx, size_t len,
|
|||
ctx, len, fs_data, XATTR_CREATE);
|
||||
}
|
||||
|
||||
static bool f2fs_dummy_context(struct inode *inode)
|
||||
static const union fscrypt_context *
|
||||
f2fs_get_dummy_context(struct super_block *sb)
|
||||
{
|
||||
return DUMMY_ENCRYPTION_ENABLED(F2FS_I_SB(inode));
|
||||
return F2FS_OPTION(F2FS_SB(sb)).dummy_enc_ctx.ctx;
|
||||
}
|
||||
|
||||
static bool f2fs_has_stable_inodes(struct super_block *sb)
|
||||
|
@ -2431,7 +2467,7 @@ static const struct fscrypt_operations f2fs_cryptops = {
|
|||
.key_prefix = "f2fs:",
|
||||
.get_context = f2fs_get_context,
|
||||
.set_context = f2fs_set_context,
|
||||
.dummy_context = f2fs_dummy_context,
|
||||
.get_dummy_context = f2fs_get_dummy_context,
|
||||
.empty_dir = f2fs_empty_dir,
|
||||
.max_namelen = F2FS_NAME_LEN,
|
||||
.has_stable_inodes = f2fs_has_stable_inodes,
|
||||
|
@ -3366,7 +3402,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
|
|||
goto free_sb_buf;
|
||||
}
|
||||
|
||||
err = parse_options(sb, options);
|
||||
err = parse_options(sb, options, false);
|
||||
if (err)
|
||||
goto free_options;
|
||||
|
||||
|
@ -3769,6 +3805,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
|
|||
for (i = 0; i < MAXQUOTAS; i++)
|
||||
kvfree(F2FS_OPTION(sbi).s_qf_names[i]);
|
||||
#endif
|
||||
fscrypt_free_dummy_context(&F2FS_OPTION(sbi).dummy_enc_ctx);
|
||||
kvfree(options);
|
||||
free_sb_buf:
|
||||
kvfree(raw_super);
|
||||
|
|
|
@ -446,6 +446,7 @@ enum feat_id {
|
|||
FEAT_SB_CHECKSUM,
|
||||
FEAT_CASEFOLD,
|
||||
FEAT_COMPRESSION,
|
||||
FEAT_TEST_DUMMY_ENCRYPTION_V2,
|
||||
};
|
||||
|
||||
static ssize_t f2fs_feature_show(struct f2fs_attr *a,
|
||||
|
@ -466,6 +467,7 @@ static ssize_t f2fs_feature_show(struct f2fs_attr *a,
|
|||
case FEAT_SB_CHECKSUM:
|
||||
case FEAT_CASEFOLD:
|
||||
case FEAT_COMPRESSION:
|
||||
case FEAT_TEST_DUMMY_ENCRYPTION_V2:
|
||||
return sprintf(buf, "supported\n");
|
||||
}
|
||||
return 0;
|
||||
|
@ -563,6 +565,7 @@ F2FS_GENERAL_RO_ATTR(avg_vblocks);
|
|||
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
F2FS_FEATURE_RO_ATTR(encryption, FEAT_CRYPTO);
|
||||
F2FS_FEATURE_RO_ATTR(test_dummy_encryption_v2, FEAT_TEST_DUMMY_ENCRYPTION_V2);
|
||||
#endif
|
||||
#ifdef CONFIG_BLK_DEV_ZONED
|
||||
F2FS_FEATURE_RO_ATTR(block_zoned, FEAT_BLKZONED);
|
||||
|
@ -647,6 +650,7 @@ ATTRIBUTE_GROUPS(f2fs);
|
|||
static struct attribute *f2fs_feat_attrs[] = {
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
ATTR_LIST(encryption),
|
||||
ATTR_LIST(test_dummy_encryption_v2),
|
||||
#endif
|
||||
#ifdef CONFIG_BLK_DEV_ZONED
|
||||
ATTR_LIST(block_zoned),
|
||||
|
|
|
@ -15,12 +15,15 @@
|
|||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/parser.h>
|
||||
#include <linux/slab.h>
|
||||
#include <uapi/linux/fscrypt.h>
|
||||
|
||||
#define FS_CRYPTO_BLOCK_SIZE 16
|
||||
|
||||
union fscrypt_context;
|
||||
struct fscrypt_info;
|
||||
struct seq_file;
|
||||
|
||||
struct fscrypt_str {
|
||||
unsigned char *name;
|
||||
|
@ -56,10 +59,12 @@ struct fscrypt_name {
|
|||
struct fscrypt_operations {
|
||||
unsigned int flags;
|
||||
const char *key_prefix;
|
||||
int (*get_context)(struct inode *, void *, size_t);
|
||||
int (*set_context)(struct inode *, const void *, size_t, void *);
|
||||
bool (*dummy_context)(struct inode *);
|
||||
bool (*empty_dir)(struct inode *);
|
||||
int (*get_context)(struct inode *inode, void *ctx, size_t len);
|
||||
int (*set_context)(struct inode *inode, const void *ctx, size_t len,
|
||||
void *fs_data);
|
||||
const union fscrypt_context *(*get_dummy_context)(
|
||||
struct super_block *sb);
|
||||
bool (*empty_dir)(struct inode *inode);
|
||||
unsigned int max_namelen;
|
||||
bool (*has_stable_inodes)(struct super_block *sb);
|
||||
void (*get_ino_and_lblk_bits)(struct super_block *sb,
|
||||
|
@ -75,6 +80,7 @@ static inline bool fscrypt_has_encryption_key(const struct inode *inode)
|
|||
/**
|
||||
* fscrypt_needs_contents_encryption() - check whether an inode needs
|
||||
* contents encryption
|
||||
* @inode: the inode to check
|
||||
*
|
||||
* Return: %true iff the inode is an encrypted regular file and the kernel was
|
||||
* built with fscrypt support.
|
||||
|
@ -87,10 +93,12 @@ static inline bool fscrypt_needs_contents_encryption(const struct inode *inode)
|
|||
return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode);
|
||||
}
|
||||
|
||||
static inline bool fscrypt_dummy_context_enabled(struct inode *inode)
|
||||
static inline const union fscrypt_context *
|
||||
fscrypt_get_dummy_context(struct super_block *sb)
|
||||
{
|
||||
return inode->i_sb->s_cop->dummy_context &&
|
||||
inode->i_sb->s_cop->dummy_context(inode);
|
||||
if (!sb->s_cop->get_dummy_context)
|
||||
return NULL;
|
||||
return sb->s_cop->get_dummy_context(sb);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -106,22 +114,21 @@ static inline void fscrypt_handle_d_move(struct dentry *dentry)
|
|||
}
|
||||
|
||||
/* crypto.c */
|
||||
extern void fscrypt_enqueue_decrypt_work(struct work_struct *);
|
||||
void fscrypt_enqueue_decrypt_work(struct work_struct *);
|
||||
|
||||
extern struct page *fscrypt_encrypt_pagecache_blocks(struct page *page,
|
||||
struct page *fscrypt_encrypt_pagecache_blocks(struct page *page,
|
||||
unsigned int len,
|
||||
unsigned int offs,
|
||||
gfp_t gfp_flags);
|
||||
extern int fscrypt_encrypt_block_inplace(const struct inode *inode,
|
||||
struct page *page, unsigned int len,
|
||||
unsigned int offs, u64 lblk_num,
|
||||
gfp_t gfp_flags);
|
||||
int fscrypt_encrypt_block_inplace(const struct inode *inode, struct page *page,
|
||||
unsigned int len, unsigned int offs,
|
||||
u64 lblk_num, gfp_t gfp_flags);
|
||||
|
||||
extern int fscrypt_decrypt_pagecache_blocks(struct page *page, unsigned int len,
|
||||
int fscrypt_decrypt_pagecache_blocks(struct page *page, unsigned int len,
|
||||
unsigned int offs);
|
||||
extern int fscrypt_decrypt_block_inplace(const struct inode *inode,
|
||||
struct page *page, unsigned int len,
|
||||
unsigned int offs, u64 lblk_num);
|
||||
int fscrypt_decrypt_block_inplace(const struct inode *inode, struct page *page,
|
||||
unsigned int len, unsigned int offs,
|
||||
u64 lblk_num);
|
||||
|
||||
static inline bool fscrypt_is_bounce_page(struct page *page)
|
||||
{
|
||||
|
@ -133,76 +140,88 @@ static inline struct page *fscrypt_pagecache_page(struct page *bounce_page)
|
|||
return (struct page *)page_private(bounce_page);
|
||||
}
|
||||
|
||||
extern void fscrypt_free_bounce_page(struct page *bounce_page);
|
||||
void fscrypt_free_bounce_page(struct page *bounce_page);
|
||||
|
||||
/* policy.c */
|
||||
extern int fscrypt_ioctl_set_policy(struct file *, const void __user *);
|
||||
extern int fscrypt_ioctl_get_policy(struct file *, void __user *);
|
||||
extern int fscrypt_ioctl_get_policy_ex(struct file *, void __user *);
|
||||
extern int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg);
|
||||
extern int fscrypt_has_permitted_context(struct inode *, struct inode *);
|
||||
extern int fscrypt_inherit_context(struct inode *, struct inode *,
|
||||
void *, bool);
|
||||
int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg);
|
||||
int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg);
|
||||
int fscrypt_ioctl_get_policy_ex(struct file *filp, void __user *arg);
|
||||
int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg);
|
||||
int fscrypt_has_permitted_context(struct inode *parent, struct inode *child);
|
||||
int fscrypt_inherit_context(struct inode *parent, struct inode *child,
|
||||
void *fs_data, bool preload);
|
||||
|
||||
struct fscrypt_dummy_context {
|
||||
const union fscrypt_context *ctx;
|
||||
};
|
||||
|
||||
int fscrypt_set_test_dummy_encryption(struct super_block *sb,
|
||||
const substring_t *arg,
|
||||
struct fscrypt_dummy_context *dummy_ctx);
|
||||
void fscrypt_show_test_dummy_encryption(struct seq_file *seq, char sep,
|
||||
struct super_block *sb);
|
||||
static inline void
|
||||
fscrypt_free_dummy_context(struct fscrypt_dummy_context *dummy_ctx)
|
||||
{
|
||||
kfree(dummy_ctx->ctx);
|
||||
dummy_ctx->ctx = NULL;
|
||||
}
|
||||
|
||||
/* keyring.c */
|
||||
extern void fscrypt_sb_free(struct super_block *sb);
|
||||
extern int fscrypt_ioctl_add_key(struct file *filp, void __user *arg);
|
||||
extern int fscrypt_ioctl_remove_key(struct file *filp, void __user *arg);
|
||||
extern int fscrypt_ioctl_remove_key_all_users(struct file *filp,
|
||||
void __user *arg);
|
||||
extern int fscrypt_ioctl_get_key_status(struct file *filp, void __user *arg);
|
||||
void fscrypt_sb_free(struct super_block *sb);
|
||||
int fscrypt_ioctl_add_key(struct file *filp, void __user *arg);
|
||||
int fscrypt_ioctl_remove_key(struct file *filp, void __user *arg);
|
||||
int fscrypt_ioctl_remove_key_all_users(struct file *filp, void __user *arg);
|
||||
int fscrypt_ioctl_get_key_status(struct file *filp, void __user *arg);
|
||||
|
||||
/* keysetup.c */
|
||||
extern int fscrypt_get_encryption_info(struct inode *);
|
||||
extern void fscrypt_put_encryption_info(struct inode *);
|
||||
extern void fscrypt_free_inode(struct inode *);
|
||||
extern int fscrypt_drop_inode(struct inode *inode);
|
||||
int fscrypt_get_encryption_info(struct inode *inode);
|
||||
void fscrypt_put_encryption_info(struct inode *inode);
|
||||
void fscrypt_free_inode(struct inode *inode);
|
||||
int fscrypt_drop_inode(struct inode *inode);
|
||||
|
||||
/* fname.c */
|
||||
extern int fscrypt_setup_filename(struct inode *, const struct qstr *,
|
||||
int lookup, struct fscrypt_name *);
|
||||
int fscrypt_setup_filename(struct inode *inode, const struct qstr *iname,
|
||||
int lookup, struct fscrypt_name *fname);
|
||||
|
||||
static inline void fscrypt_free_filename(struct fscrypt_name *fname)
|
||||
{
|
||||
kfree(fname->crypto_buf.name);
|
||||
}
|
||||
|
||||
extern int fscrypt_fname_alloc_buffer(const struct inode *, u32,
|
||||
struct fscrypt_str *);
|
||||
extern void fscrypt_fname_free_buffer(struct fscrypt_str *);
|
||||
extern int fscrypt_fname_disk_to_usr(const struct inode *inode,
|
||||
int fscrypt_fname_alloc_buffer(const struct inode *inode, u32 max_encrypted_len,
|
||||
struct fscrypt_str *crypto_str);
|
||||
void fscrypt_fname_free_buffer(struct fscrypt_str *crypto_str);
|
||||
int fscrypt_fname_disk_to_usr(const struct inode *inode,
|
||||
u32 hash, u32 minor_hash,
|
||||
const struct fscrypt_str *iname,
|
||||
struct fscrypt_str *oname);
|
||||
extern bool fscrypt_match_name(const struct fscrypt_name *fname,
|
||||
bool fscrypt_match_name(const struct fscrypt_name *fname,
|
||||
const u8 *de_name, u32 de_name_len);
|
||||
extern u64 fscrypt_fname_siphash(const struct inode *dir,
|
||||
const struct qstr *name);
|
||||
u64 fscrypt_fname_siphash(const struct inode *dir, const struct qstr *name);
|
||||
|
||||
/* bio.c */
|
||||
extern void fscrypt_decrypt_bio(struct bio *);
|
||||
extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t,
|
||||
unsigned int);
|
||||
void fscrypt_decrypt_bio(struct bio *bio);
|
||||
int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
|
||||
sector_t pblk, unsigned int len);
|
||||
|
||||
/* hooks.c */
|
||||
extern int fscrypt_file_open(struct inode *inode, struct file *filp);
|
||||
extern int __fscrypt_prepare_link(struct inode *inode, struct inode *dir,
|
||||
int fscrypt_file_open(struct inode *inode, struct file *filp);
|
||||
int __fscrypt_prepare_link(struct inode *inode, struct inode *dir,
|
||||
struct dentry *dentry);
|
||||
extern int __fscrypt_prepare_rename(struct inode *old_dir,
|
||||
struct dentry *old_dentry,
|
||||
struct inode *new_dir,
|
||||
struct dentry *new_dentry,
|
||||
int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
struct inode *new_dir, struct dentry *new_dentry,
|
||||
unsigned int flags);
|
||||
extern int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry,
|
||||
int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry,
|
||||
struct fscrypt_name *fname);
|
||||
extern int fscrypt_prepare_setflags(struct inode *inode,
|
||||
int fscrypt_prepare_setflags(struct inode *inode,
|
||||
unsigned int oldflags, unsigned int flags);
|
||||
extern int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len,
|
||||
int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len,
|
||||
unsigned int max_len,
|
||||
struct fscrypt_str *disk_link);
|
||||
extern int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
|
||||
unsigned int len,
|
||||
struct fscrypt_str *disk_link);
|
||||
extern const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
|
||||
int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
|
||||
unsigned int len, struct fscrypt_str *disk_link);
|
||||
const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
|
||||
unsigned int max_size,
|
||||
struct delayed_call *done);
|
||||
static inline void fscrypt_set_ops(struct super_block *sb,
|
||||
|
@ -222,9 +241,10 @@ static inline bool fscrypt_needs_contents_encryption(const struct inode *inode)
|
|||
return false;
|
||||
}
|
||||
|
||||
static inline bool fscrypt_dummy_context_enabled(struct inode *inode)
|
||||
static inline const union fscrypt_context *
|
||||
fscrypt_get_dummy_context(struct super_block *sb)
|
||||
{
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void fscrypt_handle_d_move(struct dentry *dentry)
|
||||
|
@ -319,6 +339,20 @@ static inline int fscrypt_inherit_context(struct inode *parent,
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
struct fscrypt_dummy_context {
|
||||
};
|
||||
|
||||
static inline void fscrypt_show_test_dummy_encryption(struct seq_file *seq,
|
||||
char sep,
|
||||
struct super_block *sb)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
fscrypt_free_dummy_context(struct fscrypt_dummy_context *dummy_ctx)
|
||||
{
|
||||
}
|
||||
|
||||
/* keyring.c */
|
||||
static inline void fscrypt_sb_free(struct super_block *sb)
|
||||
{
|
||||
|
@ -504,7 +538,7 @@ static inline void fscrypt_set_ops(struct super_block *sb,
|
|||
#endif /* !CONFIG_FS_ENCRYPTION */
|
||||
|
||||
/**
|
||||
* fscrypt_require_key - require an inode's encryption key
|
||||
* fscrypt_require_key() - require an inode's encryption key
|
||||
* @inode: the inode we need the key for
|
||||
*
|
||||
* If the inode is encrypted, set up its encryption key if not already done.
|
||||
|
@ -530,7 +564,8 @@ static inline int fscrypt_require_key(struct inode *inode)
|
|||
}
|
||||
|
||||
/**
|
||||
* fscrypt_prepare_link - prepare to link an inode into a possibly-encrypted directory
|
||||
* fscrypt_prepare_link() - prepare to link an inode into a possibly-encrypted
|
||||
* directory
|
||||
* @old_dentry: an existing dentry for the inode being linked
|
||||
* @dir: the target directory
|
||||
* @dentry: negative dentry for the target filename
|
||||
|
@ -557,7 +592,8 @@ static inline int fscrypt_prepare_link(struct dentry *old_dentry,
|
|||
}
|
||||
|
||||
/**
|
||||
* fscrypt_prepare_rename - prepare for a rename between possibly-encrypted directories
|
||||
* fscrypt_prepare_rename() - prepare for a rename between possibly-encrypted
|
||||
* directories
|
||||
* @old_dir: source directory
|
||||
* @old_dentry: dentry for source file
|
||||
* @new_dir: target directory
|
||||
|
@ -590,7 +626,8 @@ static inline int fscrypt_prepare_rename(struct inode *old_dir,
|
|||
}
|
||||
|
||||
/**
|
||||
* fscrypt_prepare_lookup - prepare to lookup a name in a possibly-encrypted directory
|
||||
* fscrypt_prepare_lookup() - prepare to lookup a name in a possibly-encrypted
|
||||
* directory
|
||||
* @dir: directory being searched
|
||||
* @dentry: filename being looked up
|
||||
* @fname: (output) the name to use to search the on-disk directory
|
||||
|
@ -623,7 +660,8 @@ static inline int fscrypt_prepare_lookup(struct inode *dir,
|
|||
}
|
||||
|
||||
/**
|
||||
* fscrypt_prepare_setattr - prepare to change a possibly-encrypted inode's attributes
|
||||
* fscrypt_prepare_setattr() - prepare to change a possibly-encrypted inode's
|
||||
* attributes
|
||||
* @dentry: dentry through which the inode is being changed
|
||||
* @attr: attributes to change
|
||||
*
|
||||
|
@ -648,7 +686,7 @@ static inline int fscrypt_prepare_setattr(struct dentry *dentry,
|
|||
}
|
||||
|
||||
/**
|
||||
* fscrypt_prepare_symlink - prepare to create a possibly-encrypted symlink
|
||||
* fscrypt_prepare_symlink() - prepare to create a possibly-encrypted symlink
|
||||
* @dir: directory in which the symlink is being created
|
||||
* @target: plaintext symlink target
|
||||
* @len: length of @target excluding null terminator
|
||||
|
@ -676,7 +714,7 @@ static inline int fscrypt_prepare_symlink(struct inode *dir,
|
|||
unsigned int max_len,
|
||||
struct fscrypt_str *disk_link)
|
||||
{
|
||||
if (IS_ENCRYPTED(dir) || fscrypt_dummy_context_enabled(dir))
|
||||
if (IS_ENCRYPTED(dir) || fscrypt_get_dummy_context(dir->i_sb) != NULL)
|
||||
return __fscrypt_prepare_symlink(dir, len, max_len, disk_link);
|
||||
|
||||
disk_link->name = (unsigned char *)target;
|
||||
|
@ -687,7 +725,7 @@ static inline int fscrypt_prepare_symlink(struct inode *dir,
|
|||
}
|
||||
|
||||
/**
|
||||
* fscrypt_encrypt_symlink - encrypt the symlink target if needed
|
||||
* fscrypt_encrypt_symlink() - encrypt the symlink target if needed
|
||||
* @inode: symlink inode
|
||||
* @target: plaintext symlink target
|
||||
* @len: length of @target excluding null terminator
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
* but could potentially be used anywhere else that simple option=arg
|
||||
* parsing is required.
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_PARSER_H
|
||||
#define _LINUX_PARSER_H
|
||||
|
||||
/* associates an integer enumerator with a pattern string. */
|
||||
struct match_token {
|
||||
|
@ -34,3 +35,5 @@ int match_hex(substring_t *, int *result);
|
|||
bool match_wildcard(const char *pattern, const char *str);
|
||||
size_t match_strlcpy(char *, const substring_t *, size_t);
|
||||
char *match_strdup(const substring_t *);
|
||||
|
||||
#endif /* _LINUX_PARSER_H */
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
#define FSCRYPT_POLICY_FLAGS_PAD_MASK 0x03
|
||||
#define FSCRYPT_POLICY_FLAG_DIRECT_KEY 0x04
|
||||
#define FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64 0x08
|
||||
#define FSCRYPT_POLICY_FLAGS_VALID 0x0F
|
||||
#define FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32 0x10
|
||||
#define FSCRYPT_POLICY_FLAGS_VALID 0x1F
|
||||
|
||||
/* Encryption algorithms */
|
||||
#define FSCRYPT_MODE_AES_256_XTS 1
|
||||
|
|
Loading…
Reference in New Issue
Block a user