fscrypt updates for 5.15
Some small fixes and cleanups for fs/crypto/: - Fix ->getattr() for ext4, f2fs, and ubifs to report the correct st_size for encrypted symlinks. - Use base64url instead of a custom Base64 variant. - Document struct fscrypt_operations. -----BEGIN PGP SIGNATURE----- iIoEABYIADIWIQSacvsUNc7UX4ntmEPzXCl4vpKOKwUCYS0HzhQcZWJpZ2dlcnNA Z29vZ2xlLmNvbQAKCRDzXCl4vpKOK+XZAQDfvDE9gK4Ii2uE4Jb5XYv4M/BnVhoR WIhNEoHROIGv+AEAtyfmeCMdpPobkWHFfAE1iBysl3iS56fibQhi2wqyuQI= =s6Wi -----END PGP SIGNATURE----- Merge tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt Pull fscrypt updates from Eric Biggers: "Some small fixes and cleanups for fs/crypto/: - Fix ->getattr() for ext4, f2fs, and ubifs to report the correct st_size for encrypted symlinks - Use base64url instead of a custom Base64 variant - Document struct fscrypt_operations" * tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt: fscrypt: document struct fscrypt_operations fscrypt: align Base64 encoding with RFC 4648 base64url fscrypt: remove mention of symlink st_size quirk from documentation ubifs: report correct st_size for encrypted symlinks f2fs: report correct st_size for encrypted symlinks ext4: report correct st_size for encrypted symlinks fscrypt: add fscrypt_symlink_getattr() for computing st_size
This commit is contained in:
commit
cd358208d7
|
@ -1063,11 +1063,6 @@ astute users may notice some differences in behavior:
|
|||
|
||||
- DAX (Direct Access) is not supported on encrypted files.
|
||||
|
||||
- The st_size of an encrypted symlink will not necessarily give the
|
||||
length of the symlink target as required by POSIX. It will actually
|
||||
give the length of the ciphertext, which will be slightly longer
|
||||
than the plaintext due to NUL-padding and an extra 2-byte overhead.
|
||||
|
||||
- The maximum length of an encrypted symlink is 2 bytes shorter than
|
||||
the maximum length of an unencrypted symlink. For example, on an
|
||||
EXT4 filesystem with a 4K block size, unencrypted symlinks can be up
|
||||
|
@ -1235,12 +1230,12 @@ the user-supplied name to get the ciphertext.
|
|||
|
||||
Lookups without the key are more complicated. The raw ciphertext may
|
||||
contain the ``\0`` and ``/`` characters, which are illegal in
|
||||
filenames. Therefore, readdir() must base64-encode the ciphertext for
|
||||
presentation. For most filenames, this works fine; on ->lookup(), the
|
||||
filesystem just base64-decodes the user-supplied name to get back to
|
||||
the raw ciphertext.
|
||||
filenames. Therefore, readdir() must base64url-encode the ciphertext
|
||||
for presentation. For most filenames, this works fine; on ->lookup(),
|
||||
the filesystem just base64url-decodes the user-supplied name to get
|
||||
back to the raw ciphertext.
|
||||
|
||||
However, for very long filenames, base64 encoding would cause the
|
||||
However, for very long filenames, base64url encoding would cause the
|
||||
filename length to exceed NAME_MAX. To prevent this, readdir()
|
||||
actually presents long filenames in an abbreviated form which encodes
|
||||
a strong "hash" of the ciphertext filename, along with the optional
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
* it to find the directory entry again if requested. Naively, that would just
|
||||
* mean using the ciphertext filenames. However, since the ciphertext filenames
|
||||
* can contain illegal characters ('\0' and '/'), they must be encoded in some
|
||||
* way. We use base64. But that can cause names to exceed NAME_MAX (255
|
||||
* way. We use base64url. But that can cause names to exceed NAME_MAX (255
|
||||
* bytes), so we also need to use a strong hash to abbreviate long names.
|
||||
*
|
||||
* The filesystem may also need another kind of hash, the "dirhash", to quickly
|
||||
|
@ -38,7 +38,7 @@
|
|||
* casefolded directories use this type of dirhash. At least in these cases,
|
||||
* each no-key name must include the name's dirhash too.
|
||||
*
|
||||
* To meet all these requirements, we base64-encode the following
|
||||
* To meet all these requirements, we base64url-encode the following
|
||||
* variable-length structure. It contains the dirhash, or 0's if the filesystem
|
||||
* didn't provide one; up to 149 bytes of the ciphertext name; and for
|
||||
* ciphertexts longer than 149 bytes, also the SHA-256 of the remaining bytes.
|
||||
|
@ -52,15 +52,19 @@ struct fscrypt_nokey_name {
|
|||
u32 dirhash[2];
|
||||
u8 bytes[149];
|
||||
u8 sha256[SHA256_DIGEST_SIZE];
|
||||
}; /* 189 bytes => 252 bytes base64-encoded, which is <= NAME_MAX (255) */
|
||||
}; /* 189 bytes => 252 bytes base64url-encoded, which is <= NAME_MAX (255) */
|
||||
|
||||
/*
|
||||
* Decoded size of max-size nokey name, i.e. a name that was abbreviated using
|
||||
* Decoded size of max-size no-key name, i.e. a name that was abbreviated using
|
||||
* the strong hash and thus includes the 'sha256' field. This isn't simply
|
||||
* sizeof(struct fscrypt_nokey_name), as the padding at the end isn't included.
|
||||
*/
|
||||
#define FSCRYPT_NOKEY_NAME_MAX offsetofend(struct fscrypt_nokey_name, sha256)
|
||||
|
||||
/* Encoded size of max-size no-key name */
|
||||
#define FSCRYPT_NOKEY_NAME_MAX_ENCODED \
|
||||
FSCRYPT_BASE64URL_CHARS(FSCRYPT_NOKEY_NAME_MAX)
|
||||
|
||||
static inline bool fscrypt_is_dot_dotdot(const struct qstr *str)
|
||||
{
|
||||
if (str->len == 1 && str->name[0] == '.')
|
||||
|
@ -175,62 +179,82 @@ static int fname_decrypt(const struct inode *inode,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const char lookup_table[65] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
|
||||
static const char base64url_table[65] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
||||
|
||||
#define BASE64_CHARS(nbytes) DIV_ROUND_UP((nbytes) * 4, 3)
|
||||
#define FSCRYPT_BASE64URL_CHARS(nbytes) DIV_ROUND_UP((nbytes) * 4, 3)
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* fscrypt_base64url_encode() - base64url-encode some binary data
|
||||
* @src: the binary data to encode
|
||||
* @srclen: the length of @src in bytes
|
||||
* @dst: (output) the base64url-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.
|
||||
* Encodes data using base64url encoding, i.e. the "Base 64 Encoding with URL
|
||||
* and Filename Safe Alphabet" specified by RFC 4648. '='-padding isn't used,
|
||||
* as it's unneeded and not required by the RFC. base64url is used instead of
|
||||
* base64 to avoid the '/' character, which isn't allowed in filenames.
|
||||
*
|
||||
* Return: length of the encoded string
|
||||
* Return: the length of the resulting base64url-encoded string in bytes.
|
||||
* This will be equal to FSCRYPT_BASE64URL_CHARS(srclen).
|
||||
*/
|
||||
static int base64_encode(const u8 *src, int len, char *dst)
|
||||
static int fscrypt_base64url_encode(const u8 *src, int srclen, char *dst)
|
||||
{
|
||||
int i, bits = 0, ac = 0;
|
||||
u32 ac = 0;
|
||||
int bits = 0;
|
||||
int i;
|
||||
char *cp = dst;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
ac += src[i] << bits;
|
||||
for (i = 0; i < srclen; i++) {
|
||||
ac = (ac << 8) | src[i];
|
||||
bits += 8;
|
||||
do {
|
||||
*cp++ = lookup_table[ac & 0x3f];
|
||||
ac >>= 6;
|
||||
bits -= 6;
|
||||
*cp++ = base64url_table[(ac >> bits) & 0x3f];
|
||||
} while (bits >= 6);
|
||||
}
|
||||
if (bits)
|
||||
*cp++ = lookup_table[ac & 0x3f];
|
||||
*cp++ = base64url_table[(ac << (6 - bits)) & 0x3f];
|
||||
return cp - dst;
|
||||
}
|
||||
|
||||
static int base64_decode(const char *src, int len, u8 *dst)
|
||||
/**
|
||||
* fscrypt_base64url_decode() - base64url-decode a string
|
||||
* @src: the string to decode. Doesn't need to be NUL-terminated.
|
||||
* @srclen: the length of @src in bytes
|
||||
* @dst: (output) the decoded binary data
|
||||
*
|
||||
* Decodes a string using base64url encoding, i.e. the "Base 64 Encoding with
|
||||
* URL and Filename Safe Alphabet" specified by RFC 4648. '='-padding isn't
|
||||
* accepted, nor are non-encoding characters such as whitespace.
|
||||
*
|
||||
* This implementation hasn't been optimized for performance.
|
||||
*
|
||||
* Return: the length of the resulting decoded binary data in bytes,
|
||||
* or -1 if the string isn't a valid base64url string.
|
||||
*/
|
||||
static int fscrypt_base64url_decode(const char *src, int srclen, u8 *dst)
|
||||
{
|
||||
int i, bits = 0, ac = 0;
|
||||
const char *p;
|
||||
u8 *cp = dst;
|
||||
u32 ac = 0;
|
||||
int bits = 0;
|
||||
int i;
|
||||
u8 *bp = dst;
|
||||
|
||||
for (i = 0; i < srclen; i++) {
|
||||
const char *p = strchr(base64url_table, src[i]);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
p = strchr(lookup_table, src[i]);
|
||||
if (p == NULL || src[i] == 0)
|
||||
return -2;
|
||||
ac += (p - lookup_table) << bits;
|
||||
return -1;
|
||||
ac = (ac << 6) | (p - base64url_table);
|
||||
bits += 6;
|
||||
if (bits >= 8) {
|
||||
*cp++ = ac & 0xff;
|
||||
ac >>= 8;
|
||||
bits -= 8;
|
||||
*bp++ = (u8)(ac >> bits);
|
||||
}
|
||||
}
|
||||
if (ac)
|
||||
if (ac & ((1 << bits) - 1))
|
||||
return -1;
|
||||
return cp - dst;
|
||||
return bp - dst;
|
||||
}
|
||||
|
||||
bool fscrypt_fname_encrypted_size(const union fscrypt_policy *policy,
|
||||
|
@ -263,10 +287,8 @@ bool fscrypt_fname_encrypted_size(const union fscrypt_policy *policy,
|
|||
int fscrypt_fname_alloc_buffer(u32 max_encrypted_len,
|
||||
struct fscrypt_str *crypto_str)
|
||||
{
|
||||
const u32 max_encoded_len = BASE64_CHARS(FSCRYPT_NOKEY_NAME_MAX);
|
||||
u32 max_presented_len;
|
||||
|
||||
max_presented_len = max(max_encoded_len, max_encrypted_len);
|
||||
u32 max_presented_len = max_t(u32, FSCRYPT_NOKEY_NAME_MAX_ENCODED,
|
||||
max_encrypted_len);
|
||||
|
||||
crypto_str->name = kmalloc(max_presented_len + 1, GFP_NOFS);
|
||||
if (!crypto_str->name)
|
||||
|
@ -342,7 +364,7 @@ int fscrypt_fname_disk_to_usr(const struct inode *inode,
|
|||
offsetof(struct fscrypt_nokey_name, bytes));
|
||||
BUILD_BUG_ON(offsetofend(struct fscrypt_nokey_name, bytes) !=
|
||||
offsetof(struct fscrypt_nokey_name, sha256));
|
||||
BUILD_BUG_ON(BASE64_CHARS(FSCRYPT_NOKEY_NAME_MAX) > NAME_MAX);
|
||||
BUILD_BUG_ON(FSCRYPT_NOKEY_NAME_MAX_ENCODED > NAME_MAX);
|
||||
|
||||
nokey_name.dirhash[0] = hash;
|
||||
nokey_name.dirhash[1] = minor_hash;
|
||||
|
@ -358,7 +380,8 @@ int fscrypt_fname_disk_to_usr(const struct inode *inode,
|
|||
nokey_name.sha256);
|
||||
size = FSCRYPT_NOKEY_NAME_MAX;
|
||||
}
|
||||
oname->len = base64_encode((const u8 *)&nokey_name, size, oname->name);
|
||||
oname->len = fscrypt_base64url_encode((const u8 *)&nokey_name, size,
|
||||
oname->name);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(fscrypt_fname_disk_to_usr);
|
||||
|
@ -432,14 +455,15 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,
|
|||
* user-supplied name
|
||||
*/
|
||||
|
||||
if (iname->len > BASE64_CHARS(FSCRYPT_NOKEY_NAME_MAX))
|
||||
if (iname->len > FSCRYPT_NOKEY_NAME_MAX_ENCODED)
|
||||
return -ENOENT;
|
||||
|
||||
fname->crypto_buf.name = kmalloc(FSCRYPT_NOKEY_NAME_MAX, GFP_KERNEL);
|
||||
if (fname->crypto_buf.name == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = base64_decode(iname->name, iname->len, fname->crypto_buf.name);
|
||||
ret = fscrypt_base64url_decode(iname->name, iname->len,
|
||||
fname->crypto_buf.name);
|
||||
if (ret < (int)offsetof(struct fscrypt_nokey_name, bytes[1]) ||
|
||||
(ret > offsetof(struct fscrypt_nokey_name, sha256) &&
|
||||
ret != FSCRYPT_NOKEY_NAME_MAX)) {
|
||||
|
|
|
@ -384,3 +384,47 @@ err_kfree:
|
|||
return ERR_PTR(err);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fscrypt_get_symlink);
|
||||
|
||||
/**
|
||||
* fscrypt_symlink_getattr() - set the correct st_size for encrypted symlinks
|
||||
* @path: the path for the encrypted symlink being queried
|
||||
* @stat: the struct being filled with the symlink's attributes
|
||||
*
|
||||
* Override st_size of encrypted symlinks to be the length of the decrypted
|
||||
* symlink target (or the no-key encoded symlink target, if the key is
|
||||
* unavailable) rather than the length of the encrypted symlink target. This is
|
||||
* necessary for st_size to match the symlink target that userspace actually
|
||||
* sees. POSIX requires this, and some userspace programs depend on it.
|
||||
*
|
||||
* This requires reading the symlink target from disk if needed, setting up the
|
||||
* inode's encryption key if possible, and then decrypting or encoding the
|
||||
* symlink target. This makes lstat() more heavyweight than is normally the
|
||||
* case. However, decrypted symlink targets will be cached in ->i_link, so
|
||||
* usually the symlink won't have to be read and decrypted again later if/when
|
||||
* it is actually followed, readlink() is called, or lstat() is called again.
|
||||
*
|
||||
* Return: 0 on success, -errno on failure
|
||||
*/
|
||||
int fscrypt_symlink_getattr(const struct path *path, struct kstat *stat)
|
||||
{
|
||||
struct dentry *dentry = path->dentry;
|
||||
struct inode *inode = d_inode(dentry);
|
||||
const char *link;
|
||||
DEFINE_DELAYED_CALL(done);
|
||||
|
||||
/*
|
||||
* To get the symlink target that userspace will see (whether it's the
|
||||
* decrypted target or the no-key encoded target), we can just get it in
|
||||
* the same way the VFS does during path resolution and readlink().
|
||||
*/
|
||||
link = READ_ONCE(inode->i_link);
|
||||
if (!link) {
|
||||
link = inode->i_op->get_link(dentry, inode, &done);
|
||||
if (IS_ERR(link))
|
||||
return PTR_ERR(link);
|
||||
}
|
||||
stat->size = strlen(link);
|
||||
do_delayed_call(&done);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fscrypt_symlink_getattr);
|
||||
|
|
|
@ -52,10 +52,20 @@ static const char *ext4_encrypted_get_link(struct dentry *dentry,
|
|||
return paddr;
|
||||
}
|
||||
|
||||
static int ext4_encrypted_symlink_getattr(struct user_namespace *mnt_userns,
|
||||
const struct path *path,
|
||||
struct kstat *stat, u32 request_mask,
|
||||
unsigned int query_flags)
|
||||
{
|
||||
ext4_getattr(mnt_userns, path, stat, request_mask, query_flags);
|
||||
|
||||
return fscrypt_symlink_getattr(path, stat);
|
||||
}
|
||||
|
||||
const struct inode_operations ext4_encrypted_symlink_inode_operations = {
|
||||
.get_link = ext4_encrypted_get_link,
|
||||
.setattr = ext4_setattr,
|
||||
.getattr = ext4_getattr,
|
||||
.getattr = ext4_encrypted_symlink_getattr,
|
||||
.listxattr = ext4_listxattr,
|
||||
};
|
||||
|
||||
|
|
|
@ -1323,9 +1323,19 @@ static const char *f2fs_encrypted_get_link(struct dentry *dentry,
|
|||
return target;
|
||||
}
|
||||
|
||||
static int f2fs_encrypted_symlink_getattr(struct user_namespace *mnt_userns,
|
||||
const struct path *path,
|
||||
struct kstat *stat, u32 request_mask,
|
||||
unsigned int query_flags)
|
||||
{
|
||||
f2fs_getattr(mnt_userns, path, stat, request_mask, query_flags);
|
||||
|
||||
return fscrypt_symlink_getattr(path, stat);
|
||||
}
|
||||
|
||||
const struct inode_operations f2fs_encrypted_symlink_inode_operations = {
|
||||
.get_link = f2fs_encrypted_get_link,
|
||||
.getattr = f2fs_getattr,
|
||||
.getattr = f2fs_encrypted_symlink_getattr,
|
||||
.setattr = f2fs_setattr,
|
||||
.listxattr = f2fs_listxattr,
|
||||
};
|
||||
|
|
|
@ -1630,6 +1630,17 @@ static const char *ubifs_get_link(struct dentry *dentry,
|
|||
return fscrypt_get_symlink(inode, ui->data, ui->data_len, done);
|
||||
}
|
||||
|
||||
static int ubifs_symlink_getattr(struct user_namespace *mnt_userns,
|
||||
const struct path *path, struct kstat *stat,
|
||||
u32 request_mask, unsigned int query_flags)
|
||||
{
|
||||
ubifs_getattr(mnt_userns, path, stat, request_mask, query_flags);
|
||||
|
||||
if (IS_ENCRYPTED(d_inode(path->dentry)))
|
||||
return fscrypt_symlink_getattr(path, stat);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct address_space_operations ubifs_file_address_operations = {
|
||||
.readpage = ubifs_readpage,
|
||||
.writepage = ubifs_writepage,
|
||||
|
@ -1655,7 +1666,7 @@ const struct inode_operations ubifs_file_inode_operations = {
|
|||
const struct inode_operations ubifs_symlink_inode_operations = {
|
||||
.get_link = ubifs_get_link,
|
||||
.setattr = ubifs_setattr,
|
||||
.getattr = ubifs_getattr,
|
||||
.getattr = ubifs_symlink_getattr,
|
||||
.listxattr = ubifs_listxattr,
|
||||
.update_time = ubifs_update_time,
|
||||
};
|
||||
|
|
|
@ -47,27 +47,128 @@ struct fscrypt_name {
|
|||
#define FSCRYPT_SET_CONTEXT_MAX_SIZE 40
|
||||
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
|
||||
/*
|
||||
* fscrypt superblock flags
|
||||
* 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
|
||||
*/
|
||||
/* Crypto operations for filesystems */
|
||||
struct fscrypt_operations {
|
||||
|
||||
/* Set of optional flags; see above for allowed flags */
|
||||
unsigned int flags;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
const char *key_prefix;
|
||||
|
||||
/*
|
||||
* Get the fscrypt context of the given inode.
|
||||
*
|
||||
* @inode: the inode whose context to get
|
||||
* @ctx: the buffer into which to get the context
|
||||
* @len: length of the @ctx buffer in bytes
|
||||
*
|
||||
* Return: On success, returns the length of the context in bytes; this
|
||||
* may be less than @len. On failure, returns -ENODATA if the
|
||||
* inode doesn't have a context, -ERANGE if the context is
|
||||
* longer than @len, or another -errno code.
|
||||
*/
|
||||
int (*get_context)(struct inode *inode, void *ctx, size_t len);
|
||||
|
||||
/*
|
||||
* Set an fscrypt context on the given inode.
|
||||
*
|
||||
* @inode: the inode whose context to set. The inode won't already have
|
||||
* an fscrypt context.
|
||||
* @ctx: the context to set
|
||||
* @len: length of @ctx in bytes (at most FSCRYPT_SET_CONTEXT_MAX_SIZE)
|
||||
* @fs_data: If called from fscrypt_set_context(), this will be the
|
||||
* value the filesystem passed to fscrypt_set_context().
|
||||
* Otherwise (i.e. when called from
|
||||
* FS_IOC_SET_ENCRYPTION_POLICY) this will be NULL.
|
||||
*
|
||||
* i_rwsem will be held for write.
|
||||
*
|
||||
* Return: 0 on success, -errno on failure.
|
||||
*/
|
||||
int (*set_context)(struct inode *inode, const void *ctx, size_t len,
|
||||
void *fs_data);
|
||||
|
||||
/*
|
||||
* Get the dummy fscrypt policy in use on the filesystem (if any).
|
||||
*
|
||||
* Filesystems only need to implement this function if they support the
|
||||
* test_dummy_encryption mount option.
|
||||
*
|
||||
* Return: A pointer to the dummy fscrypt policy, if the filesystem is
|
||||
* mounted with test_dummy_encryption; otherwise NULL.
|
||||
*/
|
||||
const union fscrypt_policy *(*get_dummy_policy)(struct super_block *sb);
|
||||
|
||||
/*
|
||||
* Check whether a directory is empty. i_rwsem will be held for write.
|
||||
*/
|
||||
bool (*empty_dir)(struct inode *inode);
|
||||
|
||||
/* The filesystem's maximum ciphertext filename length, in bytes */
|
||||
unsigned int max_namelen;
|
||||
|
||||
/*
|
||||
* Check whether the filesystem's inode numbers and UUID are stable,
|
||||
* meaning that they will never be changed even by offline operations
|
||||
* such as filesystem shrinking and therefore can be used in the
|
||||
* encryption without the possibility of files becoming unreadable.
|
||||
*
|
||||
* Filesystems only need to implement this function if they want to
|
||||
* support the FSCRYPT_POLICY_FLAG_IV_INO_LBLK_{32,64} flags. These
|
||||
* flags are designed to work around the limitations of UFS and eMMC
|
||||
* inline crypto hardware, and they shouldn't be used in scenarios where
|
||||
* such hardware isn't being used.
|
||||
*
|
||||
* Leaving this NULL is equivalent to always returning false.
|
||||
*/
|
||||
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 the number of block devices to which the filesystem may write
|
||||
* encrypted file contents.
|
||||
*
|
||||
* If the filesystem can use multiple block devices (other than block
|
||||
* devices that aren't used for encrypted file contents, such as
|
||||
* external journal devices), and wants to support inline encryption,
|
||||
* then it must implement this function. Otherwise it's not needed.
|
||||
*/
|
||||
int (*get_num_devices)(struct super_block *sb);
|
||||
|
||||
/*
|
||||
* If ->get_num_devices() returns a value greater than 1, then this
|
||||
* function is called to get the array of request_queues that the
|
||||
* filesystem is using -- one per block device. (There may be duplicate
|
||||
* entries in this array, as block devices can share a request_queue.)
|
||||
*/
|
||||
void (*get_devices)(struct super_block *sb,
|
||||
struct request_queue **devs);
|
||||
};
|
||||
|
@ -253,6 +354,7 @@ int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
|
|||
const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
|
||||
unsigned int max_size,
|
||||
struct delayed_call *done);
|
||||
int fscrypt_symlink_getattr(const struct path *path, struct kstat *stat);
|
||||
static inline void fscrypt_set_ops(struct super_block *sb,
|
||||
const struct fscrypt_operations *s_cop)
|
||||
{
|
||||
|
@ -583,6 +685,12 @@ static inline const char *fscrypt_get_symlink(struct inode *inode,
|
|||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline int fscrypt_symlink_getattr(const struct path *path,
|
||||
struct kstat *stat)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline void fscrypt_set_ops(struct super_block *sb,
|
||||
const struct fscrypt_operations *s_cop)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue