forked from Minki/linux
fscrypt updates for v5.1
First: Ted, Jaegeuk, and I have decided to add me as a co-maintainer for fscrypt, and we're now using a shared git tree. So we've updated MAINTAINERS accordingly, and I'm doing the pull request this time. The actual changes for v5.1 are: - Remove the fs-specific kconfig options like CONFIG_EXT4_ENCRYPTION and make fscrypt support for all fscrypt-capable filesystems be controlled by CONFIG_FS_ENCRYPTION, similar to how CONFIG_QUOTA works. - Improve error code for rename() and link() into encrypted directories. - Various cleanups. -----BEGIN PGP SIGNATURE----- iIoEABYIADIWIQSacvsUNc7UX4ntmEPzXCl4vpKOKwUCXH2YDRQcZWJpZ2dlcnNA Z29vZ2xlLmNvbQAKCRDzXCl4vpKOK+SAAQCWYOTwYko8uE8Ze8i2fiUm0vr91NOg zj5DGmK7Izxy/gEAsNDOVA7zWrDg/f5600/7aLpDQQTGHA38YVsgiyd7DgY= =S3tT -----END PGP SIGNATURE----- Merge tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt Pull fscrypt updates from Eric Biggers: "First: Ted, Jaegeuk, and I have decided to add me as a co-maintainer for fscrypt, and we're now using a shared git tree. So we've updated MAINTAINERS accordingly, and I'm doing the pull request this time. The actual changes for v5.1 are: - Remove the fs-specific kconfig options like CONFIG_EXT4_ENCRYPTION and make fscrypt support for all fscrypt-capable filesystems be controlled by CONFIG_FS_ENCRYPTION, similar to how CONFIG_QUOTA works. - Improve error code for rename() and link() into encrypted directories. - Various cleanups" * tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt: MAINTAINERS: add Eric Biggers as an fscrypt maintainer fscrypt: return -EXDEV for incompatible rename or link into encrypted dir fscrypt: remove filesystem specific build config option f2fs: use IS_ENCRYPTED() to check encryption status ext4: use IS_ENCRYPTED() to check encryption status fscrypt: remove CRYPTO_CTR dependency
This commit is contained in:
commit
d1cae94871
@ -343,9 +343,9 @@ FS_IOC_SET_ENCRYPTION_POLICY can fail with the following errors:
|
||||
- ``ENOTEMPTY``: the file is unencrypted and is a nonempty directory
|
||||
- ``ENOTTY``: this type of filesystem does not implement encryption
|
||||
- ``EOPNOTSUPP``: the kernel was not configured with encryption
|
||||
support for this filesystem, or the filesystem superblock has not
|
||||
support for filesystems, or the filesystem superblock has not
|
||||
had encryption enabled on it. (For example, to use encryption on an
|
||||
ext4 filesystem, CONFIG_EXT4_ENCRYPTION must be enabled in the
|
||||
ext4 filesystem, CONFIG_FS_ENCRYPTION must be enabled in the
|
||||
kernel config, and the superblock must have had the "encrypt"
|
||||
feature flag enabled using ``tune2fs -O encrypt`` or ``mkfs.ext4 -O
|
||||
encrypt``.)
|
||||
@ -451,10 +451,18 @@ astute users may notice some differences in behavior:
|
||||
- Unencrypted files, or files encrypted with a different encryption
|
||||
policy (i.e. different key, modes, or flags), cannot be renamed or
|
||||
linked into an encrypted directory; see `Encryption policy
|
||||
enforcement`_. Attempts to do so will fail with EPERM. However,
|
||||
enforcement`_. Attempts to do so will fail with EXDEV. However,
|
||||
encrypted files can be renamed within an encrypted directory, or
|
||||
into an unencrypted directory.
|
||||
|
||||
Note: "moving" an unencrypted file into an encrypted directory, e.g.
|
||||
with the `mv` program, is implemented in userspace by a copy
|
||||
followed by a delete. Be aware that the original unencrypted data
|
||||
may remain recoverable from free space on the disk; prefer to keep
|
||||
all files encrypted from the very beginning. The `shred` program
|
||||
may be used to overwrite the source files but isn't guaranteed to be
|
||||
effective on all filesystems and storage devices.
|
||||
|
||||
- Direct I/O is not supported on encrypted files. Attempts to use
|
||||
direct I/O on such files will fall back to buffered I/O.
|
||||
|
||||
@ -541,7 +549,7 @@ not be encrypted.
|
||||
Except for those special files, it is forbidden to have unencrypted
|
||||
files, or files encrypted with a different encryption policy, in an
|
||||
encrypted directory tree. Attempts to link or rename such a file into
|
||||
an encrypted directory will fail with EPERM. This is also enforced
|
||||
an encrypted directory will fail with EXDEV. This is also enforced
|
||||
during ->lookup() to provide limited protection against offline
|
||||
attacks that try to disable or downgrade encryption in known locations
|
||||
where applications may later write sensitive data. It is recommended
|
||||
|
@ -6337,9 +6337,10 @@ F: include/linux/fscache*.h
|
||||
FSCRYPT: FILE SYSTEM LEVEL ENCRYPTION SUPPORT
|
||||
M: Theodore Y. Ts'o <tytso@mit.edu>
|
||||
M: Jaegeuk Kim <jaegeuk@kernel.org>
|
||||
M: Eric Biggers <ebiggers@kernel.org>
|
||||
L: linux-fscrypt@vger.kernel.org
|
||||
Q: https://patchwork.kernel.org/project/linux-fscrypt/list/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tytso/fscrypt.git
|
||||
T: git git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt.git
|
||||
S: Supported
|
||||
F: fs/crypto/
|
||||
F: include/linux/fscrypt*.h
|
||||
|
@ -59,7 +59,7 @@ CONFIG_HID_MONTEREY=y
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_EXT4_FS_POSIX_ACL=y
|
||||
CONFIG_EXT4_FS_SECURITY=y
|
||||
CONFIG_EXT4_ENCRYPTION=y
|
||||
CONFIG_FS_ENCRYPTION=y
|
||||
CONFIG_FANOTIFY=y
|
||||
CONFIG_FUSE_FS=y
|
||||
CONFIG_CUSE=y
|
||||
|
@ -74,7 +74,7 @@ CONFIG_GENERIC_PHY=y
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_EXT4_FS_POSIX_ACL=y
|
||||
CONFIG_EXT4_FS_SECURITY=y
|
||||
CONFIG_EXT4_ENCRYPTION=y
|
||||
CONFIG_FS_ENCRYPTION=y
|
||||
CONFIG_FUSE_FS=y
|
||||
CONFIG_MSDOS_FS=y
|
||||
CONFIG_VFAT_FS=y
|
||||
|
@ -500,7 +500,6 @@ CONFIG_S390_AP_IOMMU=y
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_EXT4_FS_POSIX_ACL=y
|
||||
CONFIG_EXT4_FS_SECURITY=y
|
||||
CONFIG_EXT4_ENCRYPTION=y
|
||||
CONFIG_JBD2_DEBUG=y
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_JFS_POSIX_ACL=y
|
||||
@ -520,6 +519,7 @@ CONFIG_BTRFS_DEBUG=y
|
||||
CONFIG_NILFS2_FS=m
|
||||
CONFIG_FS_DAX=y
|
||||
CONFIG_EXPORTFS_BLOCK_OPS=y
|
||||
CONFIG_FS_ENCRYPTION=y
|
||||
CONFIG_FANOTIFY=y
|
||||
CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
|
||||
CONFIG_QUOTA_NETLINK_INTERFACE=y
|
||||
|
@ -497,7 +497,6 @@ CONFIG_S390_AP_IOMMU=y
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_EXT4_FS_POSIX_ACL=y
|
||||
CONFIG_EXT4_FS_SECURITY=y
|
||||
CONFIG_EXT4_ENCRYPTION=y
|
||||
CONFIG_JBD2_DEBUG=y
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_JFS_POSIX_ACL=y
|
||||
@ -515,6 +514,7 @@ CONFIG_BTRFS_FS_POSIX_ACL=y
|
||||
CONFIG_NILFS2_FS=m
|
||||
CONFIG_FS_DAX=y
|
||||
CONFIG_EXPORTFS_BLOCK_OPS=y
|
||||
CONFIG_FS_ENCRYPTION=y
|
||||
CONFIG_FANOTIFY=y
|
||||
CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
|
||||
CONFIG_QUOTA_NETLINK_INTERFACE=y
|
||||
|
@ -1,16 +1,16 @@
|
||||
config FS_ENCRYPTION
|
||||
tristate "FS Encryption (Per-file encryption)"
|
||||
bool "FS Encryption (Per-file encryption)"
|
||||
select CRYPTO
|
||||
select CRYPTO_AES
|
||||
select CRYPTO_CBC
|
||||
select CRYPTO_ECB
|
||||
select CRYPTO_XTS
|
||||
select CRYPTO_CTS
|
||||
select CRYPTO_CTR
|
||||
select CRYPTO_SHA256
|
||||
select KEYS
|
||||
help
|
||||
Enable encryption of files and directories. This
|
||||
feature is similar to ecryptfs, but it is more memory
|
||||
efficient since it avoids caching the encrypted and
|
||||
decrypted pages in the page cache.
|
||||
decrypted pages in the page cache. Currently Ext4,
|
||||
F2FS and UBIFS make use of this feature.
|
||||
|
@ -12,7 +12,6 @@
|
||||
#ifndef _FSCRYPT_PRIVATE_H
|
||||
#define _FSCRYPT_PRIVATE_H
|
||||
|
||||
#define __FS_HAS_ENCRYPTION 1
|
||||
#include <linux/fscrypt.h>
|
||||
#include <crypto/hash.h>
|
||||
|
||||
|
@ -58,7 +58,7 @@ int __fscrypt_prepare_link(struct inode *inode, struct inode *dir)
|
||||
return err;
|
||||
|
||||
if (!fscrypt_has_permitted_context(dir, inode))
|
||||
return -EPERM;
|
||||
return -EXDEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -82,13 +82,13 @@ int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
if (IS_ENCRYPTED(new_dir) &&
|
||||
!fscrypt_has_permitted_context(new_dir,
|
||||
d_inode(old_dentry)))
|
||||
return -EPERM;
|
||||
return -EXDEV;
|
||||
|
||||
if ((flags & RENAME_EXCHANGE) &&
|
||||
IS_ENCRYPTED(old_dir) &&
|
||||
!fscrypt_has_permitted_context(old_dir,
|
||||
d_inode(new_dentry)))
|
||||
return -EPERM;
|
||||
return -EXDEV;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -151,8 +151,7 @@ EXPORT_SYMBOL(fscrypt_ioctl_get_policy);
|
||||
* malicious offline violations of this constraint, while the link and rename
|
||||
* checks are needed to prevent online violations of this constraint.
|
||||
*
|
||||
* Return: 1 if permitted, 0 if forbidden. If forbidden, the caller must fail
|
||||
* the filesystem operation with EPERM.
|
||||
* Return: 1 if permitted, 0 if forbidden.
|
||||
*/
|
||||
int fscrypt_has_permitted_context(struct inode *parent, struct inode *child)
|
||||
{
|
||||
|
@ -96,21 +96,6 @@ config EXT4_FS_SECURITY
|
||||
If you are not using a security module that requires using
|
||||
extended attributes for file security labels, say N.
|
||||
|
||||
config EXT4_ENCRYPTION
|
||||
bool "Ext4 Encryption"
|
||||
depends on EXT4_FS
|
||||
select FS_ENCRYPTION
|
||||
help
|
||||
Enable encryption of ext4 files and directories. This
|
||||
feature is similar to ecryptfs, but it is more memory
|
||||
efficient since it avoids caching the encrypted and
|
||||
decrypted pages in the page cache.
|
||||
|
||||
config EXT4_FS_ENCRYPTION
|
||||
bool
|
||||
default y
|
||||
depends on EXT4_ENCRYPTION
|
||||
|
||||
config EXT4_DEBUG
|
||||
bool "EXT4 debugging support"
|
||||
depends on EXT4_FS
|
||||
|
@ -111,7 +111,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
|
||||
int dir_has_error = 0;
|
||||
struct fscrypt_str fstr = FSTR_INIT(NULL, 0);
|
||||
|
||||
if (ext4_encrypted_inode(inode)) {
|
||||
if (IS_ENCRYPTED(inode)) {
|
||||
err = fscrypt_get_encryption_info(inode);
|
||||
if (err && err != -ENOKEY)
|
||||
return err;
|
||||
@ -138,7 +138,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (ext4_encrypted_inode(inode)) {
|
||||
if (IS_ENCRYPTED(inode)) {
|
||||
err = fscrypt_fname_alloc_buffer(inode, EXT4_NAME_LEN, &fstr);
|
||||
if (err < 0)
|
||||
return err;
|
||||
@ -245,7 +245,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
|
||||
offset += ext4_rec_len_from_disk(de->rec_len,
|
||||
sb->s_blocksize);
|
||||
if (le32_to_cpu(de->inode)) {
|
||||
if (!ext4_encrypted_inode(inode)) {
|
||||
if (!IS_ENCRYPTED(inode)) {
|
||||
if (!dir_emit(ctx, de->name,
|
||||
de->name_len,
|
||||
le32_to_cpu(de->inode),
|
||||
@ -283,9 +283,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
|
||||
done:
|
||||
err = 0;
|
||||
errout:
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
fscrypt_fname_free_buffer(&fstr);
|
||||
#endif
|
||||
brelse(bh);
|
||||
return err;
|
||||
}
|
||||
@ -613,7 +611,7 @@ finished:
|
||||
|
||||
static int ext4_dir_open(struct inode * inode, struct file * filp)
|
||||
{
|
||||
if (ext4_encrypted_inode(inode))
|
||||
if (IS_ENCRYPTED(inode))
|
||||
return fscrypt_get_encryption_info(inode) ? -EACCES : 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -40,7 +40,6 @@
|
||||
#include <linux/compat.h>
|
||||
#endif
|
||||
|
||||
#define __FS_HAS_ENCRYPTION IS_ENABLED(CONFIG_EXT4_FS_ENCRYPTION)
|
||||
#include <linux/fscrypt.h>
|
||||
|
||||
#include <linux/compiler.h>
|
||||
@ -1326,7 +1325,7 @@ struct ext4_super_block {
|
||||
#define EXT4_MF_FS_ABORTED 0x0002 /* Fatal error detected */
|
||||
#define EXT4_MF_TEST_DUMMY_ENCRYPTION 0x0004
|
||||
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
#define DUMMY_ENCRYPTION_ENABLED(sbi) (unlikely((sbi)->s_mount_flags & \
|
||||
EXT4_MF_TEST_DUMMY_ENCRYPTION))
|
||||
#else
|
||||
@ -2051,7 +2050,7 @@ struct ext4_filename {
|
||||
const struct qstr *usr_fname;
|
||||
struct fscrypt_str disk_name;
|
||||
struct dx_hash_info hinfo;
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
struct fscrypt_str crypto_buf;
|
||||
#endif
|
||||
};
|
||||
@ -2279,12 +2278,7 @@ extern unsigned ext4_free_clusters_after_init(struct super_block *sb,
|
||||
struct ext4_group_desc *gdp);
|
||||
ext4_fsblk_t ext4_inode_to_goal_block(struct inode *);
|
||||
|
||||
static inline bool ext4_encrypted_inode(struct inode *inode)
|
||||
{
|
||||
return ext4_test_inode_flag(inode, EXT4_INODE_ENCRYPT);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
static inline int ext4_fname_setup_filename(struct inode *dir,
|
||||
const struct qstr *iname,
|
||||
int lookup, struct ext4_filename *fname)
|
||||
|
@ -411,7 +411,7 @@ static inline int ext4_inode_journal_mode(struct inode *inode)
|
||||
(ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) &&
|
||||
!test_opt(inode->i_sb, DELALLOC))) {
|
||||
/* We do not support data journalling for encrypted data */
|
||||
if (S_ISREG(inode->i_mode) && ext4_encrypted_inode(inode))
|
||||
if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode))
|
||||
return EXT4_INODE_ORDERED_DATA_MODE; /* ordered */
|
||||
return EXT4_INODE_JOURNAL_DATA_MODE; /* journal data */
|
||||
}
|
||||
|
@ -3631,7 +3631,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
|
||||
max_zeroout = sbi->s_extent_max_zeroout_kb >>
|
||||
(inode->i_sb->s_blocksize_bits - 10);
|
||||
|
||||
if (ext4_encrypted_inode(inode))
|
||||
if (IS_ENCRYPTED(inode))
|
||||
max_zeroout = 0;
|
||||
|
||||
/*
|
||||
@ -4818,7 +4818,7 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
|
||||
* leave it disabled for encrypted inodes for now. This is a
|
||||
* bug we should fix....
|
||||
*/
|
||||
if (ext4_encrypted_inode(inode) &&
|
||||
if (IS_ENCRYPTED(inode) &&
|
||||
(mode & (FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_INSERT_RANGE |
|
||||
FALLOC_FL_ZERO_RANGE)))
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -771,7 +771,7 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
|
||||
if (unlikely(ext4_forced_shutdown(sbi)))
|
||||
return ERR_PTR(-EIO);
|
||||
|
||||
if ((ext4_encrypted_inode(dir) || DUMMY_ENCRYPTION_ENABLED(sbi)) &&
|
||||
if ((IS_ENCRYPTED(dir) || DUMMY_ENCRYPTION_ENABLED(sbi)) &&
|
||||
(S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) &&
|
||||
!(i_flags & EXT4_EA_INODE_FL)) {
|
||||
err = fscrypt_get_encryption_info(dir);
|
||||
|
@ -415,7 +415,7 @@ int ext4_issue_zeroout(struct inode *inode, ext4_lblk_t lblk, ext4_fsblk_t pblk,
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (ext4_encrypted_inode(inode))
|
||||
if (IS_ENCRYPTED(inode))
|
||||
return fscrypt_zeroout_range(inode, lblk, pblk, len);
|
||||
|
||||
ret = sb_issue_zeroout(inode->i_sb, pblk, len, GFP_NOFS);
|
||||
@ -1150,7 +1150,7 @@ int do_journal_get_write_access(handle_t *handle,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
static int ext4_block_write_begin(struct page *page, loff_t pos, unsigned len,
|
||||
get_block_t *get_block)
|
||||
{
|
||||
@ -1217,8 +1217,7 @@ static int ext4_block_write_begin(struct page *page, loff_t pos, unsigned len,
|
||||
(block_start < from || block_end > to)) {
|
||||
ll_rw_block(REQ_OP_READ, 0, 1, &bh);
|
||||
*wait_bh++ = bh;
|
||||
decrypt = ext4_encrypted_inode(inode) &&
|
||||
S_ISREG(inode->i_mode);
|
||||
decrypt = IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode);
|
||||
}
|
||||
}
|
||||
/*
|
||||
@ -1303,7 +1302,7 @@ retry_journal:
|
||||
/* In case writeback began while the page was unlocked */
|
||||
wait_for_stable_page(page);
|
||||
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
if (ext4_should_dioread_nolock(inode))
|
||||
ret = ext4_block_write_begin(page, pos, len,
|
||||
ext4_get_block_unwritten);
|
||||
@ -3105,7 +3104,7 @@ retry_journal:
|
||||
/* In case writeback began while the page was unlocked */
|
||||
wait_for_stable_page(page);
|
||||
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
ret = ext4_block_write_begin(page, pos, len,
|
||||
ext4_da_get_block_prep);
|
||||
#else
|
||||
@ -3880,8 +3879,8 @@ static ssize_t ext4_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
|
||||
loff_t offset = iocb->ki_pos;
|
||||
ssize_t ret;
|
||||
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode))
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
@ -4065,8 +4064,7 @@ static int __ext4_block_zero_page_range(handle_t *handle,
|
||||
/* Uhhuh. Read error. Complain and punt. */
|
||||
if (!buffer_uptodate(bh))
|
||||
goto unlock;
|
||||
if (S_ISREG(inode->i_mode) &&
|
||||
ext4_encrypted_inode(inode)) {
|
||||
if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode)) {
|
||||
/* We expect the key to be set. */
|
||||
BUG_ON(!fscrypt_has_encryption_key(inode));
|
||||
BUG_ON(blocksize != PAGE_SIZE);
|
||||
@ -4142,7 +4140,7 @@ static int ext4_block_truncate_page(handle_t *handle,
|
||||
struct inode *inode = mapping->host;
|
||||
|
||||
/* If we are processing an encrypted inode during orphan list handling */
|
||||
if (ext4_encrypted_inode(inode) && !fscrypt_has_encryption_key(inode))
|
||||
if (IS_ENCRYPTED(inode) && !fscrypt_has_encryption_key(inode))
|
||||
return 0;
|
||||
|
||||
blocksize = inode->i_sb->s_blocksize;
|
||||
@ -4722,7 +4720,7 @@ static bool ext4_should_use_dax(struct inode *inode)
|
||||
return false;
|
||||
if (ext4_has_inline_data(inode))
|
||||
return false;
|
||||
if (ext4_encrypted_inode(inode))
|
||||
if (ext4_test_inode_flag(inode, EXT4_INODE_ENCRYPT))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@ -5072,7 +5070,7 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
|
||||
ret = -EFSCORRUPTED;
|
||||
goto bad_inode;
|
||||
}
|
||||
if (ext4_encrypted_inode(inode)) {
|
||||
if (IS_ENCRYPTED(inode)) {
|
||||
inode->i_op = &ext4_encrypted_symlink_inode_operations;
|
||||
ext4_set_aops(inode);
|
||||
} else if (ext4_inode_is_fast_symlink(inode)) {
|
||||
|
@ -210,7 +210,7 @@ journal_err_out:
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
static int uuid_is_zero(__u8 u[16])
|
||||
{
|
||||
int i;
|
||||
@ -978,7 +978,7 @@ resizefs_out:
|
||||
return fscrypt_ioctl_set_policy(filp, (const void __user *)arg);
|
||||
|
||||
case EXT4_IOC_GET_ENCRYPTION_PWSALT: {
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
int err, err2;
|
||||
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||
handle_t *handle;
|
||||
|
@ -592,8 +592,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, __u64 orig_blk,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (ext4_encrypted_inode(orig_inode) ||
|
||||
ext4_encrypted_inode(donor_inode)) {
|
||||
if (IS_ENCRYPTED(orig_inode) || IS_ENCRYPTED(donor_inode)) {
|
||||
ext4_msg(orig_inode->i_sb, KERN_ERR,
|
||||
"Online defrag not supported for encrypted files");
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -612,7 +612,7 @@ static struct stats dx_show_leaf(struct inode *dir,
|
||||
{
|
||||
if (show_names)
|
||||
{
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
int len;
|
||||
char *name;
|
||||
struct fscrypt_str fname_crypto_str =
|
||||
@ -621,7 +621,7 @@ static struct stats dx_show_leaf(struct inode *dir,
|
||||
|
||||
name = de->name;
|
||||
len = de->name_len;
|
||||
if (ext4_encrypted_inode(dir))
|
||||
if (IS_ENCRYPTED(dir))
|
||||
res = fscrypt_get_encryption_info(dir);
|
||||
if (res) {
|
||||
printk(KERN_WARNING "Error setting up"
|
||||
@ -984,9 +984,9 @@ static int htree_dirblock_to_tree(struct file *dir_file,
|
||||
top = (struct ext4_dir_entry_2 *) ((char *) de +
|
||||
dir->i_sb->s_blocksize -
|
||||
EXT4_DIR_REC_LEN(0));
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
/* Check if the directory is encrypted */
|
||||
if (ext4_encrypted_inode(dir)) {
|
||||
if (IS_ENCRYPTED(dir)) {
|
||||
err = fscrypt_get_encryption_info(dir);
|
||||
if (err < 0) {
|
||||
brelse(bh);
|
||||
@ -1015,7 +1015,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
|
||||
continue;
|
||||
if (de->inode == 0)
|
||||
continue;
|
||||
if (!ext4_encrypted_inode(dir)) {
|
||||
if (!IS_ENCRYPTED(dir)) {
|
||||
tmp_str.name = de->name;
|
||||
tmp_str.len = de->name_len;
|
||||
err = ext4_htree_store_dirent(dir_file,
|
||||
@ -1047,7 +1047,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
|
||||
}
|
||||
errout:
|
||||
brelse(bh);
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
fscrypt_fname_free_buffer(&fname_crypto_str);
|
||||
#endif
|
||||
return count;
|
||||
@ -1267,7 +1267,7 @@ static inline bool ext4_match(const struct ext4_filename *fname,
|
||||
|
||||
f.usr_fname = fname->usr_fname;
|
||||
f.disk_name = fname->disk_name;
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
f.crypto_buf = fname->crypto_buf;
|
||||
#endif
|
||||
return fscrypt_match_name(&f, de->name, de->name_len);
|
||||
@ -1498,7 +1498,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
|
||||
ext4_lblk_t block;
|
||||
int retval;
|
||||
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
*res_dir = NULL;
|
||||
#endif
|
||||
frame = dx_probe(fname, dir, NULL, frames);
|
||||
@ -1578,7 +1578,7 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
|
||||
ino);
|
||||
return ERR_PTR(-EFSCORRUPTED);
|
||||
}
|
||||
if (!IS_ERR(inode) && ext4_encrypted_inode(dir) &&
|
||||
if (!IS_ERR(inode) && IS_ENCRYPTED(dir) &&
|
||||
(S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) &&
|
||||
!fscrypt_has_permitted_context(dir, inode)) {
|
||||
ext4_warning(inode->i_sb,
|
||||
|
@ -67,7 +67,7 @@ static void ext4_finish_bio(struct bio *bio)
|
||||
|
||||
bio_for_each_segment_all(bvec, bio, i, iter_all) {
|
||||
struct page *page = bvec->bv_page;
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
struct page *data_page = NULL;
|
||||
#endif
|
||||
struct buffer_head *bh, *head;
|
||||
@ -79,7 +79,7 @@ static void ext4_finish_bio(struct bio *bio)
|
||||
if (!page)
|
||||
continue;
|
||||
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
if (!page->mapping) {
|
||||
/* The bounce data pages are unmapped. */
|
||||
data_page = page;
|
||||
@ -112,7 +112,7 @@ static void ext4_finish_bio(struct bio *bio)
|
||||
bit_spin_unlock(BH_Uptodate_Lock, &head->b_state);
|
||||
local_irq_restore(flags);
|
||||
if (!under_io) {
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
if (data_page)
|
||||
fscrypt_restore_control_page(data_page);
|
||||
#endif
|
||||
@ -478,8 +478,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
|
||||
|
||||
bh = head = page_buffers(page);
|
||||
|
||||
if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode) &&
|
||||
nr_to_submit) {
|
||||
if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode) && nr_to_submit) {
|
||||
gfp_t gfp_flags = GFP_NOFS;
|
||||
|
||||
retry_encrypt:
|
||||
|
@ -49,7 +49,7 @@
|
||||
|
||||
static inline bool ext4_bio_encrypted(struct bio *bio)
|
||||
{
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
return unlikely(bio->bi_private != NULL);
|
||||
#else
|
||||
return false;
|
||||
@ -243,8 +243,7 @@ int ext4_mpage_readpages(struct address_space *mapping,
|
||||
if (bio == NULL) {
|
||||
struct fscrypt_ctx *ctx = NULL;
|
||||
|
||||
if (ext4_encrypted_inode(inode) &&
|
||||
S_ISREG(inode->i_mode)) {
|
||||
if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode)) {
|
||||
ctx = fscrypt_get_ctx(inode, GFP_NOFS);
|
||||
if (IS_ERR(ctx))
|
||||
goto set_error_page;
|
||||
|
@ -1232,7 +1232,7 @@ static int bdev_try_to_free_page(struct super_block *sb, struct page *page,
|
||||
return try_to_free_buffers(page);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
static int ext4_get_context(struct inode *inode, void *ctx, size_t len)
|
||||
{
|
||||
return ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION,
|
||||
@ -1922,7 +1922,7 @@ 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_EXT4_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
sbi->s_mount_flags |= EXT4_MF_TEST_DUMMY_ENCRYPTION;
|
||||
ext4_msg(sb, KERN_WARNING,
|
||||
"Test dummy encryption mode enabled");
|
||||
@ -4167,7 +4167,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
||||
sb->s_op = &ext4_sops;
|
||||
sb->s_export_op = &ext4_export_ops;
|
||||
sb->s_xattr = ext4_xattr_handlers;
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
sb->s_cop = &ext4_cryptops;
|
||||
#endif
|
||||
#ifdef CONFIG_QUOTA
|
||||
|
@ -224,7 +224,7 @@ static struct attribute *ext4_attrs[] = {
|
||||
EXT4_ATTR_FEATURE(lazy_itable_init);
|
||||
EXT4_ATTR_FEATURE(batched_discard);
|
||||
EXT4_ATTR_FEATURE(meta_bg_resize);
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
EXT4_ATTR_FEATURE(encryption);
|
||||
#endif
|
||||
EXT4_ATTR_FEATURE(metadata_csum_seed);
|
||||
@ -233,7 +233,7 @@ static struct attribute *ext4_feat_attrs[] = {
|
||||
ATTR_LIST(lazy_itable_init),
|
||||
ATTR_LIST(batched_discard),
|
||||
ATTR_LIST(meta_bg_resize),
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
ATTR_LIST(encryption),
|
||||
#endif
|
||||
ATTR_LIST(metadata_csum_seed),
|
||||
|
@ -3,6 +3,7 @@ config F2FS_FS
|
||||
depends on BLOCK
|
||||
select CRYPTO
|
||||
select CRYPTO_CRC32
|
||||
select F2FS_FS_XATTR if FS_ENCRYPTION
|
||||
help
|
||||
F2FS is based on Log-structured File System (LFS), which supports
|
||||
versatile "flash-friendly" features. The design has been focused on
|
||||
@ -70,17 +71,6 @@ config F2FS_CHECK_FS
|
||||
|
||||
If you want to improve the performance, say N.
|
||||
|
||||
config F2FS_FS_ENCRYPTION
|
||||
bool "F2FS Encryption"
|
||||
depends on F2FS_FS
|
||||
depends on F2FS_FS_XATTR
|
||||
select FS_ENCRYPTION
|
||||
help
|
||||
Enable encryption of f2fs files and directories. This
|
||||
feature is similar to ecryptfs, but it is more memory
|
||||
efficient since it avoids caching the encrypted and
|
||||
decrypted pages in the page cache.
|
||||
|
||||
config F2FS_IO_TRACE
|
||||
bool "F2FS IO tracer"
|
||||
depends on F2FS_FS
|
||||
|
@ -1468,7 +1468,7 @@ next:
|
||||
}
|
||||
|
||||
if (size) {
|
||||
if (f2fs_encrypted_inode(inode))
|
||||
if (IS_ENCRYPTED(inode))
|
||||
flags |= FIEMAP_EXTENT_DATA_ENCRYPTED;
|
||||
|
||||
ret = fiemap_fill_next_extent(fieinfo, logical,
|
||||
@ -1739,7 +1739,7 @@ static inline bool check_inplace_update_policy(struct inode *inode,
|
||||
if (policy & (0x1 << F2FS_IPU_ASYNC) &&
|
||||
fio && fio->op == REQ_OP_WRITE &&
|
||||
!(fio->op_flags & REQ_SYNC) &&
|
||||
!f2fs_encrypted_inode(inode))
|
||||
!IS_ENCRYPTED(inode))
|
||||
return true;
|
||||
|
||||
/* this is only set during fdatasync */
|
||||
|
@ -385,7 +385,7 @@ struct page *f2fs_init_inode_metadata(struct inode *inode, struct inode *dir,
|
||||
if (err)
|
||||
goto put_error;
|
||||
|
||||
if ((f2fs_encrypted_inode(dir) || dummy_encrypt) &&
|
||||
if ((IS_ENCRYPTED(dir) || dummy_encrypt) &&
|
||||
f2fs_may_encrypt(inode)) {
|
||||
err = fscrypt_inherit_context(dir, inode, page, false);
|
||||
if (err)
|
||||
@ -399,7 +399,7 @@ struct page *f2fs_init_inode_metadata(struct inode *inode, struct inode *dir,
|
||||
|
||||
if (new_name) {
|
||||
init_dent_inode(new_name, page);
|
||||
if (f2fs_encrypted_inode(dir))
|
||||
if (IS_ENCRYPTED(dir))
|
||||
file_set_enc_name(inode);
|
||||
}
|
||||
|
||||
@ -819,7 +819,7 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (f2fs_encrypted_inode(d->inode)) {
|
||||
if (IS_ENCRYPTED(d->inode)) {
|
||||
int save_len = fstr->len;
|
||||
|
||||
err = fscrypt_fname_disk_to_usr(d->inode,
|
||||
@ -862,7 +862,7 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
|
||||
struct fscrypt_str fstr = FSTR_INIT(NULL, 0);
|
||||
int err = 0;
|
||||
|
||||
if (f2fs_encrypted_inode(inode)) {
|
||||
if (IS_ENCRYPTED(inode)) {
|
||||
err = fscrypt_get_encryption_info(inode);
|
||||
if (err && err != -ENOKEY)
|
||||
goto out;
|
||||
@ -924,7 +924,7 @@ out:
|
||||
|
||||
static int f2fs_dir_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
if (f2fs_encrypted_inode(inode))
|
||||
if (IS_ENCRYPTED(inode))
|
||||
return fscrypt_get_encryption_info(inode) ? -EACCES : 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include <linux/quotaops.h>
|
||||
#include <crypto/hash.h>
|
||||
|
||||
#define __FS_HAS_ENCRYPTION IS_ENABLED(CONFIG_F2FS_FS_ENCRYPTION)
|
||||
#include <linux/fscrypt.h>
|
||||
|
||||
#ifdef CONFIG_F2FS_CHECK_FS
|
||||
@ -1137,7 +1136,7 @@ enum fsync_mode {
|
||||
FSYNC_MODE_NOBARRIER, /* fsync behaves nobarrier based on posix */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_F2FS_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
#define DUMMY_ENCRYPTION_ENABLED(sbi) \
|
||||
(unlikely(F2FS_OPTION(sbi).test_dummy_encryption))
|
||||
#else
|
||||
@ -3463,19 +3462,14 @@ void f2fs_unregister_sysfs(struct f2fs_sb_info *sbi);
|
||||
/*
|
||||
* crypto support
|
||||
*/
|
||||
static inline bool f2fs_encrypted_inode(struct inode *inode)
|
||||
{
|
||||
return file_is_encrypt(inode);
|
||||
}
|
||||
|
||||
static inline bool f2fs_encrypted_file(struct inode *inode)
|
||||
{
|
||||
return f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode);
|
||||
return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode);
|
||||
}
|
||||
|
||||
static inline void f2fs_set_encrypted_inode(struct inode *inode)
|
||||
{
|
||||
#ifdef CONFIG_F2FS_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
file_set_encrypt(inode);
|
||||
f2fs_set_inode_flags(inode);
|
||||
#endif
|
||||
@ -3554,7 +3548,7 @@ static inline void set_opt_mode(struct f2fs_sb_info *sbi, unsigned int mt)
|
||||
|
||||
static inline bool f2fs_may_encrypt(struct inode *inode)
|
||||
{
|
||||
#ifdef CONFIG_F2FS_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
umode_t mode = inode->i_mode;
|
||||
|
||||
return (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode));
|
||||
|
@ -582,7 +582,7 @@ truncate_out:
|
||||
zero_user(page, offset, PAGE_SIZE - offset);
|
||||
|
||||
/* An encrypted inode should have a key and truncate the last page. */
|
||||
f2fs_bug_on(F2FS_I_SB(inode), cache_only && f2fs_encrypted_inode(inode));
|
||||
f2fs_bug_on(F2FS_I_SB(inode), cache_only && IS_ENCRYPTED(inode));
|
||||
if (!cache_only)
|
||||
set_page_dirty(page);
|
||||
f2fs_put_page(page, 1);
|
||||
@ -711,7 +711,7 @@ int f2fs_getattr(const struct path *path, struct kstat *stat,
|
||||
stat->attributes |= STATX_ATTR_APPEND;
|
||||
if (flags & F2FS_COMPR_FL)
|
||||
stat->attributes |= STATX_ATTR_COMPRESSED;
|
||||
if (f2fs_encrypted_inode(inode))
|
||||
if (IS_ENCRYPTED(inode))
|
||||
stat->attributes |= STATX_ATTR_ENCRYPTED;
|
||||
if (flags & F2FS_IMMUTABLE_FL)
|
||||
stat->attributes |= STATX_ATTR_IMMUTABLE;
|
||||
@ -1563,7 +1563,7 @@ static long f2fs_fallocate(struct file *file, int mode,
|
||||
if (!S_ISREG(inode->i_mode))
|
||||
return -EINVAL;
|
||||
|
||||
if (f2fs_encrypted_inode(inode) &&
|
||||
if (IS_ENCRYPTED(inode) &&
|
||||
(mode & (FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_INSERT_RANGE)))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
@ -1647,7 +1647,7 @@ static int f2fs_ioc_getflags(struct file *filp, unsigned long arg)
|
||||
struct f2fs_inode_info *fi = F2FS_I(inode);
|
||||
unsigned int flags = fi->i_flags;
|
||||
|
||||
if (f2fs_encrypted_inode(inode))
|
||||
if (IS_ENCRYPTED(inode))
|
||||
flags |= F2FS_ENCRYPT_FL;
|
||||
if (f2fs_has_inline_data(inode) || f2fs_has_inline_dentry(inode))
|
||||
flags |= F2FS_INLINE_DATA_FL;
|
||||
@ -2414,7 +2414,7 @@ static int f2fs_move_file_range(struct file *file_in, loff_t pos_in,
|
||||
if (!S_ISREG(src->i_mode) || !S_ISREG(dst->i_mode))
|
||||
return -EINVAL;
|
||||
|
||||
if (f2fs_encrypted_inode(src) || f2fs_encrypted_inode(dst))
|
||||
if (IS_ENCRYPTED(src) || IS_ENCRYPTED(dst))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (src == dst) {
|
||||
|
@ -43,7 +43,7 @@ void f2fs_set_inode_flags(struct inode *inode)
|
||||
new_fl |= S_NOATIME;
|
||||
if (flags & F2FS_DIRSYNC_FL)
|
||||
new_fl |= S_DIRSYNC;
|
||||
if (f2fs_encrypted_inode(inode))
|
||||
if (file_is_encrypt(inode))
|
||||
new_fl |= S_ENCRYPTED;
|
||||
inode_set_flags(inode, new_fl,
|
||||
S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|
|
||||
@ -453,7 +453,7 @@ make_now:
|
||||
inode->i_mapping->a_ops = &f2fs_dblock_aops;
|
||||
inode_nohighmem(inode);
|
||||
} else if (S_ISLNK(inode->i_mode)) {
|
||||
if (f2fs_encrypted_inode(inode))
|
||||
if (file_is_encrypt(inode))
|
||||
inode->i_op = &f2fs_encrypted_symlink_inode_operations;
|
||||
else
|
||||
inode->i_op = &f2fs_symlink_inode_operations;
|
||||
|
@ -75,7 +75,7 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
|
||||
set_inode_flag(inode, FI_NEW_INODE);
|
||||
|
||||
/* If the directory encrypted, then we should encrypt the inode. */
|
||||
if ((f2fs_encrypted_inode(dir) || DUMMY_ENCRYPTION_ENABLED(sbi)) &&
|
||||
if ((IS_ENCRYPTED(dir) || DUMMY_ENCRYPTION_ENABLED(sbi)) &&
|
||||
f2fs_may_encrypt(inode))
|
||||
f2fs_set_encrypted_inode(inode);
|
||||
|
||||
@ -476,7 +476,7 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry,
|
||||
if (err)
|
||||
goto out_iput;
|
||||
}
|
||||
if (f2fs_encrypted_inode(dir) &&
|
||||
if (IS_ENCRYPTED(dir) &&
|
||||
(S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) &&
|
||||
!fscrypt_has_permitted_context(dir, inode)) {
|
||||
f2fs_msg(inode->i_sb, KERN_WARNING,
|
||||
@ -803,7 +803,7 @@ static int f2fs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||
if (unlikely(f2fs_cp_error(sbi)))
|
||||
return -EIO;
|
||||
|
||||
if (f2fs_encrypted_inode(dir) || DUMMY_ENCRYPTION_ENABLED(sbi)) {
|
||||
if (IS_ENCRYPTED(dir) || DUMMY_ENCRYPTION_ENABLED(sbi)) {
|
||||
int err = fscrypt_get_encryption_info(dir);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -757,7 +757,7 @@ static int parse_options(struct super_block *sb, char *options)
|
||||
kvfree(name);
|
||||
break;
|
||||
case Opt_test_dummy_encryption:
|
||||
#ifdef CONFIG_F2FS_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
if (!f2fs_sb_has_encrypt(sbi)) {
|
||||
f2fs_msg(sb, KERN_ERR, "Encrypt feature is off");
|
||||
return -EINVAL;
|
||||
@ -1390,7 +1390,7 @@ 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_F2FS_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
if (F2FS_OPTION(sbi).test_dummy_encryption)
|
||||
seq_puts(seq, ",test_dummy_encryption");
|
||||
#endif
|
||||
@ -2154,7 +2154,7 @@ static const struct super_operations f2fs_sops = {
|
||||
.remount_fs = f2fs_remount,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_F2FS_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
static int f2fs_get_context(struct inode *inode, void *ctx, size_t len)
|
||||
{
|
||||
return f2fs_getxattr(inode, F2FS_XATTR_INDEX_ENCRYPTION,
|
||||
@ -3116,7 +3116,7 @@ try_onemore:
|
||||
#endif
|
||||
|
||||
sb->s_op = &f2fs_sops;
|
||||
#ifdef CONFIG_F2FS_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
sb->s_cop = &f2fs_cryptops;
|
||||
#endif
|
||||
sb->s_xattr = f2fs_xattr_handlers;
|
||||
|
@ -431,7 +431,7 @@ F2FS_GENERAL_RO_ATTR(lifetime_write_kbytes);
|
||||
F2FS_GENERAL_RO_ATTR(features);
|
||||
F2FS_GENERAL_RO_ATTR(current_reserved_blocks);
|
||||
|
||||
#ifdef CONFIG_F2FS_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
F2FS_FEATURE_RO_ATTR(encryption, FEAT_CRYPTO);
|
||||
#endif
|
||||
#ifdef CONFIG_BLK_DEV_ZONED
|
||||
@ -492,7 +492,7 @@ static struct attribute *f2fs_attrs[] = {
|
||||
};
|
||||
|
||||
static struct attribute *f2fs_feat_attrs[] = {
|
||||
#ifdef CONFIG_F2FS_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
ATTR_LIST(encryption),
|
||||
#endif
|
||||
#ifdef CONFIG_BLK_DEV_ZONED
|
||||
|
@ -8,6 +8,7 @@ config UBIFS_FS
|
||||
select CRYPTO_LZO if UBIFS_FS_LZO
|
||||
select CRYPTO_DEFLATE if UBIFS_FS_ZLIB
|
||||
select CRYPTO_HASH_INFO
|
||||
select UBIFS_FS_XATTR if FS_ENCRYPTION
|
||||
depends on MTD_UBI
|
||||
help
|
||||
UBIFS is a file system for flash devices which works on top of UBI.
|
||||
@ -60,17 +61,6 @@ config UBIFS_FS_XATTR
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config UBIFS_FS_ENCRYPTION
|
||||
bool "UBIFS Encryption"
|
||||
depends on UBIFS_FS_XATTR && BLOCK
|
||||
select FS_ENCRYPTION
|
||||
default n
|
||||
help
|
||||
Enable encryption of UBIFS files and directories. This
|
||||
feature is similar to ecryptfs, but it is more memory
|
||||
efficient since it avoids caching the encrypted and
|
||||
decrypted pages in the page cache.
|
||||
|
||||
config UBIFS_FS_SECURITY
|
||||
bool "UBIFS Security Labels"
|
||||
depends on UBIFS_FS_XATTR
|
||||
|
@ -6,6 +6,6 @@ ubifs-y += tnc.o master.o scan.o replay.o log.o commit.o gc.o orphan.o
|
||||
ubifs-y += budget.o find.o tnc_commit.o compress.o lpt.o lprops.o
|
||||
ubifs-y += recovery.o ioctl.o lpt_commit.o tnc_misc.o debug.o
|
||||
ubifs-y += misc.o
|
||||
ubifs-$(CONFIG_UBIFS_FS_ENCRYPTION) += crypto.o
|
||||
ubifs-$(CONFIG_FS_ENCRYPTION) += crypto.o
|
||||
ubifs-$(CONFIG_UBIFS_FS_XATTR) += xattr.o
|
||||
ubifs-$(CONFIG_UBIFS_FS_AUTHENTICATION) += auth.o
|
||||
|
@ -185,7 +185,7 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
return err;
|
||||
}
|
||||
case FS_IOC_SET_ENCRYPTION_POLICY: {
|
||||
#ifdef CONFIG_UBIFS_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
struct ubifs_info *c = inode->i_sb->s_fs_info;
|
||||
|
||||
err = ubifs_enable_encryption(c);
|
||||
@ -198,7 +198,7 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
#endif
|
||||
}
|
||||
case FS_IOC_GET_ENCRYPTION_POLICY: {
|
||||
#ifdef CONFIG_UBIFS_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
return fscrypt_ioctl_get_policy(file, (void __user *)arg);
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -748,7 +748,7 @@ int ubifs_read_superblock(struct ubifs_info *c)
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_UBIFS_FS_ENCRYPTION
|
||||
#ifndef CONFIG_FS_ENCRYPTION
|
||||
if (c->encrypted) {
|
||||
ubifs_err(c, "file system contains encrypted files but UBIFS"
|
||||
" was built without crypto support.");
|
||||
|
@ -2146,7 +2146,7 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
#ifdef CONFIG_UBIFS_FS_XATTR
|
||||
sb->s_xattr = ubifs_xattr_handlers;
|
||||
#endif
|
||||
#ifdef CONFIG_UBIFS_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
sb->s_cop = &ubifs_crypt_operations;
|
||||
#endif
|
||||
|
||||
|
@ -43,7 +43,6 @@
|
||||
#include <crypto/hash.h>
|
||||
#include <crypto/algapi.h>
|
||||
|
||||
#define __FS_HAS_ENCRYPTION IS_ENABLED(CONFIG_UBIFS_FS_ENCRYPTION)
|
||||
#include <linux/fscrypt.h>
|
||||
|
||||
#include "ubifs-media.h"
|
||||
@ -142,7 +141,7 @@
|
||||
*/
|
||||
#define WORST_COMPR_FACTOR 2
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_ENCRYPTION
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
#define UBIFS_CIPHER_BLOCK_SIZE FS_CRYPTO_BLOCK_SIZE
|
||||
#else
|
||||
#define UBIFS_CIPHER_BLOCK_SIZE 0
|
||||
@ -2072,7 +2071,7 @@ int ubifs_decompress(const struct ubifs_info *c, const void *buf, int len,
|
||||
#include "misc.h"
|
||||
#include "key.h"
|
||||
|
||||
#ifndef CONFIG_UBIFS_FS_ENCRYPTION
|
||||
#ifndef CONFIG_FS_ENCRYPTION
|
||||
static inline int ubifs_encrypt(const struct inode *inode,
|
||||
struct ubifs_data_node *dn,
|
||||
unsigned int in_len, unsigned int *out_len,
|
||||
|
@ -708,7 +708,7 @@ struct inode {
|
||||
struct fsnotify_mark_connector __rcu *i_fsnotify_marks;
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_FS_ENCRYPTION)
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
struct fscrypt_info *i_crypt_info;
|
||||
#endif
|
||||
|
||||
@ -1415,7 +1415,7 @@ struct super_block {
|
||||
void *s_security;
|
||||
#endif
|
||||
const struct xattr_handler **s_xattr;
|
||||
#if IS_ENABLED(CONFIG_FS_ENCRYPTION)
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
const struct fscrypt_operations *s_cop;
|
||||
#endif
|
||||
struct hlist_bl_head s_roots; /* alternate root dentries for NFS */
|
||||
|
@ -2,9 +2,8 @@
|
||||
/*
|
||||
* fscrypt.h: declarations for per-file encryption
|
||||
*
|
||||
* Filesystems that implement per-file encryption include this header
|
||||
* file with the __FS_HAS_ENCRYPTION set according to whether that filesystem
|
||||
* is being built with encryption support or not.
|
||||
* Filesystems that implement per-file encryption must include this header
|
||||
* file.
|
||||
*
|
||||
* Copyright (C) 2015, Google, Inc.
|
||||
*
|
||||
@ -15,6 +14,8 @@
|
||||
#define _LINUX_FSCRYPT_H
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define FS_CRYPTO_BLOCK_SIZE 16
|
||||
|
||||
@ -42,11 +43,410 @@ struct fscrypt_name {
|
||||
/* Maximum value for the third parameter of fscrypt_operations.set_context(). */
|
||||
#define FSCRYPT_SET_CONTEXT_MAX_SIZE 28
|
||||
|
||||
#if __FS_HAS_ENCRYPTION
|
||||
#include <linux/fscrypt_supp.h>
|
||||
#else
|
||||
#include <linux/fscrypt_notsupp.h>
|
||||
#endif
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
/*
|
||||
* fscrypt superblock flags
|
||||
*/
|
||||
#define FS_CFLG_OWN_PAGES (1U << 1)
|
||||
|
||||
/*
|
||||
* crypto operations for filesystems
|
||||
*/
|
||||
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 *);
|
||||
unsigned int max_namelen;
|
||||
};
|
||||
|
||||
struct fscrypt_ctx {
|
||||
union {
|
||||
struct {
|
||||
struct page *bounce_page; /* Ciphertext page */
|
||||
struct page *control_page; /* Original page */
|
||||
} w;
|
||||
struct {
|
||||
struct bio *bio;
|
||||
struct work_struct work;
|
||||
} r;
|
||||
struct list_head free_list; /* Free list */
|
||||
};
|
||||
u8 flags; /* Flags */
|
||||
};
|
||||
|
||||
static inline bool fscrypt_has_encryption_key(const struct inode *inode)
|
||||
{
|
||||
return (inode->i_crypt_info != NULL);
|
||||
}
|
||||
|
||||
static inline bool fscrypt_dummy_context_enabled(struct inode *inode)
|
||||
{
|
||||
return inode->i_sb->s_cop->dummy_context &&
|
||||
inode->i_sb->s_cop->dummy_context(inode);
|
||||
}
|
||||
|
||||
/* crypto.c */
|
||||
extern void fscrypt_enqueue_decrypt_work(struct work_struct *);
|
||||
extern struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *, gfp_t);
|
||||
extern void fscrypt_release_ctx(struct fscrypt_ctx *);
|
||||
extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *,
|
||||
unsigned int, unsigned int,
|
||||
u64, gfp_t);
|
||||
extern int fscrypt_decrypt_page(const struct inode *, struct page *, unsigned int,
|
||||
unsigned int, u64);
|
||||
|
||||
static inline struct page *fscrypt_control_page(struct page *page)
|
||||
{
|
||||
return ((struct fscrypt_ctx *)page_private(page))->w.control_page;
|
||||
}
|
||||
|
||||
extern void fscrypt_restore_control_page(struct 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_has_permitted_context(struct inode *, struct inode *);
|
||||
extern int fscrypt_inherit_context(struct inode *, struct inode *,
|
||||
void *, bool);
|
||||
/* keyinfo.c */
|
||||
extern int fscrypt_get_encryption_info(struct inode *);
|
||||
extern void fscrypt_put_encryption_info(struct inode *);
|
||||
|
||||
/* fname.c */
|
||||
extern int fscrypt_setup_filename(struct inode *, const struct qstr *,
|
||||
int lookup, struct fscrypt_name *);
|
||||
|
||||
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(struct inode *, u32, u32,
|
||||
const struct fscrypt_str *, struct fscrypt_str *);
|
||||
|
||||
#define FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE 32
|
||||
|
||||
/* Extracts the second-to-last ciphertext block; see explanation below */
|
||||
#define FSCRYPT_FNAME_DIGEST(name, len) \
|
||||
((name) + round_down((len) - FS_CRYPTO_BLOCK_SIZE - 1, \
|
||||
FS_CRYPTO_BLOCK_SIZE))
|
||||
|
||||
#define FSCRYPT_FNAME_DIGEST_SIZE FS_CRYPTO_BLOCK_SIZE
|
||||
|
||||
/**
|
||||
* fscrypt_digested_name - alternate identifier for an on-disk filename
|
||||
*
|
||||
* When userspace lists an encrypted directory without access to the key,
|
||||
* filenames whose ciphertext is longer than FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE
|
||||
* bytes are shown in this abbreviated form (base64-encoded) rather than as the
|
||||
* full ciphertext (base64-encoded). This is necessary to allow supporting
|
||||
* filenames up to NAME_MAX bytes, since base64 encoding expands the length.
|
||||
*
|
||||
* To make it possible for filesystems to still find the correct directory entry
|
||||
* despite not knowing the full on-disk name, we encode any filesystem-specific
|
||||
* 'hash' and/or 'minor_hash' which the filesystem may need for its lookups,
|
||||
* followed by the second-to-last ciphertext block of the filename. Due to the
|
||||
* use of the CBC-CTS encryption mode, the second-to-last ciphertext block
|
||||
* depends on the full plaintext. (Note that ciphertext stealing causes the
|
||||
* last two blocks to appear "flipped".) This makes accidental collisions very
|
||||
* unlikely: just a 1 in 2^128 chance for two filenames to collide even if they
|
||||
* share the same filesystem-specific hashes.
|
||||
*
|
||||
* However, this scheme isn't immune to intentional collisions, which can be
|
||||
* created by anyone able to create arbitrary plaintext filenames and view them
|
||||
* without the key. Making the "digest" be a real cryptographic hash like
|
||||
* SHA-256 over the full ciphertext would prevent this, although it would be
|
||||
* less efficient and harder to implement, especially since the filesystem would
|
||||
* need to calculate it for each directory entry examined during a search.
|
||||
*/
|
||||
struct fscrypt_digested_name {
|
||||
u32 hash;
|
||||
u32 minor_hash;
|
||||
u8 digest[FSCRYPT_FNAME_DIGEST_SIZE];
|
||||
};
|
||||
|
||||
/**
|
||||
* fscrypt_match_name() - test whether the given name matches a directory entry
|
||||
* @fname: the name being searched for
|
||||
* @de_name: the name from the directory entry
|
||||
* @de_name_len: the length of @de_name in bytes
|
||||
*
|
||||
* Normally @fname->disk_name will be set, and in that case we simply compare
|
||||
* that to the name stored in the directory entry. The only exception is that
|
||||
* if we don't have the key for an encrypted directory and a filename in it is
|
||||
* very long, then we won't have the full disk_name and we'll instead need to
|
||||
* match against the fscrypt_digested_name.
|
||||
*
|
||||
* Return: %true if the name matches, otherwise %false.
|
||||
*/
|
||||
static inline bool fscrypt_match_name(const struct fscrypt_name *fname,
|
||||
const u8 *de_name, u32 de_name_len)
|
||||
{
|
||||
if (unlikely(!fname->disk_name.name)) {
|
||||
const struct fscrypt_digested_name *n =
|
||||
(const void *)fname->crypto_buf.name;
|
||||
if (WARN_ON_ONCE(fname->usr_fname->name[0] != '_'))
|
||||
return false;
|
||||
if (de_name_len <= FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE)
|
||||
return false;
|
||||
return !memcmp(FSCRYPT_FNAME_DIGEST(de_name, de_name_len),
|
||||
n->digest, FSCRYPT_FNAME_DIGEST_SIZE);
|
||||
}
|
||||
|
||||
if (de_name_len != fname->disk_name.len)
|
||||
return false;
|
||||
return !memcmp(de_name, fname->disk_name.name, fname->disk_name.len);
|
||||
}
|
||||
|
||||
/* bio.c */
|
||||
extern void fscrypt_decrypt_bio(struct bio *);
|
||||
extern void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx,
|
||||
struct bio *bio);
|
||||
extern void fscrypt_pullback_bio_page(struct page **, bool);
|
||||
extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t,
|
||||
unsigned int);
|
||||
|
||||
/* hooks.c */
|
||||
extern int fscrypt_file_open(struct inode *inode, struct file *filp);
|
||||
extern int __fscrypt_prepare_link(struct inode *inode, struct inode *dir);
|
||||
extern int __fscrypt_prepare_rename(struct inode *old_dir,
|
||||
struct dentry *old_dentry,
|
||||
struct inode *new_dir,
|
||||
struct dentry *new_dentry,
|
||||
unsigned int flags);
|
||||
extern int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry);
|
||||
extern int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len,
|
||||
unsigned int max_len,
|
||||
struct fscrypt_str *disk_link);
|
||||
extern int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
|
||||
unsigned int len,
|
||||
struct fscrypt_str *disk_link);
|
||||
extern const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
|
||||
unsigned int max_size,
|
||||
struct delayed_call *done);
|
||||
#else /* !CONFIG_FS_ENCRYPTION */
|
||||
|
||||
static inline bool fscrypt_has_encryption_key(const struct inode *inode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool fscrypt_dummy_context_enabled(struct inode *inode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* crypto.c */
|
||||
static inline void fscrypt_enqueue_decrypt_work(struct work_struct *work)
|
||||
{
|
||||
}
|
||||
|
||||
static inline struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *inode,
|
||||
gfp_t gfp_flags)
|
||||
{
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline void fscrypt_release_ctx(struct fscrypt_ctx *ctx)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline struct page *fscrypt_encrypt_page(const struct inode *inode,
|
||||
struct page *page,
|
||||
unsigned int len,
|
||||
unsigned int offs,
|
||||
u64 lblk_num, gfp_t gfp_flags)
|
||||
{
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline int fscrypt_decrypt_page(const struct inode *inode,
|
||||
struct page *page,
|
||||
unsigned int len, unsigned int offs,
|
||||
u64 lblk_num)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline struct page *fscrypt_control_page(struct page *page)
|
||||
{
|
||||
WARN_ON_ONCE(1);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static inline void fscrypt_restore_control_page(struct page *page)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* policy.c */
|
||||
static inline int fscrypt_ioctl_set_policy(struct file *filp,
|
||||
const void __user *arg)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int fscrypt_has_permitted_context(struct inode *parent,
|
||||
struct inode *child)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int fscrypt_inherit_context(struct inode *parent,
|
||||
struct inode *child,
|
||||
void *fs_data, bool preload)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* keyinfo.c */
|
||||
static inline int fscrypt_get_encryption_info(struct inode *inode)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline void fscrypt_put_encryption_info(struct inode *inode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* fname.c */
|
||||
static inline int fscrypt_setup_filename(struct inode *dir,
|
||||
const struct qstr *iname,
|
||||
int lookup, struct fscrypt_name *fname)
|
||||
{
|
||||
if (IS_ENCRYPTED(dir))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
memset(fname, 0, sizeof(struct fscrypt_name));
|
||||
fname->usr_fname = iname;
|
||||
fname->disk_name.name = (unsigned char *)iname->name;
|
||||
fname->disk_name.len = iname->len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void fscrypt_free_filename(struct fscrypt_name *fname)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int fscrypt_fname_alloc_buffer(const struct inode *inode,
|
||||
u32 max_encrypted_len,
|
||||
struct fscrypt_str *crypto_str)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline void fscrypt_fname_free_buffer(struct fscrypt_str *crypto_str)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int fscrypt_fname_disk_to_usr(struct inode *inode,
|
||||
u32 hash, u32 minor_hash,
|
||||
const struct fscrypt_str *iname,
|
||||
struct fscrypt_str *oname)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline bool fscrypt_match_name(const struct fscrypt_name *fname,
|
||||
const u8 *de_name, u32 de_name_len)
|
||||
{
|
||||
/* Encryption support disabled; use standard comparison */
|
||||
if (de_name_len != fname->disk_name.len)
|
||||
return false;
|
||||
return !memcmp(de_name, fname->disk_name.name, fname->disk_name.len);
|
||||
}
|
||||
|
||||
/* bio.c */
|
||||
static inline void fscrypt_decrypt_bio(struct bio *bio)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx,
|
||||
struct bio *bio)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void fscrypt_pullback_bio_page(struct page **page, bool restore)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
|
||||
sector_t pblk, unsigned int len)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* hooks.c */
|
||||
|
||||
static inline int fscrypt_file_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
if (IS_ENCRYPTED(inode))
|
||||
return -EOPNOTSUPP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int __fscrypt_prepare_link(struct inode *inode,
|
||||
struct inode *dir)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int __fscrypt_prepare_rename(struct inode *old_dir,
|
||||
struct dentry *old_dentry,
|
||||
struct inode *new_dir,
|
||||
struct dentry *new_dentry,
|
||||
unsigned int flags)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int __fscrypt_prepare_lookup(struct inode *dir,
|
||||
struct dentry *dentry)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int __fscrypt_prepare_symlink(struct inode *dir,
|
||||
unsigned int len,
|
||||
unsigned int max_len,
|
||||
struct fscrypt_str *disk_link)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
|
||||
static inline int __fscrypt_encrypt_symlink(struct inode *inode,
|
||||
const char *target,
|
||||
unsigned int len,
|
||||
struct fscrypt_str *disk_link)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline const char *fscrypt_get_symlink(struct inode *inode,
|
||||
const void *caddr,
|
||||
unsigned int max_size,
|
||||
struct delayed_call *done)
|
||||
{
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
#endif /* !CONFIG_FS_ENCRYPTION */
|
||||
|
||||
/**
|
||||
* fscrypt_require_key - require an inode's encryption key
|
||||
@ -89,7 +489,7 @@ static inline int fscrypt_require_key(struct inode *inode)
|
||||
* in an encrypted directory tree use the same encryption policy.
|
||||
*
|
||||
* Return: 0 on success, -ENOKEY if the directory's encryption key is missing,
|
||||
* -EPERM if the link would result in an inconsistent encryption policy, or
|
||||
* -EXDEV if the link would result in an inconsistent encryption policy, or
|
||||
* another -errno code.
|
||||
*/
|
||||
static inline int fscrypt_prepare_link(struct dentry *old_dentry,
|
||||
@ -119,7 +519,7 @@ static inline int fscrypt_prepare_link(struct dentry *old_dentry,
|
||||
* We also verify that the rename will not violate the constraint that all files
|
||||
* in an encrypted directory tree use the same encryption policy.
|
||||
*
|
||||
* Return: 0 on success, -ENOKEY if an encryption key is missing, -EPERM if the
|
||||
* Return: 0 on success, -ENOKEY if an encryption key is missing, -EXDEV if the
|
||||
* rename would cause inconsistent encryption policies, or another -errno code.
|
||||
*/
|
||||
static inline int fscrypt_prepare_rename(struct inode *old_dir,
|
||||
|
@ -1,231 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* fscrypt_notsupp.h
|
||||
*
|
||||
* This stubs out the fscrypt functions for filesystems configured without
|
||||
* encryption support.
|
||||
*
|
||||
* Do not include this file directly. Use fscrypt.h instead!
|
||||
*/
|
||||
#ifndef _LINUX_FSCRYPT_H
|
||||
#error "Incorrect include of linux/fscrypt_notsupp.h!"
|
||||
#endif
|
||||
|
||||
#ifndef _LINUX_FSCRYPT_NOTSUPP_H
|
||||
#define _LINUX_FSCRYPT_NOTSUPP_H
|
||||
|
||||
static inline bool fscrypt_has_encryption_key(const struct inode *inode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool fscrypt_dummy_context_enabled(struct inode *inode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* crypto.c */
|
||||
static inline void fscrypt_enqueue_decrypt_work(struct work_struct *work)
|
||||
{
|
||||
}
|
||||
|
||||
static inline struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *inode,
|
||||
gfp_t gfp_flags)
|
||||
{
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline void fscrypt_release_ctx(struct fscrypt_ctx *ctx)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline struct page *fscrypt_encrypt_page(const struct inode *inode,
|
||||
struct page *page,
|
||||
unsigned int len,
|
||||
unsigned int offs,
|
||||
u64 lblk_num, gfp_t gfp_flags)
|
||||
{
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline int fscrypt_decrypt_page(const struct inode *inode,
|
||||
struct page *page,
|
||||
unsigned int len, unsigned int offs,
|
||||
u64 lblk_num)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline struct page *fscrypt_control_page(struct page *page)
|
||||
{
|
||||
WARN_ON_ONCE(1);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static inline void fscrypt_restore_control_page(struct page *page)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* policy.c */
|
||||
static inline int fscrypt_ioctl_set_policy(struct file *filp,
|
||||
const void __user *arg)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int fscrypt_has_permitted_context(struct inode *parent,
|
||||
struct inode *child)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int fscrypt_inherit_context(struct inode *parent,
|
||||
struct inode *child,
|
||||
void *fs_data, bool preload)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* keyinfo.c */
|
||||
static inline int fscrypt_get_encryption_info(struct inode *inode)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline void fscrypt_put_encryption_info(struct inode *inode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* fname.c */
|
||||
static inline int fscrypt_setup_filename(struct inode *dir,
|
||||
const struct qstr *iname,
|
||||
int lookup, struct fscrypt_name *fname)
|
||||
{
|
||||
if (IS_ENCRYPTED(dir))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
memset(fname, 0, sizeof(struct fscrypt_name));
|
||||
fname->usr_fname = iname;
|
||||
fname->disk_name.name = (unsigned char *)iname->name;
|
||||
fname->disk_name.len = iname->len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void fscrypt_free_filename(struct fscrypt_name *fname)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int fscrypt_fname_alloc_buffer(const struct inode *inode,
|
||||
u32 max_encrypted_len,
|
||||
struct fscrypt_str *crypto_str)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline void fscrypt_fname_free_buffer(struct fscrypt_str *crypto_str)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int fscrypt_fname_disk_to_usr(struct inode *inode,
|
||||
u32 hash, u32 minor_hash,
|
||||
const struct fscrypt_str *iname,
|
||||
struct fscrypt_str *oname)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline bool fscrypt_match_name(const struct fscrypt_name *fname,
|
||||
const u8 *de_name, u32 de_name_len)
|
||||
{
|
||||
/* Encryption support disabled; use standard comparison */
|
||||
if (de_name_len != fname->disk_name.len)
|
||||
return false;
|
||||
return !memcmp(de_name, fname->disk_name.name, fname->disk_name.len);
|
||||
}
|
||||
|
||||
/* bio.c */
|
||||
static inline void fscrypt_decrypt_bio(struct bio *bio)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx,
|
||||
struct bio *bio)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void fscrypt_pullback_bio_page(struct page **page, bool restore)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
|
||||
sector_t pblk, unsigned int len)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* hooks.c */
|
||||
|
||||
static inline int fscrypt_file_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
if (IS_ENCRYPTED(inode))
|
||||
return -EOPNOTSUPP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int __fscrypt_prepare_link(struct inode *inode,
|
||||
struct inode *dir)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int __fscrypt_prepare_rename(struct inode *old_dir,
|
||||
struct dentry *old_dentry,
|
||||
struct inode *new_dir,
|
||||
struct dentry *new_dentry,
|
||||
unsigned int flags)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int __fscrypt_prepare_lookup(struct inode *dir,
|
||||
struct dentry *dentry)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int __fscrypt_prepare_symlink(struct inode *dir,
|
||||
unsigned int len,
|
||||
unsigned int max_len,
|
||||
struct fscrypt_str *disk_link)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int __fscrypt_encrypt_symlink(struct inode *inode,
|
||||
const char *target,
|
||||
unsigned int len,
|
||||
struct fscrypt_str *disk_link)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline const char *fscrypt_get_symlink(struct inode *inode,
|
||||
const void *caddr,
|
||||
unsigned int max_size,
|
||||
struct delayed_call *done)
|
||||
{
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
#endif /* _LINUX_FSCRYPT_NOTSUPP_H */
|
@ -1,204 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* fscrypt_supp.h
|
||||
*
|
||||
* Do not include this file directly. Use fscrypt.h instead!
|
||||
*/
|
||||
#ifndef _LINUX_FSCRYPT_H
|
||||
#error "Incorrect include of linux/fscrypt_supp.h!"
|
||||
#endif
|
||||
|
||||
#ifndef _LINUX_FSCRYPT_SUPP_H
|
||||
#define _LINUX_FSCRYPT_SUPP_H
|
||||
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
/*
|
||||
* fscrypt superblock flags
|
||||
*/
|
||||
#define FS_CFLG_OWN_PAGES (1U << 1)
|
||||
|
||||
/*
|
||||
* crypto operations for filesystems
|
||||
*/
|
||||
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 *);
|
||||
unsigned int max_namelen;
|
||||
};
|
||||
|
||||
struct fscrypt_ctx {
|
||||
union {
|
||||
struct {
|
||||
struct page *bounce_page; /* Ciphertext page */
|
||||
struct page *control_page; /* Original page */
|
||||
} w;
|
||||
struct {
|
||||
struct bio *bio;
|
||||
struct work_struct work;
|
||||
} r;
|
||||
struct list_head free_list; /* Free list */
|
||||
};
|
||||
u8 flags; /* Flags */
|
||||
};
|
||||
|
||||
static inline bool fscrypt_has_encryption_key(const struct inode *inode)
|
||||
{
|
||||
return (inode->i_crypt_info != NULL);
|
||||
}
|
||||
|
||||
static inline bool fscrypt_dummy_context_enabled(struct inode *inode)
|
||||
{
|
||||
return inode->i_sb->s_cop->dummy_context &&
|
||||
inode->i_sb->s_cop->dummy_context(inode);
|
||||
}
|
||||
|
||||
/* crypto.c */
|
||||
extern void fscrypt_enqueue_decrypt_work(struct work_struct *);
|
||||
extern struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *, gfp_t);
|
||||
extern void fscrypt_release_ctx(struct fscrypt_ctx *);
|
||||
extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *,
|
||||
unsigned int, unsigned int,
|
||||
u64, gfp_t);
|
||||
extern int fscrypt_decrypt_page(const struct inode *, struct page *, unsigned int,
|
||||
unsigned int, u64);
|
||||
|
||||
static inline struct page *fscrypt_control_page(struct page *page)
|
||||
{
|
||||
return ((struct fscrypt_ctx *)page_private(page))->w.control_page;
|
||||
}
|
||||
|
||||
extern void fscrypt_restore_control_page(struct 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_has_permitted_context(struct inode *, struct inode *);
|
||||
extern int fscrypt_inherit_context(struct inode *, struct inode *,
|
||||
void *, bool);
|
||||
/* keyinfo.c */
|
||||
extern int fscrypt_get_encryption_info(struct inode *);
|
||||
extern void fscrypt_put_encryption_info(struct inode *);
|
||||
|
||||
/* fname.c */
|
||||
extern int fscrypt_setup_filename(struct inode *, const struct qstr *,
|
||||
int lookup, struct fscrypt_name *);
|
||||
|
||||
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(struct inode *, u32, u32,
|
||||
const struct fscrypt_str *, struct fscrypt_str *);
|
||||
|
||||
#define FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE 32
|
||||
|
||||
/* Extracts the second-to-last ciphertext block; see explanation below */
|
||||
#define FSCRYPT_FNAME_DIGEST(name, len) \
|
||||
((name) + round_down((len) - FS_CRYPTO_BLOCK_SIZE - 1, \
|
||||
FS_CRYPTO_BLOCK_SIZE))
|
||||
|
||||
#define FSCRYPT_FNAME_DIGEST_SIZE FS_CRYPTO_BLOCK_SIZE
|
||||
|
||||
/**
|
||||
* fscrypt_digested_name - alternate identifier for an on-disk filename
|
||||
*
|
||||
* When userspace lists an encrypted directory without access to the key,
|
||||
* filenames whose ciphertext is longer than FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE
|
||||
* bytes are shown in this abbreviated form (base64-encoded) rather than as the
|
||||
* full ciphertext (base64-encoded). This is necessary to allow supporting
|
||||
* filenames up to NAME_MAX bytes, since base64 encoding expands the length.
|
||||
*
|
||||
* To make it possible for filesystems to still find the correct directory entry
|
||||
* despite not knowing the full on-disk name, we encode any filesystem-specific
|
||||
* 'hash' and/or 'minor_hash' which the filesystem may need for its lookups,
|
||||
* followed by the second-to-last ciphertext block of the filename. Due to the
|
||||
* use of the CBC-CTS encryption mode, the second-to-last ciphertext block
|
||||
* depends on the full plaintext. (Note that ciphertext stealing causes the
|
||||
* last two blocks to appear "flipped".) This makes accidental collisions very
|
||||
* unlikely: just a 1 in 2^128 chance for two filenames to collide even if they
|
||||
* share the same filesystem-specific hashes.
|
||||
*
|
||||
* However, this scheme isn't immune to intentional collisions, which can be
|
||||
* created by anyone able to create arbitrary plaintext filenames and view them
|
||||
* without the key. Making the "digest" be a real cryptographic hash like
|
||||
* SHA-256 over the full ciphertext would prevent this, although it would be
|
||||
* less efficient and harder to implement, especially since the filesystem would
|
||||
* need to calculate it for each directory entry examined during a search.
|
||||
*/
|
||||
struct fscrypt_digested_name {
|
||||
u32 hash;
|
||||
u32 minor_hash;
|
||||
u8 digest[FSCRYPT_FNAME_DIGEST_SIZE];
|
||||
};
|
||||
|
||||
/**
|
||||
* fscrypt_match_name() - test whether the given name matches a directory entry
|
||||
* @fname: the name being searched for
|
||||
* @de_name: the name from the directory entry
|
||||
* @de_name_len: the length of @de_name in bytes
|
||||
*
|
||||
* Normally @fname->disk_name will be set, and in that case we simply compare
|
||||
* that to the name stored in the directory entry. The only exception is that
|
||||
* if we don't have the key for an encrypted directory and a filename in it is
|
||||
* very long, then we won't have the full disk_name and we'll instead need to
|
||||
* match against the fscrypt_digested_name.
|
||||
*
|
||||
* Return: %true if the name matches, otherwise %false.
|
||||
*/
|
||||
static inline bool fscrypt_match_name(const struct fscrypt_name *fname,
|
||||
const u8 *de_name, u32 de_name_len)
|
||||
{
|
||||
if (unlikely(!fname->disk_name.name)) {
|
||||
const struct fscrypt_digested_name *n =
|
||||
(const void *)fname->crypto_buf.name;
|
||||
if (WARN_ON_ONCE(fname->usr_fname->name[0] != '_'))
|
||||
return false;
|
||||
if (de_name_len <= FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE)
|
||||
return false;
|
||||
return !memcmp(FSCRYPT_FNAME_DIGEST(de_name, de_name_len),
|
||||
n->digest, FSCRYPT_FNAME_DIGEST_SIZE);
|
||||
}
|
||||
|
||||
if (de_name_len != fname->disk_name.len)
|
||||
return false;
|
||||
return !memcmp(de_name, fname->disk_name.name, fname->disk_name.len);
|
||||
}
|
||||
|
||||
/* bio.c */
|
||||
extern void fscrypt_decrypt_bio(struct bio *);
|
||||
extern void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx,
|
||||
struct bio *bio);
|
||||
extern void fscrypt_pullback_bio_page(struct page **, bool);
|
||||
extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t,
|
||||
unsigned int);
|
||||
|
||||
/* hooks.c */
|
||||
extern int fscrypt_file_open(struct inode *inode, struct file *filp);
|
||||
extern int __fscrypt_prepare_link(struct inode *inode, struct inode *dir);
|
||||
extern int __fscrypt_prepare_rename(struct inode *old_dir,
|
||||
struct dentry *old_dentry,
|
||||
struct inode *new_dir,
|
||||
struct dentry *new_dentry,
|
||||
unsigned int flags);
|
||||
extern int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry);
|
||||
extern int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len,
|
||||
unsigned int max_len,
|
||||
struct fscrypt_str *disk_link);
|
||||
extern int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
|
||||
unsigned int len,
|
||||
struct fscrypt_str *disk_link);
|
||||
extern const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
|
||||
unsigned int max_size,
|
||||
struct delayed_call *done);
|
||||
|
||||
#endif /* _LINUX_FSCRYPT_SUPP_H */
|
Loading…
Reference in New Issue
Block a user