2018-11-19 15:46:05

by Chandan Rajendra

[permalink] [raw]
Subject: [PATCH 0/7] Remove fs specific fscrypt and fsverity build config options

As a first step to avoid copy-pasting common code across filesystems
which implement fscrypt/fsverity, this commit removes filesystem
specific build config option (CONFIG_EXT4_FS_ENCRYPTION,
CONFIG_EXT4_FS_VERITY, CONFIG_F2FS_FS_ENCRYPTION and
CONFIG_F2FS_FS_VERITY) and replaces it with build options
(CONFIG_FS_ENCRYPTION and CONFIG_FS_VERITY) whose values affect all
the filesystems making use of fscrypt and fsverity. This is done in
order to have a common code base for implementing "post read"
processing across filesystems.

Changelog:
RFC -> V1:
1. Add a new patch to implement S_VERITY/IS_VERITY().
2. Split code that replaces filesystem specific routines with generic
IS_ENCRYPTED() and IS_VERITY() calls into separate patches.

Chandan Rajendra (7):
ext4: use IS_ENCRYPTED() to check encryption status
f2fs: use IS_ENCRYPTED() to check encryption status
fscrypt: Remove filesystem specific build config option
Add S_VERITY and IS_VERITY()
ext4: use IS_VERITY() to check inode's fsverity status
f2fs: use IS_VERITY() to check inode's fsverity status
fsverity: Remove filesystem specific build config option

fs/crypto/Kconfig | 2 +-
fs/ext4/Kconfig | 35 ---
fs/ext4/dir.c | 10 +-
fs/ext4/ext4.h | 23 +-
fs/ext4/ext4_jbd2.h | 2 +-
fs/ext4/extents.c | 4 +-
fs/ext4/file.c | 2 +-
fs/ext4/ialloc.c | 2 +-
fs/ext4/inode.c | 32 +--
fs/ext4/ioctl.c | 4 +-
fs/ext4/move_extent.c | 3 +-
fs/ext4/namei.c | 18 +-
fs/ext4/page-io.c | 8 +-
fs/ext4/readpage.c | 10 +-
fs/ext4/super.c | 12 +-
fs/ext4/sysfs.c | 8 +-
fs/f2fs/Kconfig | 31 ---
fs/f2fs/data.c | 6 +-
fs/f2fs/dir.c | 10 +-
fs/f2fs/f2fs.h | 9 +-
fs/f2fs/file.c | 16 +-
fs/f2fs/inode.c | 4 +-
fs/f2fs/namei.c | 6 +-
fs/f2fs/super.c | 14 +-
fs/f2fs/sysfs.c | 8 +-
fs/verity/Kconfig | 2 +-
include/linux/fs.h | 2 +
include/linux/fscrypt.h | 416 +++++++++++++++++++++++++++++++-
include/linux/fscrypt_notsupp.h | 231 ------------------
include/linux/fscrypt_supp.h | 204 ----------------
include/linux/fsverity.h | 3 +-
31 files changed, 509 insertions(+), 628 deletions(-)
delete mode 100644 include/linux/fscrypt_notsupp.h
delete mode 100644 include/linux/fscrypt_supp.h

--
2.19.1


2018-11-28 00:28:21

by Chandan Rajendra

[permalink] [raw]
Subject: Re: [PATCH 4/7] Add S_VERITY and IS_VERITY()

On Tuesday, November 27, 2018 5:38:38 AM IST Eric Biggers wrote:
> Hi Chandan,
>
> On Mon, Nov 19, 2018 at 10:53:21AM +0530, Chandan Rajendra wrote:
> > Similar to S_ENCRYPTED/IS_ENCRYPTED(), this commit adds
> > S_VERITY/IS_VERITY() to be able to check if a VFS inode has verity
> > information associated with it.
> >
> > Signed-off-by: Chandan Rajendra <[email protected]>
> > ---
> > include/linux/fs.h | 2 ++
> > 1 file changed, 2 insertions(+)
> >
> > diff --git a/include/linux/fs.h b/include/linux/fs.h
> > index bcfc40062757..8129617c9718 100644
> > --- a/include/linux/fs.h
> > +++ b/include/linux/fs.h
> > @@ -1938,6 +1938,7 @@ struct super_operations {
> > #define S_DAX 0 /* Make all the DAX code disappear */
> > #endif
> > #define S_ENCRYPTED 16384 /* Encrypted file (using fs/crypto/) */
> > +#define S_VERITY 32768 /* File with fsverity info (using fs/verity) */
> >
>
> The comment for S_VERITY is misleading because IS_VERITY() is used to check
> whether the verity bit is set *before* the fsverity_info is created.
>
> Can you change it to just mirror the fscrypt comment?
>
> #define S_VERITY 32768 /* Verity file (using fs/verity/) */

I will fix this up.

--
chandan

2018-11-19 16:47:48

by Chao Yu

[permalink] [raw]
Subject: Re: [f2fs-dev] [PATCH 6/7] f2fs: use IS_VERITY() to check inode's fsverity status

On 2018/11/19 13:23, Chandan Rajendra wrote:
> This commit now uses IS_VERITY() macro to check if fsverity is
> enabled on an inode.
>
> Signed-off-by: Chandan Rajendra <[email protected]>

Acked-by: Chao Yu <[email protected]>

Thanks,

2018-11-19 15:46:22

by Chandan Rajendra

[permalink] [raw]
Subject: [PATCH 3/7] fscrypt: Remove filesystem specific build config option

In order to have a common code base for fscrypt "post read" processing
for all filesystems which support encryption, this commit removes
filesystem specific build config option (e.g. CONFIG_EXT4_FS_ENCRYPTION)
and replaces it with a build option (i.e. CONFIG_FS_ENCRYPTION) whose
value affects all the filesystems making use of fscrypt.

Signed-off-by: Chandan Rajendra <[email protected]>
---
fs/crypto/Kconfig | 2 +-
fs/ext4/Kconfig | 15 --
fs/ext4/dir.c | 2 -
fs/ext4/ext4.h | 7 +-
fs/ext4/inode.c | 8 +-
fs/ext4/ioctl.c | 4 +-
fs/ext4/namei.c | 10 +-
fs/ext4/page-io.c | 6 +-
fs/ext4/readpage.c | 2 +-
fs/ext4/super.c | 6 +-
fs/ext4/sysfs.c | 4 +-
fs/f2fs/Kconfig | 11 -
fs/f2fs/f2fs.h | 7 +-
fs/f2fs/super.c | 8 +-
fs/f2fs/sysfs.c | 4 +-
include/linux/fscrypt.h | 416 +++++++++++++++++++++++++++++++-
include/linux/fscrypt_notsupp.h | 231 ------------------
include/linux/fscrypt_supp.h | 204 ----------------
18 files changed, 441 insertions(+), 506 deletions(-)
delete mode 100644 include/linux/fscrypt_notsupp.h
delete mode 100644 include/linux/fscrypt_supp.h

diff --git a/fs/crypto/Kconfig b/fs/crypto/Kconfig
index 02b7d91c9231..6e9ae566a8fc 100644
--- a/fs/crypto/Kconfig
+++ b/fs/crypto/Kconfig
@@ -1,5 +1,5 @@
config FS_ENCRYPTION
- tristate "FS Encryption (Per-file encryption)"
+ bool "FS Encryption (Per-file encryption)"
select CRYPTO
select CRYPTO_AES
select CRYPTO_CBC
diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
index 5a76125ac0f8..e1002bbf35bf 100644
--- a/fs/ext4/Kconfig
+++ b/fs/ext4/Kconfig
@@ -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_FS_VERITY
bool "Ext4 Verity"
depends on EXT4_FS
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
index fb7a64ea5679..0ccd51f72048 100644
--- a/fs/ext4/dir.c
+++ b/fs/ext4/dir.c
@@ -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;
}
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 2ae6ab88f218..db21df885186 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -40,7 +40,6 @@
#include <linux/compat.h>
#endif

-#define __FS_HAS_ENCRYPTION IS_ENABLED(CONFIG_EXT4_FS_ENCRYPTION)
#include <linux/fscrypt.h>

#define __FS_HAS_VERITY IS_ENABLED(CONFIG_EXT4_FS_VERITY)
@@ -1341,7 +1340,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
@@ -2069,7 +2068,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
};
@@ -2306,7 +2305,7 @@ static inline bool ext4_verity_inode(struct inode *inode)
#endif
}

-#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)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 725777772f32..ae6794649817 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -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)
{
@@ -1303,7 +1303,7 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
/* 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);
@@ -3104,7 +3104,7 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
/* 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
@@ -3879,7 +3879,7 @@ 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
+#ifdef CONFIG_FS_ENCRYPTION
if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
return 0;
#endif
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 9bb6cc1ae8ce..892fb1925836 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -210,7 +210,7 @@ static long swap_inode_boot_loader(struct super_block *sb,
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 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
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;
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 0de60207a963..1e1a3c8c3a8b 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -611,7 +611,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 =
@@ -983,7 +983,7 @@ 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 (IS_ENCRYPTED(dir)) {
err = fscrypt_get_encryption_info(dir);
@@ -1046,7 +1046,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;
@@ -1266,7 +1266,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);
@@ -1497,7 +1497,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);
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
index 008c20b58f98..7d5f12be07ab 100644
--- a/fs/ext4/page-io.c
+++ b/fs/ext4/page-io.c
@@ -66,7 +66,7 @@ static void ext4_finish_bio(struct bio *bio)

bio_for_each_segment_all(bvec, bio, i) {
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;
@@ -78,7 +78,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;
@@ -111,7 +111,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
diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
index 45e707fb9749..7252f0a60cdb 100644
--- a/fs/ext4/readpage.c
+++ b/fs/ext4/readpage.c
@@ -54,7 +54,7 @@ static mempool_t *bio_post_read_ctx_pool;

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;
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index fb4e060f28ec..16fb483a6f4a 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1210,7 +1210,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,
@@ -1986,7 +1986,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");
@@ -4231,7 +4231,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_EXT4_FS_VERITY
diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
index 8e86087c2f03..8bc915452a38 100644
--- a/fs/ext4/sysfs.c
+++ b/fs/ext4/sysfs.c
@@ -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
#ifdef CONFIG_EXT4_FS_VERITY
@@ -236,7 +236,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
#ifdef CONFIG_EXT4_FS_VERITY
diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig
index c8396c7220f2..ce60e480fec1 100644
--- a/fs/f2fs/Kconfig
+++ b/fs/f2fs/Kconfig
@@ -70,17 +70,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_FS_VERITY
bool "F2FS Verity"
depends on F2FS_FS
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index dadb5f468f20..ea8a5ffc4f1f 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -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>

#define __FS_HAS_VERITY IS_ENABLED(CONFIG_F2FS_FS_VERITY)
@@ -1145,7 +1144,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
@@ -3448,7 +3447,7 @@ static inline bool f2fs_encrypted_file(struct inode *inode)

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
@@ -3533,7 +3532,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));
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index adf38c1b6414..4287cf348d3c 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -757,7 +757,7 @@ static int parse_options(struct super_block *sb, char *options)
kfree(name);
break;
case Opt_test_dummy_encryption:
-#ifdef CONFIG_F2FS_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
if (!f2fs_sb_has_encrypt(sb)) {
f2fs_msg(sb, KERN_ERR, "Encrypt feature is off");
return -EINVAL;
@@ -1387,7 +1387,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,
@@ -3143,7 +3143,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
#endif

sb->s_op = &f2fs_sops;
-#ifdef CONFIG_F2FS_FS_ENCRYPTION
+#ifdef CONFIG_FS_ENCRYPTION
sb->s_cop = &f2fs_cryptops;
#endif
#ifdef CONFIG_F2FS_FS_VERITY
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index 5599c9ac4426..737677655bc0 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -430,7 +430,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
@@ -493,7 +493,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
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 952ab97af325..6ba193c23f37 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -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
diff --git a/include/linux/fscrypt_notsupp.h b/include/linux/fscrypt_notsupp.h
deleted file mode 100644
index ee8b43e4c15a..000000000000
--- a/include/linux/fscrypt_notsupp.h
+++ /dev/null
@@ -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 */
diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h
deleted file mode 100644
index 6456c6b2005f..000000000000
--- a/include/linux/fscrypt_supp.h
+++ /dev/null
@@ -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 */
--
2.19.1

2018-11-27 04:29:25

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [f2fs-dev] [PATCH 2/7] f2fs: use IS_ENCRYPTED() to check encryption status

On Sun, Nov 25, 2018 at 11:00:38PM -0500, Theodore Y. Ts'o wrote:
>
> It might be that the simplest way to solve things is to merge the f2fs
> dev branch up to 79c66e75720c. This will have the net effect of
> including the five patches listed above onto the fscrypt git tree. So
> long you don't plan to rebase or otherwise change these five patches,
> it should avoid any merge conflicts.

I've set up a git branch which has the f2fs dev branch, 4.20-rc4, the
fsverity patches, and part of Chandan's patch series here:

git://git.kernel.org/pub/scm/linux/kernel/git/tytso/fscrypt.git test-working

There is a minor conflict when I did a trial merge with f2fs.git's dev
branch, but it's pretty obvious to how to resolve it.

Jaegeuk, Eric, Chandan, please take a look and let me know what you
think.

- Ted

2018-11-19 16:47:17

by Chao Yu

[permalink] [raw]
Subject: Re: [PATCH 2/7] f2fs: use IS_ENCRYPTED() to check encryption status

On 2018/11/19 13:23, Chandan Rajendra wrote:
> This commit removes the f2fs specific f2fs_encrypted_inode() and makes
> use of the generic IS_ENCRYPTED() macro to check for the encryption
> status of an inode.
>
> Signed-off-by: Chandan Rajendra <[email protected]>

Acked-by: Chao Yu <[email protected]>

Thanks,

2018-12-01 04:54:31

by Eric Biggers

[permalink] [raw]
Subject: Re: [f2fs-dev] [PATCH 2/7] f2fs: use IS_ENCRYPTED() to check encryption status

On Fri, Nov 30, 2018 at 10:57:58AM +0530, Chandan Rajendra wrote:
> On Friday, November 30, 2018 12:35:13 AM IST Eric Biggers wrote:
> > Hi Chandan,
> >
> > On Thu, Nov 29, 2018 at 04:08:31PM +0530, Chandan Rajendra wrote:
> > > On Monday, November 26, 2018 11:04:35 PM IST Theodore Y. Ts'o wrote:
> > > > On Sun, Nov 25, 2018 at 11:00:38PM -0500, Theodore Y. Ts'o wrote:
> > > > >
> > > > > It might be that the simplest way to solve things is to merge the f2fs
> > > > > dev branch up to 79c66e75720c. This will have the net effect of
> > > > > including the five patches listed above onto the fscrypt git tree. So
> > > > > long you don't plan to rebase or otherwise change these five patches,
> > > > > it should avoid any merge conflicts.
> > > >
> > > > I've set up a git branch which has the f2fs dev branch, 4.20-rc4, the
> > > > fsverity patches, and part of Chandan's patch series here:
> > > >
> > > > git://git.kernel.org/pub/scm/linux/kernel/git/tytso/fscrypt.git test-working
> > > >
> > > > There is a minor conflict when I did a trial merge with f2fs.git's dev
> > > > branch, but it's pretty obvious to how to resolve it.
> > > >
> > > > Jaegeuk, Eric, Chandan, please take a look and let me know what you
> > > > think.
> > >
> > > Ted,
> > >
> > > I have addressed the review comments provided by Eric. Hence three out of
> > > the four patches in the test-working branch have new changes. I also got
> > > UBIFS to use CONFIG_FS_ENCRYPTION instead of the per-filesystem config
> > > symbol.
> > >
> > > I am currently executing fstests to verify the changes.
> > >
> > >
> > > Eric,
> > >
> > > When executing generic/900, I noticed that sometimes xfs_io would get stuck
> > > for an indefinite period. /proc/<pid of xfs_io>/stack showed that the task was
> > > stuck in tty_read() inside the kernel. The following change fixed it,
> > >
> > > diff --git a/tests/generic/900 b/tests/generic/900
> > > index 290889ce..0831eed4 100755
> > > --- a/tests/generic/900
> > > +++ b/tests/generic/900
> > > @@ -83,7 +83,7 @@ _fsv_create_enable_file $fsv_file >> $seqres.full
> > > echo "* reading"
> > > $XFS_IO_PROG -r $fsv_file -c ''
> > > echo "* xfs_io writing, should be O_RDWR"
> > > -$XFS_IO_PROG $fsv_file |& _filter_scratch
> > > +$XFS_IO_PROG -c '' $fsv_file 2>&1 | _filter_scratch
> > > echo "* bash >>, should be O_APPEND"
> > > bash -c "echo >> $fsv_file" |& _filter_scratch
> > > echo "* bash >, should be O_WRONLY|O_CREAT|O_TRUNC"
> > >
> > > xfs_io gets into interactive mode when invoked without a "-c cmd" string.
> > >
> > > However, I am not able recreate the scenario once again without the above
> > > changes applied. I am not sure about what changed.
> > >
> >
> > The test is opening a verity file for read+write access, which should fail. But
> > it's incorrectly succeeding, hence the test is right to not pass. Did you add
> > the missing call to ext4_set_inode_flags() in ext4_set_verity() as I
> > suggested?
> >
> > (But I'll make the suggested change to the test too, so it fails cleanly in this
> > case rather than hangs reading from stdin.)
>
> Yes, I did make the suggested changes. But the test would some times hang
> indefinitely because of xfs_io waiting on input from stdin.
>
> With the new changes made to ext4_set_verity(), I see that the fsck fails
> consistency check. But the failure is seen even without my patches applied. I
> have planned to debug the failure after I post the next version of the
> patchset.
>

You're testing with e2fsprogs "1.44.4-2" or later, right? Note that the
original "v1.44.4" had some bugs with verity support, which were fixed shortly
after. Specifically, e2fsprogs needs to be commit 3baafde6a8ae7 or later.

- Eric

2018-11-27 14:00:17

by Chandan Rajendra

[permalink] [raw]
Subject: Re: [PATCH 5/7] ext4: use IS_VERITY() to check inode's fsverity status

On Monday, November 26, 2018 11:06:15 PM IST Theodore Y. Ts'o wrote:
> On Mon, Nov 19, 2018 at 10:53:22AM +0530, Chandan Rajendra wrote:
> > This commit now uses IS_VERITY() macro to check if fsverity is
> > enabled on an inode.
> >
> > Signed-off-by: Chandan Rajendra <[email protected]>
>
> This patch causes a massive number of fsverity tests. I suspect it's
> due to a mismatch between the ext4's inode flags as opposed to the VFS
> inode's flags. I'll take a closer look in the next day or two.
>

I will check this and report back soon.

--
chandan

2018-11-29 21:43:34

by Chandan Rajendra

[permalink] [raw]
Subject: Re: [f2fs-dev] [PATCH 2/7] f2fs: use IS_ENCRYPTED() to check encryption status

On Monday, November 26, 2018 11:04:35 PM IST Theodore Y. Ts'o wrote:
> On Sun, Nov 25, 2018 at 11:00:38PM -0500, Theodore Y. Ts'o wrote:
> >
> > It might be that the simplest way to solve things is to merge the f2fs
> > dev branch up to 79c66e75720c. This will have the net effect of
> > including the five patches listed above onto the fscrypt git tree. So
> > long you don't plan to rebase or otherwise change these five patches,
> > it should avoid any merge conflicts.
>
> I've set up a git branch which has the f2fs dev branch, 4.20-rc4, the
> fsverity patches, and part of Chandan's patch series here:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/tytso/fscrypt.git test-working
>
> There is a minor conflict when I did a trial merge with f2fs.git's dev
> branch, but it's pretty obvious to how to resolve it.
>
> Jaegeuk, Eric, Chandan, please take a look and let me know what you
> think.

Ted,

I have addressed the review comments provided by Eric. Hence three out of
the four patches in the test-working branch have new changes. I also got
UBIFS to use CONFIG_FS_ENCRYPTION instead of the per-filesystem config
symbol.

I am currently executing fstests to verify the changes.


Eric,

When executing generic/900, I noticed that sometimes xfs_io would get stuck
for an indefinite period. /proc/<pid of xfs_io>/stack showed that the task was
stuck in tty_read() inside the kernel. The following change fixed it,

diff --git a/tests/generic/900 b/tests/generic/900
index 290889ce..0831eed4 100755
--- a/tests/generic/900
+++ b/tests/generic/900
@@ -83,7 +83,7 @@ _fsv_create_enable_file $fsv_file >> $seqres.full
echo "* reading"
$XFS_IO_PROG -r $fsv_file -c ''
echo "* xfs_io writing, should be O_RDWR"
-$XFS_IO_PROG $fsv_file |& _filter_scratch
+$XFS_IO_PROG -c '' $fsv_file 2>&1 | _filter_scratch
echo "* bash >>, should be O_APPEND"
bash -c "echo >> $fsv_file" |& _filter_scratch
echo "* bash >, should be O_WRONLY|O_CREAT|O_TRUNC"

xfs_io gets into interactive mode when invoked without a "-c cmd" string.

However, I am not able recreate the scenario once again without the above
changes applied. I am not sure about what changed.

--
chandan

2018-11-27 11:31:12

by Eric Biggers

[permalink] [raw]
Subject: Re: [PATCH 1/7] ext4: use IS_ENCRYPTED() to check encryption status

Hi Chandan,

On Mon, Nov 19, 2018 at 10:53:18AM +0530, Chandan Rajendra wrote:
> @@ -4724,7 +4724,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 (IS_ENCRYPTED(inode))
> return false;
> if (ext4_verity_inode(inode))
> return false;

I think this part is wrong. See how ext4_should_use_dax() is called from
ext4_set_inode_flags(), from ext4_set_context(). In this case,
ext4_set_inode_flags() should set S_ENCRYPTED and clear S_DAX. However, you've
changed ext4_should_use_dax() to check S_ENCRYPTED instead of EXT4_ENCRYPT_FL;
but S_ENCRYPTED isn't set until later in ext4_set_inode_flags(), so S_DAX won't
be cleared anymore.

So I think you need to use ext4_test_inode_flag() here instead.

Similarly for the verity check.

- Eric

2018-11-28 00:29:28

by Chandan Rajendra

[permalink] [raw]
Subject: Re: [PATCH 7/7] fsverity: Remove filesystem specific build config option

On Tuesday, November 27, 2018 6:15:30 AM IST Eric Biggers wrote:
> Hi Chandan,
>
> On Mon, Nov 19, 2018 at 10:53:24AM +0530, Chandan Rajendra wrote:
> > In order to have a common code base for fsverity "post read" processing
> > for all filesystems which support per-file verity, this commit removes
> > filesystem specific build config option (e.g. CONFIG_EXT4_FS_VERITY) and
> > replaces it with a build option (i.e. CONFIG_FS_VERITY) whose value
> > affects all the filesystems making use of fsverity.
> >
> > Signed-off-by: Chandan Rajendra <[email protected]>
>
> Like the corresponding fscrypt patch, this is missing changing
>
> #if IS_ENABLED(CONFIG_FS_VERITY)
>
> in include/linux/fs.h to
>
> #ifdef CONFIG_FS_VERITY
>
> There are also references to the filesystem-specific config options in
> Documentation/filesystems/fsverity.rst that need to be updated.
>
> I also suggest updating the Kconfig help text for CONFIG_FS_VERITY and
> CONFIG_FS_ENCRYPTION to mention the supported filesystems, similar to how
> CONFIG_QUOTA lists the filesystems it supports.
>

I will fix this one too.

--
chandan

2018-11-26 14:53:29

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [f2fs-dev] [PATCH 2/7] f2fs: use IS_ENCRYPTED() to check encryption status

On Sun, Nov 25, 2018 at 10:41:32PM -0500, Theodore Y. Ts'o wrote:
> On Mon, Nov 19, 2018 at 01:23:32PM -0800, Jaegeuk Kim wrote:
> > Hi Chandan,
> >
> > Let me try to queue and test this patch separately from the patch-set in order
> > to avoid merge conflicts. So, I think IS_ENCRYPTED should be merged in f2fs/ext4
> > branches, and the others can be applied to fscrypt and fsverity into each trees.
>
> Hi Jaeguk,
>
> What conflicts are you anticipating? I can't apply the rest of
> Chandan's patches without unless we apply them in order, and I'd
> prefer to avoid cross-merging, or spreading out this series across two
> kernel releases.

Oh, I see the problem. It's commit 79c66e7572 ("f2fs: clean up
f2fs_sb_has_##feature_name") on the f2fs dev branch. It changes the
function signature of the f2fs_sb_has_<feature>() functions.

This is going to be a problem for merging the fsverity patch series as
well. How stable are these patches on the f2fs dev branch?

79c66e75720c f2fs: clean up f2fs_sb_has_##feature_name
6a917e69d3b8 f2fs: remove codes of unused wio_mutex
67bdd2a68f0a f2fs: fix count of seg_freed to make sec_freed correct
a5c7029ba357 f2fs: fix to account preflush command for noflush_merge mode
83effa8865cc f2fs: avoid GC causing encrypted file corrupted

It might be that the simplest way to solve things is to merge the f2fs
dev branch up to 79c66e75720c. This will have the net effect of
including the five patches listed above onto the fscrypt git tree. So
long you don't plan to rebase or otherwise change these five patches,
it should avoid any merge conflicts.

- Ted

2018-11-19 15:46:07

by Chandan Rajendra

[permalink] [raw]
Subject: [PATCH 1/7] ext4: use IS_ENCRYPTED() to check encryption status

This commit removes the ext4 specific ext4_encrypted_inode() and makes
use of the generic IS_ENCRYPTED() macro to check for the encryption
status of an inode.

Signed-off-by: Chandan Rajendra <[email protected]>
---
fs/ext4/dir.c | 8 ++++----
fs/ext4/ext4.h | 5 -----
fs/ext4/ext4_jbd2.h | 2 +-
fs/ext4/extents.c | 4 ++--
fs/ext4/ialloc.c | 2 +-
fs/ext4/inode.c | 14 +++++++-------
fs/ext4/move_extent.c | 3 +--
fs/ext4/namei.c | 8 ++++----
fs/ext4/page-io.c | 2 +-
fs/ext4/readpage.c | 2 +-
10 files changed, 22 insertions(+), 28 deletions(-)

diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
index f93f9881ec18..fb7a64ea5679 100644
--- a/fs/ext4/dir.c
+++ b/fs/ext4/dir.c
@@ -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),
@@ -613,7 +613,7 @@ static int ext4_dx_readdir(struct file *file, struct dir_context *ctx)

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;
}
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 80957f9d3cbe..2ae6ab88f218 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2297,11 +2297,6 @@ 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);
-}
-
static inline bool ext4_verity_inode(struct inode *inode)
{
#ifdef CONFIG_EXT4_FS_VERITY
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
index 15b6dd733780..a1ac7e9245ec 100644
--- a/fs/ext4/ext4_jbd2.h
+++ b/fs/ext4/ext4_jbd2.h
@@ -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 */
}
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 240b6dea5441..79d986dbf5af 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -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;
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 2addcb8730e1..3002f110eb4f 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -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);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index d7019f5dca6f..725777772f32 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -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);
@@ -1217,7 +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) &&
+ decrypt = IS_ENCRYPTED(inode) &&
S_ISREG(inode->i_mode);
}
}
@@ -3880,7 +3880,7 @@ static ssize_t ext4_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
ssize_t ret;

#ifdef CONFIG_EXT4_FS_ENCRYPTION
- if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode))
+ if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
return 0;
#endif

@@ -4068,7 +4068,7 @@ static int __ext4_block_zero_page_range(handle_t *handle,
if (!buffer_uptodate(bh))
goto unlock;
if (S_ISREG(inode->i_mode) &&
- ext4_encrypted_inode(inode)) {
+ IS_ENCRYPTED(inode)) {
/* We expect the key to be set. */
BUG_ON(!fscrypt_has_encryption_key(inode));
BUG_ON(blocksize != PAGE_SIZE);
@@ -4144,7 +4144,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;
@@ -4724,7 +4724,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 (IS_ENCRYPTED(inode))
return false;
if (ext4_verity_inode(inode))
return false;
@@ -5050,7 +5050,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)) {
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index 2f5be02fc6f6..1083a9f3f16a 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -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;
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 67a38532032a..0de60207a963 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -620,7 +620,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"
@@ -985,7 +985,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
EXT4_DIR_REC_LEN(0));
#ifdef CONFIG_EXT4_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);
@@ -1014,7 +1014,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,
@@ -1577,7 +1577,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,
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
index 2aa62d58d8dd..008c20b58f98 100644
--- a/fs/ext4/page-io.c
+++ b/fs/ext4/page-io.c
@@ -477,7 +477,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) &&
+ if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode) &&
nr_to_submit) {
gfp_t gfp_flags = GFP_NOFS;

diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
index d3dd1ff745db..45e707fb9749 100644
--- a/fs/ext4/readpage.c
+++ b/fs/ext4/readpage.c
@@ -156,7 +156,7 @@ static struct bio_post_read_ctx *get_bio_post_read_ctx(struct inode *inode,
unsigned int post_read_steps = 0;
struct bio_post_read_ctx *ctx = NULL;

- if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode))
+ if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
post_read_steps |= 1 << STEP_DECRYPT;
#ifdef CONFIG_EXT4_FS_VERITY
if (inode->i_verity_info != NULL &&
--
2.19.1

2018-11-27 10:48:52

by Jaegeuk Kim

[permalink] [raw]
Subject: Re: [f2fs-dev] [PATCH 2/7] f2fs: use IS_ENCRYPTED() to check encryption status

Hi Ted,

On 11/26, Theodore Y. Ts'o wrote:
> On Sun, Nov 25, 2018 at 11:00:38PM -0500, Theodore Y. Ts'o wrote:
> >
> > It might be that the simplest way to solve things is to merge the f2fs
> > dev branch up to 79c66e75720c. This will have the net effect of
> > including the five patches listed above onto the fscrypt git tree. So
> > long you don't plan to rebase or otherwise change these five patches,
> > it should avoid any merge conflicts.
>
> I've set up a git branch which has the f2fs dev branch, 4.20-rc4, the
> fsverity patches, and part of Chandan's patch series here:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/tytso/fscrypt.git test-working
>
> There is a minor conflict when I did a trial merge with f2fs.git's dev
> branch, but it's pretty obvious to how to resolve it.
>
> Jaegeuk, Eric, Chandan, please take a look and let me know what you
> think.

I was about to rebase f2fs-dev branch to catch up -rc4, so could you please
update test-working with the rebased one? Then, I'll test Eric & Chandan's
patches in the test-working branch locally. If there is no issue, I'm okay
to push all of their work via fscrypt.git, if you prefer.

Afterward, merging f2fs patches till "f2fs: clean up f2fs_sb_has_##feature_name"
into the test-working branch would be fine as well.

Thanks,

>
> - Ted

2018-11-27 11:41:33

by Eric Biggers

[permalink] [raw]
Subject: Re: [PATCH 7/7] fsverity: Remove filesystem specific build config option

Hi Chandan,

On Mon, Nov 19, 2018 at 10:53:24AM +0530, Chandan Rajendra wrote:
> In order to have a common code base for fsverity "post read" processing
> for all filesystems which support per-file verity, this commit removes
> filesystem specific build config option (e.g. CONFIG_EXT4_FS_VERITY) and
> replaces it with a build option (i.e. CONFIG_FS_VERITY) whose value
> affects all the filesystems making use of fsverity.
>
> Signed-off-by: Chandan Rajendra <[email protected]>

Like the corresponding fscrypt patch, this is missing changing

#if IS_ENABLED(CONFIG_FS_VERITY)

in include/linux/fs.h to

#ifdef CONFIG_FS_VERITY

There are also references to the filesystem-specific config options in
Documentation/filesystems/fsverity.rst that need to be updated.

I also suggest updating the Kconfig help text for CONFIG_FS_VERITY and
CONFIG_FS_ENCRYPTION to mention the supported filesystems, similar to how
CONFIG_QUOTA lists the filesystems it supports.

Thanks!

- Eric

> ---
> fs/ext4/Kconfig | 20 --------------------
> fs/ext4/ext4.h | 2 --
> fs/ext4/readpage.c | 4 ++--
> fs/ext4/super.c | 6 +++---
> fs/ext4/sysfs.c | 4 ++--
> fs/f2fs/Kconfig | 20 --------------------
> fs/f2fs/data.c | 2 +-
> fs/f2fs/f2fs.h | 2 --
> fs/f2fs/super.c | 6 +++---
> fs/f2fs/sysfs.c | 4 ++--
> fs/verity/Kconfig | 2 +-
> include/linux/fsverity.h | 3 +--
> 12 files changed, 15 insertions(+), 60 deletions(-)
>
> diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
> index e1002bbf35bf..031e5a82d556 100644
> --- a/fs/ext4/Kconfig
> +++ b/fs/ext4/Kconfig
> @@ -96,26 +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_FS_VERITY
> - bool "Ext4 Verity"
> - depends on EXT4_FS
> - select FS_VERITY
> - help
> - This option enables fs-verity for ext4. fs-verity is the
> - dm-verity mechanism implemented at the file level. Userspace
> - can append a Merkle tree (hash tree) to a file, then enable
> - fs-verity on the file. ext4 will then transparently verify
> - any data read from the file against the Merkle tree. The file
> - is also made read-only.
> -
> - This serves as an integrity check, but the availability of the
> - Merkle tree root hash also allows efficiently supporting
> - various use cases where normally the whole file would need to
> - be hashed at once, such as auditing and authenticity
> - verification (appraisal).
> -
> - If unsure, say N.
> -
> config EXT4_DEBUG
> bool "EXT4 debugging support"
> depends on EXT4_FS
> diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
> index 64bf9fb7ef18..bff8d639dd0c 100644
> --- a/fs/ext4/ext4.h
> +++ b/fs/ext4/ext4.h
> @@ -41,8 +41,6 @@
> #endif
>
> #include <linux/fscrypt.h>
> -
> -#define __FS_HAS_VERITY IS_ENABLED(CONFIG_EXT4_FS_VERITY)
> #include <linux/fsverity.h>
>
> #include <linux/compiler.h>
> diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
> index 2c037df629dd..8717ac0a5bb2 100644
> --- a/fs/ext4/readpage.c
> +++ b/fs/ext4/readpage.c
> @@ -158,7 +158,7 @@ static struct bio_post_read_ctx *get_bio_post_read_ctx(struct inode *inode,
>
> if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
> post_read_steps |= 1 << STEP_DECRYPT;
> -#ifdef CONFIG_EXT4_FS_VERITY
> +#ifdef CONFIG_FS_VERITY
> if (inode->i_verity_info != NULL &&
> (index < ((i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT)))
> post_read_steps |= 1 << STEP_VERITY;
> @@ -205,7 +205,7 @@ static void mpage_end_io(struct bio *bio)
>
> static inline loff_t ext4_readpage_limit(struct inode *inode)
> {
> -#ifdef CONFIG_EXT4_FS_VERITY
> +#ifdef CONFIG_FS_VERITY
> if (IS_VERITY(inode)) {
> if (inode->i_verity_info)
> /* limit to end of metadata region */
> diff --git a/fs/ext4/super.c b/fs/ext4/super.c
> index 16fb483a6f4a..472338c7cd03 100644
> --- a/fs/ext4/super.c
> +++ b/fs/ext4/super.c
> @@ -1316,7 +1316,7 @@ static const struct fscrypt_operations ext4_cryptops = {
> };
> #endif
>
> -#ifdef CONFIG_EXT4_FS_VERITY
> +#ifdef CONFIG_FS_VERITY
> static int ext4_set_verity(struct inode *inode, loff_t data_i_size)
> {
> int err;
> @@ -1401,7 +1401,7 @@ static const struct fsverity_operations ext4_verityops = {
> .set_verity = ext4_set_verity,
> .get_metadata_end = ext4_get_metadata_end,
> };
> -#endif /* CONFIG_EXT4_FS_VERITY */
> +#endif /* CONFIG_FS_VERITY */
>
> #ifdef CONFIG_QUOTA
> static const char * const quotatypes[] = INITQFNAMES;
> @@ -4234,7 +4234,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
> #ifdef CONFIG_FS_ENCRYPTION
> sb->s_cop = &ext4_cryptops;
> #endif
> -#ifdef CONFIG_EXT4_FS_VERITY
> +#ifdef CONFIG_FS_VERITY
> sb->s_vop = &ext4_verityops;
> #endif
> #ifdef CONFIG_QUOTA
> diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
> index 8bc915452a38..6fa0f47c3180 100644
> --- a/fs/ext4/sysfs.c
> +++ b/fs/ext4/sysfs.c
> @@ -227,7 +227,7 @@ EXT4_ATTR_FEATURE(meta_bg_resize);
> #ifdef CONFIG_FS_ENCRYPTION
> EXT4_ATTR_FEATURE(encryption);
> #endif
> -#ifdef CONFIG_EXT4_FS_VERITY
> +#ifdef CONFIG_FS_VERITY
> EXT4_ATTR_FEATURE(verity);
> #endif
> EXT4_ATTR_FEATURE(metadata_csum_seed);
> @@ -239,7 +239,7 @@ static struct attribute *ext4_feat_attrs[] = {
> #ifdef CONFIG_FS_ENCRYPTION
> ATTR_LIST(encryption),
> #endif
> -#ifdef CONFIG_EXT4_FS_VERITY
> +#ifdef CONFIG_FS_VERITY
> ATTR_LIST(verity),
> #endif
> ATTR_LIST(metadata_csum_seed),
> diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig
> index ce60e480fec1..708e23816575 100644
> --- a/fs/f2fs/Kconfig
> +++ b/fs/f2fs/Kconfig
> @@ -70,26 +70,6 @@ config F2FS_CHECK_FS
>
> If you want to improve the performance, say N.
>
> -config F2FS_FS_VERITY
> - bool "F2FS Verity"
> - depends on F2FS_FS
> - select FS_VERITY
> - help
> - This option enables fs-verity for f2fs. fs-verity is the
> - dm-verity mechanism implemented at the file level. Userspace
> - can append a Merkle tree (hash tree) to a file, then enable
> - fs-verity on the file. f2fs will then transparently verify
> - any data read from the file against the Merkle tree. The file
> - is also made read-only.
> -
> - This serves as an integrity check, but the availability of the
> - Merkle tree root hash also allows efficiently supporting
> - various use cases where normally the whole file would need to
> - be hashed at once, such as auditing and authenticity
> - verification (appraisal).
> -
> - If unsure, say N.
> -
> config F2FS_IO_TRACE
> bool "F2FS IO tracer"
> depends on F2FS_FS
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index 844ec573263e..83b59b985894 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -610,7 +610,7 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr,
>
> if (f2fs_encrypted_file(inode))
> post_read_steps |= 1 << STEP_DECRYPT;
> -#ifdef CONFIG_F2FS_FS_VERITY
> +#ifdef CONFIG_FS_VERITY
> if (inode->i_verity_info != NULL &&
> (first_idx < ((i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT)))
> post_read_steps |= 1 << STEP_VERITY;
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index ea8a5ffc4f1f..dc999af932f2 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -25,8 +25,6 @@
> #include <crypto/hash.h>
>
> #include <linux/fscrypt.h>
> -
> -#define __FS_HAS_VERITY IS_ENABLED(CONFIG_F2FS_FS_VERITY)
> #include <linux/fsverity.h>
>
> #ifdef CONFIG_F2FS_CHECK_FS
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index 4287cf348d3c..60d5338280fb 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -2197,7 +2197,7 @@ static const struct fscrypt_operations f2fs_cryptops = {
> };
> #endif
>
> -#ifdef CONFIG_F2FS_FS_VERITY
> +#ifdef CONFIG_FS_VERITY
> static int f2fs_set_verity(struct inode *inode, loff_t data_i_size)
> {
> int err;
> @@ -2222,7 +2222,7 @@ static const struct fsverity_operations f2fs_verityops = {
> .set_verity = f2fs_set_verity,
> .get_metadata_end = f2fs_get_metadata_end,
> };
> -#endif /* CONFIG_F2FS_FS_VERITY */
> +#endif /* CONFIG_FS_VERITY */
>
> static struct inode *f2fs_nfs_get_inode(struct super_block *sb,
> u64 ino, u32 generation)
> @@ -3146,7 +3146,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
> #ifdef CONFIG_FS_ENCRYPTION
> sb->s_cop = &f2fs_cryptops;
> #endif
> -#ifdef CONFIG_F2FS_FS_VERITY
> +#ifdef CONFIG_FS_VERITY
> sb->s_vop = &f2fs_verityops;
> #endif
> sb->s_xattr = f2fs_xattr_handlers;
> diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
> index 737677655bc0..949e6d87f4e3 100644
> --- a/fs/f2fs/sysfs.c
> +++ b/fs/f2fs/sysfs.c
> @@ -444,7 +444,7 @@ F2FS_FEATURE_RO_ATTR(flexible_inline_xattr, FEAT_FLEXIBLE_INLINE_XATTR);
> F2FS_FEATURE_RO_ATTR(quota_ino, FEAT_QUOTA_INO);
> F2FS_FEATURE_RO_ATTR(inode_crtime, FEAT_INODE_CRTIME);
> F2FS_FEATURE_RO_ATTR(lost_found, FEAT_LOST_FOUND);
> -#ifdef CONFIG_F2FS_FS_VERITY
> +#ifdef CONFIG_FS_VERITY
> F2FS_FEATURE_RO_ATTR(verity, FEAT_VERITY);
> #endif
> F2FS_FEATURE_RO_ATTR(sb_checksum, FEAT_SB_CHECKSUM);
> @@ -507,7 +507,7 @@ static struct attribute *f2fs_feat_attrs[] = {
> ATTR_LIST(quota_ino),
> ATTR_LIST(inode_crtime),
> ATTR_LIST(lost_found),
> -#ifdef CONFIG_F2FS_FS_VERITY
> +#ifdef CONFIG_FS_VERITY
> ATTR_LIST(verity),
> #endif
> ATTR_LIST(sb_checksum),
> diff --git a/fs/verity/Kconfig b/fs/verity/Kconfig
> index a7470a2e4892..b5a48a9ef0ca 100644
> --- a/fs/verity/Kconfig
> +++ b/fs/verity/Kconfig
> @@ -1,5 +1,5 @@
> config FS_VERITY
> - tristate "FS Verity (read-only file-based authenticity protection)"
> + bool "FS Verity (read-only file-based authenticity protection)"
> select CRYPTO
> # SHA-256 is selected as it's intended to be the default hash algorithm.
> # To avoid bloat, other wanted algorithms must be selected explicitly.
> diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h
> index c30c4f6ed411..f37132c640ee 100644
> --- a/include/linux/fsverity.h
> +++ b/include/linux/fsverity.h
> @@ -19,8 +19,7 @@ struct fsverity_operations {
> int (*get_metadata_end)(struct inode *inode, loff_t *metadata_end_ret);
> };
>
> -#if __FS_HAS_VERITY
> -
> +#ifdef CONFIG_FS_VERITY
> /* ioctl.c */
> extern int fsverity_ioctl_enable(struct file *filp, const void __user *arg);
> extern int fsverity_ioctl_measure(struct file *filp, void __user *arg);
> --
> 2.19.1
>

2018-11-27 04:31:05

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 5/7] ext4: use IS_VERITY() to check inode's fsverity status

On Mon, Nov 19, 2018 at 10:53:22AM +0530, Chandan Rajendra wrote:
> This commit now uses IS_VERITY() macro to check if fsverity is
> enabled on an inode.
>
> Signed-off-by: Chandan Rajendra <[email protected]>

This patch causes a massive number of fsverity tests. I suspect it's
due to a mismatch between the ext4's inode flags as opposed to the VFS
inode's flags. I'll take a closer look in the next day or two.

Cheers,

- Ted

2018-11-27 11:10:23

by Eric Biggers

[permalink] [raw]
Subject: Re: [PATCH 3/7] fscrypt: Remove filesystem specific build config option

Hi Chandan,

On Mon, Nov 19, 2018 at 10:53:20AM +0530, Chandan Rajendra wrote:
> In order to have a common code base for fscrypt "post read" processing
> for all filesystems which support encryption, this commit removes
> filesystem specific build config option (e.g. CONFIG_EXT4_FS_ENCRYPTION)
> and replaces it with a build option (i.e. CONFIG_FS_ENCRYPTION) whose
> value affects all the filesystems making use of fscrypt.
>
> Signed-off-by: Chandan Rajendra <[email protected]>

Can you grep for EXT4_ENCRYPTION? There are still some references left, one in
Documentation/filesystems/fscrypt.rst and some in defconfig files.

Also in include/linux/fs.h, there are tests of

#if IS_ENABLED(CONFIG_FS_ENCRYPTION)

which after this change should be

#ifdef CONFIG_FS_ENCRYPTION

like is done elsewhere.

Thanks,

- Eric

> ---
> fs/crypto/Kconfig | 2 +-
> fs/ext4/Kconfig | 15 --
> fs/ext4/dir.c | 2 -
> fs/ext4/ext4.h | 7 +-
> fs/ext4/inode.c | 8 +-
> fs/ext4/ioctl.c | 4 +-
> fs/ext4/namei.c | 10 +-
> fs/ext4/page-io.c | 6 +-
> fs/ext4/readpage.c | 2 +-
> fs/ext4/super.c | 6 +-
> fs/ext4/sysfs.c | 4 +-
> fs/f2fs/Kconfig | 11 -
> fs/f2fs/f2fs.h | 7 +-
> fs/f2fs/super.c | 8 +-
> fs/f2fs/sysfs.c | 4 +-
> include/linux/fscrypt.h | 416 +++++++++++++++++++++++++++++++-
> include/linux/fscrypt_notsupp.h | 231 ------------------
> include/linux/fscrypt_supp.h | 204 ----------------
> 18 files changed, 441 insertions(+), 506 deletions(-)
> delete mode 100644 include/linux/fscrypt_notsupp.h
> delete mode 100644 include/linux/fscrypt_supp.h
>
> diff --git a/fs/crypto/Kconfig b/fs/crypto/Kconfig
> index 02b7d91c9231..6e9ae566a8fc 100644
> --- a/fs/crypto/Kconfig
> +++ b/fs/crypto/Kconfig
> @@ -1,5 +1,5 @@
> config FS_ENCRYPTION
> - tristate "FS Encryption (Per-file encryption)"
> + bool "FS Encryption (Per-file encryption)"
> select CRYPTO
> select CRYPTO_AES
> select CRYPTO_CBC
> diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
> index 5a76125ac0f8..e1002bbf35bf 100644
> --- a/fs/ext4/Kconfig
> +++ b/fs/ext4/Kconfig
> @@ -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_FS_VERITY
> bool "Ext4 Verity"
> depends on EXT4_FS
> diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
> index fb7a64ea5679..0ccd51f72048 100644
> --- a/fs/ext4/dir.c
> +++ b/fs/ext4/dir.c
> @@ -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;
> }
> diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
> index 2ae6ab88f218..db21df885186 100644
> --- a/fs/ext4/ext4.h
> +++ b/fs/ext4/ext4.h
> @@ -40,7 +40,6 @@
> #include <linux/compat.h>
> #endif
>
> -#define __FS_HAS_ENCRYPTION IS_ENABLED(CONFIG_EXT4_FS_ENCRYPTION)
> #include <linux/fscrypt.h>
>
> #define __FS_HAS_VERITY IS_ENABLED(CONFIG_EXT4_FS_VERITY)
> @@ -1341,7 +1340,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
> @@ -2069,7 +2068,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
> };
> @@ -2306,7 +2305,7 @@ static inline bool ext4_verity_inode(struct inode *inode)
> #endif
> }
>
> -#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)
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index 725777772f32..ae6794649817 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -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)
> {
> @@ -1303,7 +1303,7 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
> /* 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);
> @@ -3104,7 +3104,7 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
> /* 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
> @@ -3879,7 +3879,7 @@ 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
> +#ifdef CONFIG_FS_ENCRYPTION
> if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
> return 0;
> #endif
> diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
> index 9bb6cc1ae8ce..892fb1925836 100644
> --- a/fs/ext4/ioctl.c
> +++ b/fs/ext4/ioctl.c
> @@ -210,7 +210,7 @@ static long swap_inode_boot_loader(struct super_block *sb,
> 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 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> 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;
> diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
> index 0de60207a963..1e1a3c8c3a8b 100644
> --- a/fs/ext4/namei.c
> +++ b/fs/ext4/namei.c
> @@ -611,7 +611,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 =
> @@ -983,7 +983,7 @@ 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 (IS_ENCRYPTED(dir)) {
> err = fscrypt_get_encryption_info(dir);
> @@ -1046,7 +1046,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;
> @@ -1266,7 +1266,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);
> @@ -1497,7 +1497,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);
> diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
> index 008c20b58f98..7d5f12be07ab 100644
> --- a/fs/ext4/page-io.c
> +++ b/fs/ext4/page-io.c
> @@ -66,7 +66,7 @@ static void ext4_finish_bio(struct bio *bio)
>
> bio_for_each_segment_all(bvec, bio, i) {
> 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;
> @@ -78,7 +78,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;
> @@ -111,7 +111,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
> diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
> index 45e707fb9749..7252f0a60cdb 100644
> --- a/fs/ext4/readpage.c
> +++ b/fs/ext4/readpage.c
> @@ -54,7 +54,7 @@ static mempool_t *bio_post_read_ctx_pool;
>
> 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;
> diff --git a/fs/ext4/super.c b/fs/ext4/super.c
> index fb4e060f28ec..16fb483a6f4a 100644
> --- a/fs/ext4/super.c
> +++ b/fs/ext4/super.c
> @@ -1210,7 +1210,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,
> @@ -1986,7 +1986,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");
> @@ -4231,7 +4231,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_EXT4_FS_VERITY
> diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
> index 8e86087c2f03..8bc915452a38 100644
> --- a/fs/ext4/sysfs.c
> +++ b/fs/ext4/sysfs.c
> @@ -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
> #ifdef CONFIG_EXT4_FS_VERITY
> @@ -236,7 +236,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
> #ifdef CONFIG_EXT4_FS_VERITY
> diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig
> index c8396c7220f2..ce60e480fec1 100644
> --- a/fs/f2fs/Kconfig
> +++ b/fs/f2fs/Kconfig
> @@ -70,17 +70,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_FS_VERITY
> bool "F2FS Verity"
> depends on F2FS_FS
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index dadb5f468f20..ea8a5ffc4f1f 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -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>
>
> #define __FS_HAS_VERITY IS_ENABLED(CONFIG_F2FS_FS_VERITY)
> @@ -1145,7 +1144,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
> @@ -3448,7 +3447,7 @@ static inline bool f2fs_encrypted_file(struct inode *inode)
>
> 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
> @@ -3533,7 +3532,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));
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index adf38c1b6414..4287cf348d3c 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -757,7 +757,7 @@ static int parse_options(struct super_block *sb, char *options)
> kfree(name);
> break;
> case Opt_test_dummy_encryption:
> -#ifdef CONFIG_F2FS_FS_ENCRYPTION
> +#ifdef CONFIG_FS_ENCRYPTION
> if (!f2fs_sb_has_encrypt(sb)) {
> f2fs_msg(sb, KERN_ERR, "Encrypt feature is off");
> return -EINVAL;
> @@ -1387,7 +1387,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,
> @@ -3143,7 +3143,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
> #endif
>
> sb->s_op = &f2fs_sops;
> -#ifdef CONFIG_F2FS_FS_ENCRYPTION
> +#ifdef CONFIG_FS_ENCRYPTION
> sb->s_cop = &f2fs_cryptops;
> #endif
> #ifdef CONFIG_F2FS_FS_VERITY
> diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
> index 5599c9ac4426..737677655bc0 100644
> --- a/fs/f2fs/sysfs.c
> +++ b/fs/f2fs/sysfs.c
> @@ -430,7 +430,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
> @@ -493,7 +493,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
> diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
> index 952ab97af325..6ba193c23f37 100644
> --- a/include/linux/fscrypt.h
> +++ b/include/linux/fscrypt.h
> @@ -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
> diff --git a/include/linux/fscrypt_notsupp.h b/include/linux/fscrypt_notsupp.h
> deleted file mode 100644
> index ee8b43e4c15a..000000000000
> --- a/include/linux/fscrypt_notsupp.h
> +++ /dev/null
> @@ -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 */
> diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h
> deleted file mode 100644
> index 6456c6b2005f..000000000000
> --- a/include/linux/fscrypt_supp.h
> +++ /dev/null
> @@ -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 */
> --
> 2.19.1
>

2018-11-30 06:11:40

by Eric Biggers

[permalink] [raw]
Subject: Re: [f2fs-dev] [PATCH 2/7] f2fs: use IS_ENCRYPTED() to check encryption status

Hi Chandan,

On Thu, Nov 29, 2018 at 04:08:31PM +0530, Chandan Rajendra wrote:
> On Monday, November 26, 2018 11:04:35 PM IST Theodore Y. Ts'o wrote:
> > On Sun, Nov 25, 2018 at 11:00:38PM -0500, Theodore Y. Ts'o wrote:
> > >
> > > It might be that the simplest way to solve things is to merge the f2fs
> > > dev branch up to 79c66e75720c. This will have the net effect of
> > > including the five patches listed above onto the fscrypt git tree. So
> > > long you don't plan to rebase or otherwise change these five patches,
> > > it should avoid any merge conflicts.
> >
> > I've set up a git branch which has the f2fs dev branch, 4.20-rc4, the
> > fsverity patches, and part of Chandan's patch series here:
> >
> > git://git.kernel.org/pub/scm/linux/kernel/git/tytso/fscrypt.git test-working
> >
> > There is a minor conflict when I did a trial merge with f2fs.git's dev
> > branch, but it's pretty obvious to how to resolve it.
> >
> > Jaegeuk, Eric, Chandan, please take a look and let me know what you
> > think.
>
> Ted,
>
> I have addressed the review comments provided by Eric. Hence three out of
> the four patches in the test-working branch have new changes. I also got
> UBIFS to use CONFIG_FS_ENCRYPTION instead of the per-filesystem config
> symbol.
>
> I am currently executing fstests to verify the changes.
>
>
> Eric,
>
> When executing generic/900, I noticed that sometimes xfs_io would get stuck
> for an indefinite period. /proc/<pid of xfs_io>/stack showed that the task was
> stuck in tty_read() inside the kernel. The following change fixed it,
>
> diff --git a/tests/generic/900 b/tests/generic/900
> index 290889ce..0831eed4 100755
> --- a/tests/generic/900
> +++ b/tests/generic/900
> @@ -83,7 +83,7 @@ _fsv_create_enable_file $fsv_file >> $seqres.full
> echo "* reading"
> $XFS_IO_PROG -r $fsv_file -c ''
> echo "* xfs_io writing, should be O_RDWR"
> -$XFS_IO_PROG $fsv_file |& _filter_scratch
> +$XFS_IO_PROG -c '' $fsv_file 2>&1 | _filter_scratch
> echo "* bash >>, should be O_APPEND"
> bash -c "echo >> $fsv_file" |& _filter_scratch
> echo "* bash >, should be O_WRONLY|O_CREAT|O_TRUNC"
>
> xfs_io gets into interactive mode when invoked without a "-c cmd" string.
>
> However, I am not able recreate the scenario once again without the above
> changes applied. I am not sure about what changed.
>

The test is opening a verity file for read+write access, which should fail. But
it's incorrectly succeeding, hence the test is right to not pass. Did you add
the missing call to ext4_set_inode_flags() in ext4_set_verity() as I suggested?

(But I'll make the suggested change to the test too, so it fails cleanly in this
case rather than hangs reading from stdin.)

- Eric

2018-11-19 15:46:22

by Chandan Rajendra

[permalink] [raw]
Subject: [PATCH 5/7] ext4: use IS_VERITY() to check inode's fsverity status

This commit now uses IS_VERITY() macro to check if fsverity is
enabled on an inode.

Signed-off-by: Chandan Rajendra <[email protected]>
---
fs/ext4/ext4.h | 9 ---------
fs/ext4/file.c | 2 +-
fs/ext4/inode.c | 10 ++++++----
fs/ext4/readpage.c | 2 +-
4 files changed, 8 insertions(+), 15 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index db21df885186..64bf9fb7ef18 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2296,15 +2296,6 @@ 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_verity_inode(struct inode *inode)
-{
-#ifdef CONFIG_EXT4_FS_VERITY
- return ext4_test_inode_flag(inode, EXT4_INODE_VERITY);
-#else
- return false;
-#endif
-}
-
#ifdef CONFIG_FS_ENCRYPTION
static inline int ext4_fname_setup_filename(struct inode *dir,
const struct qstr *iname,
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index cb4b69ef01a2..30fbd663354f 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -444,7 +444,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
if (ret)
return ret;

- if (ext4_verity_inode(inode)) {
+ if (IS_VERITY(inode)) {
ret = fsverity_file_open(inode, filp);
if (ret)
return ret;
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index ae6794649817..3786740b73fa 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3884,7 +3884,7 @@ static ssize_t ext4_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
return 0;
#endif

- if (ext4_verity_inode(inode))
+ if (IS_VERITY(inode))
return 0;

/*
@@ -4726,7 +4726,7 @@ static bool ext4_should_use_dax(struct inode *inode)
return false;
if (IS_ENCRYPTED(inode))
return false;
- if (ext4_verity_inode(inode))
+ if (IS_VERITY(inode))
return false;
return true;
}
@@ -4750,9 +4750,11 @@ void ext4_set_inode_flags(struct inode *inode)
new_fl |= S_DAX;
if (flags & EXT4_ENCRYPT_FL)
new_fl |= S_ENCRYPTED;
+ if (flags & EXT4_VERITY_FL)
+ new_fl |= S_VERITY;
inode_set_flags(inode, new_fl,
S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|S_DAX|
- S_ENCRYPTED);
+ S_ENCRYPTED|S_VERITY);
}

static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode,
@@ -5510,7 +5512,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
if (error)
return error;

- if (ext4_verity_inode(inode)) {
+ if (IS_VERITY(inode)) {
error = fsverity_prepare_setattr(dentry, attr);
if (error)
return error;
diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
index 7252f0a60cdb..2c037df629dd 100644
--- a/fs/ext4/readpage.c
+++ b/fs/ext4/readpage.c
@@ -206,7 +206,7 @@ static void mpage_end_io(struct bio *bio)
static inline loff_t ext4_readpage_limit(struct inode *inode)
{
#ifdef CONFIG_EXT4_FS_VERITY
- if (ext4_verity_inode(inode)) {
+ if (IS_VERITY(inode)) {
if (inode->i_verity_info)
/* limit to end of metadata region */
return fsverity_full_i_size(inode);
--
2.19.1

2018-11-19 15:47:32

by Chandan Rajendra

[permalink] [raw]
Subject: [PATCH 6/7] f2fs: use IS_VERITY() to check inode's fsverity status

This commit now uses IS_VERITY() macro to check if fsverity is
enabled on an inode.

Signed-off-by: Chandan Rajendra <[email protected]>
---
fs/f2fs/file.c | 6 +++---
fs/f2fs/inode.c | 4 +++-
2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 6c7ad15000b9..2eb4821d95d1 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -491,7 +491,7 @@ static int f2fs_file_open(struct inode *inode, struct file *filp)
if (err)
return err;

- if (f2fs_verity_file(inode)) {
+ if (IS_VERITY(inode)) {
err = fsverity_file_open(inode, filp);
if (err)
return err;
@@ -701,7 +701,7 @@ int f2fs_getattr(const struct path *path, struct kstat *stat,
struct f2fs_inode *ri;
unsigned int flags;

- if (f2fs_verity_file(inode)) {
+ if (IS_VERITY(inode)) {
/*
* For fs-verity we need to override i_size with the original
* data i_size. This requires I/O to the file which with
@@ -800,7 +800,7 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
if (err)
return err;

- if (f2fs_verity_file(inode)) {
+ if (IS_VERITY(inode)) {
err = fsverity_prepare_setattr(dentry, attr);
if (err)
return err;
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index ddef483ad689..02806feed64c 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -45,9 +45,11 @@ void f2fs_set_inode_flags(struct inode *inode)
new_fl |= S_DIRSYNC;
if (f2fs_encrypted_inode(inode))
new_fl |= S_ENCRYPTED;
+ if (f2fs_verity_file(inode))
+ new_fl |= S_VERITY;
inode_set_flags(inode, new_fl,
S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|
- S_ENCRYPTED);
+ S_ENCRYPTED|S_VERITY);
}

static void __get_inode_rdev(struct inode *inode, struct f2fs_inode *ri)
--
2.19.1

2018-11-19 15:46:10

by Chandan Rajendra

[permalink] [raw]
Subject: [PATCH 2/7] f2fs: use IS_ENCRYPTED() to check encryption status

This commit removes the f2fs specific f2fs_encrypted_inode() and makes
use of the generic IS_ENCRYPTED() macro to check for the encryption
status of an inode.

Signed-off-by: Chandan Rajendra <[email protected]>
---
fs/f2fs/data.c | 4 ++--
fs/f2fs/dir.c | 10 +++++-----
fs/f2fs/file.c | 10 +++++-----
fs/f2fs/namei.c | 6 +++---
4 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 09d9fc1676a7..844ec573263e 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1491,7 +1491,7 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
}

if (size) {
- if (f2fs_encrypted_inode(inode))
+ if (IS_ENCRYPTED(inode))
flags |= FIEMAP_EXTENT_DATA_ENCRYPTED;

ret = fiemap_fill_next_extent(fieinfo, logical,
@@ -1764,7 +1764,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 */
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index bacc667950b6..cf9e2564388d 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -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);
}

@@ -808,7 +808,7 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
de_name.name = d->filename[bit_pos];
de_name.len = le16_to_cpu(de->name_len);

- if (f2fs_encrypted_inode(d->inode)) {
+ if (IS_ENCRYPTED(d->inode)) {
int save_len = fstr->len;

err = fscrypt_fname_disk_to_usr(d->inode,
@@ -852,7 +852,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;
@@ -914,7 +914,7 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)

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;
}
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 87794b2a45ff..6c7ad15000b9 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -585,7 +585,7 @@ static int truncate_partial_data_page(struct inode *inode, u64 from,
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);
@@ -730,7 +730,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;
@@ -1587,7 +1587,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;

@@ -1671,7 +1671,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;
@@ -2430,7 +2430,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) {
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index 99299ede7429..6ae37e0cf6e3 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -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;
--
2.19.1

2018-11-28 00:27:15

by Chandan Rajendra

[permalink] [raw]
Subject: Re: [PATCH 3/7] fscrypt: Remove filesystem specific build config option

On Tuesday, November 27, 2018 5:44:24 AM IST Eric Biggers wrote:
> Hi Chandan,
>
> On Mon, Nov 19, 2018 at 10:53:20AM +0530, Chandan Rajendra wrote:
> > In order to have a common code base for fscrypt "post read" processing
> > for all filesystems which support encryption, this commit removes
> > filesystem specific build config option (e.g. CONFIG_EXT4_FS_ENCRYPTION)
> > and replaces it with a build option (i.e. CONFIG_FS_ENCRYPTION) whose
> > value affects all the filesystems making use of fscrypt.
> >
> > Signed-off-by: Chandan Rajendra <[email protected]>
>
> Can you grep for EXT4_ENCRYPTION? There are still some references left, one in
> Documentation/filesystems/fscrypt.rst and some in defconfig files.
>
> Also in include/linux/fs.h, there are tests of
>
> #if IS_ENABLED(CONFIG_FS_ENCRYPTION)
>
> which after this change should be
>
> #ifdef CONFIG_FS_ENCRYPTION
>
> like is done elsewhere.

Sorry, I had restricted my search to *.[ch] files and that too within
linux/fs/ directory. I will fix the other occurrences as well.

>
> > ---
> > fs/crypto/Kconfig | 2 +-
> > fs/ext4/Kconfig | 15 --
> > fs/ext4/dir.c | 2 -
> > fs/ext4/ext4.h | 7 +-
> > fs/ext4/inode.c | 8 +-
> > fs/ext4/ioctl.c | 4 +-
> > fs/ext4/namei.c | 10 +-
> > fs/ext4/page-io.c | 6 +-
> > fs/ext4/readpage.c | 2 +-
> > fs/ext4/super.c | 6 +-
> > fs/ext4/sysfs.c | 4 +-
> > fs/f2fs/Kconfig | 11 -
> > fs/f2fs/f2fs.h | 7 +-
> > fs/f2fs/super.c | 8 +-
> > fs/f2fs/sysfs.c | 4 +-
> > include/linux/fscrypt.h | 416 +++++++++++++++++++++++++++++++-
> > include/linux/fscrypt_notsupp.h | 231 ------------------
> > include/linux/fscrypt_supp.h | 204 ----------------
> > 18 files changed, 441 insertions(+), 506 deletions(-)
> > delete mode 100644 include/linux/fscrypt_notsupp.h
> > delete mode 100644 include/linux/fscrypt_supp.h
> >
> > diff --git a/fs/crypto/Kconfig b/fs/crypto/Kconfig
> > index 02b7d91c9231..6e9ae566a8fc 100644
> > --- a/fs/crypto/Kconfig
> > +++ b/fs/crypto/Kconfig
> > @@ -1,5 +1,5 @@
> > config FS_ENCRYPTION
> > - tristate "FS Encryption (Per-file encryption)"
> > + bool "FS Encryption (Per-file encryption)"
> > select CRYPTO
> > select CRYPTO_AES
> > select CRYPTO_CBC
> > diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
> > index 5a76125ac0f8..e1002bbf35bf 100644
> > --- a/fs/ext4/Kconfig
> > +++ b/fs/ext4/Kconfig
> > @@ -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_FS_VERITY
> > bool "Ext4 Verity"
> > depends on EXT4_FS
> > diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
> > index fb7a64ea5679..0ccd51f72048 100644
> > --- a/fs/ext4/dir.c
> > +++ b/fs/ext4/dir.c
> > @@ -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;
> > }
> > diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
> > index 2ae6ab88f218..db21df885186 100644
> > --- a/fs/ext4/ext4.h
> > +++ b/fs/ext4/ext4.h
> > @@ -40,7 +40,6 @@
> > #include <linux/compat.h>
> > #endif
> >
> > -#define __FS_HAS_ENCRYPTION IS_ENABLED(CONFIG_EXT4_FS_ENCRYPTION)
> > #include <linux/fscrypt.h>
> >
> > #define __FS_HAS_VERITY IS_ENABLED(CONFIG_EXT4_FS_VERITY)
> > @@ -1341,7 +1340,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
> > @@ -2069,7 +2068,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
> > };
> > @@ -2306,7 +2305,7 @@ static inline bool ext4_verity_inode(struct inode *inode)
> > #endif
> > }
> >
> > -#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)
> > diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> > index 725777772f32..ae6794649817 100644
> > --- a/fs/ext4/inode.c
> > +++ b/fs/ext4/inode.c
> > @@ -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)
> > {
> > @@ -1303,7 +1303,7 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
> > /* 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);
> > @@ -3104,7 +3104,7 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
> > /* 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
> > @@ -3879,7 +3879,7 @@ 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
> > +#ifdef CONFIG_FS_ENCRYPTION
> > if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
> > return 0;
> > #endif
> > diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
> > index 9bb6cc1ae8ce..892fb1925836 100644
> > --- a/fs/ext4/ioctl.c
> > +++ b/fs/ext4/ioctl.c
> > @@ -210,7 +210,7 @@ static long swap_inode_boot_loader(struct super_block *sb,
> > 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 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> > 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;
> > diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
> > index 0de60207a963..1e1a3c8c3a8b 100644
> > --- a/fs/ext4/namei.c
> > +++ b/fs/ext4/namei.c
> > @@ -611,7 +611,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 =
> > @@ -983,7 +983,7 @@ 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 (IS_ENCRYPTED(dir)) {
> > err = fscrypt_get_encryption_info(dir);
> > @@ -1046,7 +1046,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;
> > @@ -1266,7 +1266,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);
> > @@ -1497,7 +1497,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);
> > diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
> > index 008c20b58f98..7d5f12be07ab 100644
> > --- a/fs/ext4/page-io.c
> > +++ b/fs/ext4/page-io.c
> > @@ -66,7 +66,7 @@ static void ext4_finish_bio(struct bio *bio)
> >
> > bio_for_each_segment_all(bvec, bio, i) {
> > 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;
> > @@ -78,7 +78,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;
> > @@ -111,7 +111,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
> > diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
> > index 45e707fb9749..7252f0a60cdb 100644
> > --- a/fs/ext4/readpage.c
> > +++ b/fs/ext4/readpage.c
> > @@ -54,7 +54,7 @@ static mempool_t *bio_post_read_ctx_pool;
> >
> > 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;
> > diff --git a/fs/ext4/super.c b/fs/ext4/super.c
> > index fb4e060f28ec..16fb483a6f4a 100644
> > --- a/fs/ext4/super.c
> > +++ b/fs/ext4/super.c
> > @@ -1210,7 +1210,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,
> > @@ -1986,7 +1986,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");
> > @@ -4231,7 +4231,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_EXT4_FS_VERITY
> > diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
> > index 8e86087c2f03..8bc915452a38 100644
> > --- a/fs/ext4/sysfs.c
> > +++ b/fs/ext4/sysfs.c
> > @@ -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
> > #ifdef CONFIG_EXT4_FS_VERITY
> > @@ -236,7 +236,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
> > #ifdef CONFIG_EXT4_FS_VERITY
> > diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig
> > index c8396c7220f2..ce60e480fec1 100644
> > --- a/fs/f2fs/Kconfig
> > +++ b/fs/f2fs/Kconfig
> > @@ -70,17 +70,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_FS_VERITY
> > bool "F2FS Verity"
> > depends on F2FS_FS
> > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> > index dadb5f468f20..ea8a5ffc4f1f 100644
> > --- a/fs/f2fs/f2fs.h
> > +++ b/fs/f2fs/f2fs.h
> > @@ -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>
> >
> > #define __FS_HAS_VERITY IS_ENABLED(CONFIG_F2FS_FS_VERITY)
> > @@ -1145,7 +1144,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
> > @@ -3448,7 +3447,7 @@ static inline bool f2fs_encrypted_file(struct inode *inode)
> >
> > 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
> > @@ -3533,7 +3532,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));
> > diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> > index adf38c1b6414..4287cf348d3c 100644
> > --- a/fs/f2fs/super.c
> > +++ b/fs/f2fs/super.c
> > @@ -757,7 +757,7 @@ static int parse_options(struct super_block *sb, char *options)
> > kfree(name);
> > break;
> > case Opt_test_dummy_encryption:
> > -#ifdef CONFIG_F2FS_FS_ENCRYPTION
> > +#ifdef CONFIG_FS_ENCRYPTION
> > if (!f2fs_sb_has_encrypt(sb)) {
> > f2fs_msg(sb, KERN_ERR, "Encrypt feature is off");
> > return -EINVAL;
> > @@ -1387,7 +1387,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,
> > @@ -3143,7 +3143,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
> > #endif
> >
> > sb->s_op = &f2fs_sops;
> > -#ifdef CONFIG_F2FS_FS_ENCRYPTION
> > +#ifdef CONFIG_FS_ENCRYPTION
> > sb->s_cop = &f2fs_cryptops;
> > #endif
> > #ifdef CONFIG_F2FS_FS_VERITY
> > diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
> > index 5599c9ac4426..737677655bc0 100644
> > --- a/fs/f2fs/sysfs.c
> > +++ b/fs/f2fs/sysfs.c
> > @@ -430,7 +430,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
> > @@ -493,7 +493,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
> > diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
> > index 952ab97af325..6ba193c23f37 100644
> > --- a/include/linux/fscrypt.h
> > +++ b/include/linux/fscrypt.h
> > @@ -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
> > diff --git a/include/linux/fscrypt_notsupp.h b/include/linux/fscrypt_notsupp.h
> > deleted file mode 100644
> > index ee8b43e4c15a..000000000000
> > --- a/include/linux/fscrypt_notsupp.h
> > +++ /dev/null
> > @@ -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 */
> > diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h
> > deleted file mode 100644
> > index 6456c6b2005f..000000000000
> > --- a/include/linux/fscrypt_supp.h
> > +++ /dev/null
> > @@ -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 */
>
>

--
chandan

2018-11-19 15:46:49

by Chandan Rajendra

[permalink] [raw]
Subject: [PATCH 7/7] fsverity: Remove filesystem specific build config option

In order to have a common code base for fsverity "post read" processing
for all filesystems which support per-file verity, this commit removes
filesystem specific build config option (e.g. CONFIG_EXT4_FS_VERITY) and
replaces it with a build option (i.e. CONFIG_FS_VERITY) whose value
affects all the filesystems making use of fsverity.

Signed-off-by: Chandan Rajendra <[email protected]>
---
fs/ext4/Kconfig | 20 --------------------
fs/ext4/ext4.h | 2 --
fs/ext4/readpage.c | 4 ++--
fs/ext4/super.c | 6 +++---
fs/ext4/sysfs.c | 4 ++--
fs/f2fs/Kconfig | 20 --------------------
fs/f2fs/data.c | 2 +-
fs/f2fs/f2fs.h | 2 --
fs/f2fs/super.c | 6 +++---
fs/f2fs/sysfs.c | 4 ++--
fs/verity/Kconfig | 2 +-
include/linux/fsverity.h | 3 +--
12 files changed, 15 insertions(+), 60 deletions(-)

diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
index e1002bbf35bf..031e5a82d556 100644
--- a/fs/ext4/Kconfig
+++ b/fs/ext4/Kconfig
@@ -96,26 +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_FS_VERITY
- bool "Ext4 Verity"
- depends on EXT4_FS
- select FS_VERITY
- help
- This option enables fs-verity for ext4. fs-verity is the
- dm-verity mechanism implemented at the file level. Userspace
- can append a Merkle tree (hash tree) to a file, then enable
- fs-verity on the file. ext4 will then transparently verify
- any data read from the file against the Merkle tree. The file
- is also made read-only.
-
- This serves as an integrity check, but the availability of the
- Merkle tree root hash also allows efficiently supporting
- various use cases where normally the whole file would need to
- be hashed at once, such as auditing and authenticity
- verification (appraisal).
-
- If unsure, say N.
-
config EXT4_DEBUG
bool "EXT4 debugging support"
depends on EXT4_FS
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 64bf9fb7ef18..bff8d639dd0c 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -41,8 +41,6 @@
#endif

#include <linux/fscrypt.h>
-
-#define __FS_HAS_VERITY IS_ENABLED(CONFIG_EXT4_FS_VERITY)
#include <linux/fsverity.h>

#include <linux/compiler.h>
diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
index 2c037df629dd..8717ac0a5bb2 100644
--- a/fs/ext4/readpage.c
+++ b/fs/ext4/readpage.c
@@ -158,7 +158,7 @@ static struct bio_post_read_ctx *get_bio_post_read_ctx(struct inode *inode,

if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
post_read_steps |= 1 << STEP_DECRYPT;
-#ifdef CONFIG_EXT4_FS_VERITY
+#ifdef CONFIG_FS_VERITY
if (inode->i_verity_info != NULL &&
(index < ((i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT)))
post_read_steps |= 1 << STEP_VERITY;
@@ -205,7 +205,7 @@ static void mpage_end_io(struct bio *bio)

static inline loff_t ext4_readpage_limit(struct inode *inode)
{
-#ifdef CONFIG_EXT4_FS_VERITY
+#ifdef CONFIG_FS_VERITY
if (IS_VERITY(inode)) {
if (inode->i_verity_info)
/* limit to end of metadata region */
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 16fb483a6f4a..472338c7cd03 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1316,7 +1316,7 @@ static const struct fscrypt_operations ext4_cryptops = {
};
#endif

-#ifdef CONFIG_EXT4_FS_VERITY
+#ifdef CONFIG_FS_VERITY
static int ext4_set_verity(struct inode *inode, loff_t data_i_size)
{
int err;
@@ -1401,7 +1401,7 @@ static const struct fsverity_operations ext4_verityops = {
.set_verity = ext4_set_verity,
.get_metadata_end = ext4_get_metadata_end,
};
-#endif /* CONFIG_EXT4_FS_VERITY */
+#endif /* CONFIG_FS_VERITY */

#ifdef CONFIG_QUOTA
static const char * const quotatypes[] = INITQFNAMES;
@@ -4234,7 +4234,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
#ifdef CONFIG_FS_ENCRYPTION
sb->s_cop = &ext4_cryptops;
#endif
-#ifdef CONFIG_EXT4_FS_VERITY
+#ifdef CONFIG_FS_VERITY
sb->s_vop = &ext4_verityops;
#endif
#ifdef CONFIG_QUOTA
diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
index 8bc915452a38..6fa0f47c3180 100644
--- a/fs/ext4/sysfs.c
+++ b/fs/ext4/sysfs.c
@@ -227,7 +227,7 @@ EXT4_ATTR_FEATURE(meta_bg_resize);
#ifdef CONFIG_FS_ENCRYPTION
EXT4_ATTR_FEATURE(encryption);
#endif
-#ifdef CONFIG_EXT4_FS_VERITY
+#ifdef CONFIG_FS_VERITY
EXT4_ATTR_FEATURE(verity);
#endif
EXT4_ATTR_FEATURE(metadata_csum_seed);
@@ -239,7 +239,7 @@ static struct attribute *ext4_feat_attrs[] = {
#ifdef CONFIG_FS_ENCRYPTION
ATTR_LIST(encryption),
#endif
-#ifdef CONFIG_EXT4_FS_VERITY
+#ifdef CONFIG_FS_VERITY
ATTR_LIST(verity),
#endif
ATTR_LIST(metadata_csum_seed),
diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig
index ce60e480fec1..708e23816575 100644
--- a/fs/f2fs/Kconfig
+++ b/fs/f2fs/Kconfig
@@ -70,26 +70,6 @@ config F2FS_CHECK_FS

If you want to improve the performance, say N.

-config F2FS_FS_VERITY
- bool "F2FS Verity"
- depends on F2FS_FS
- select FS_VERITY
- help
- This option enables fs-verity for f2fs. fs-verity is the
- dm-verity mechanism implemented at the file level. Userspace
- can append a Merkle tree (hash tree) to a file, then enable
- fs-verity on the file. f2fs will then transparently verify
- any data read from the file against the Merkle tree. The file
- is also made read-only.
-
- This serves as an integrity check, but the availability of the
- Merkle tree root hash also allows efficiently supporting
- various use cases where normally the whole file would need to
- be hashed at once, such as auditing and authenticity
- verification (appraisal).
-
- If unsure, say N.
-
config F2FS_IO_TRACE
bool "F2FS IO tracer"
depends on F2FS_FS
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 844ec573263e..83b59b985894 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -610,7 +610,7 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr,

if (f2fs_encrypted_file(inode))
post_read_steps |= 1 << STEP_DECRYPT;
-#ifdef CONFIG_F2FS_FS_VERITY
+#ifdef CONFIG_FS_VERITY
if (inode->i_verity_info != NULL &&
(first_idx < ((i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT)))
post_read_steps |= 1 << STEP_VERITY;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index ea8a5ffc4f1f..dc999af932f2 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -25,8 +25,6 @@
#include <crypto/hash.h>

#include <linux/fscrypt.h>
-
-#define __FS_HAS_VERITY IS_ENABLED(CONFIG_F2FS_FS_VERITY)
#include <linux/fsverity.h>

#ifdef CONFIG_F2FS_CHECK_FS
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 4287cf348d3c..60d5338280fb 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -2197,7 +2197,7 @@ static const struct fscrypt_operations f2fs_cryptops = {
};
#endif

-#ifdef CONFIG_F2FS_FS_VERITY
+#ifdef CONFIG_FS_VERITY
static int f2fs_set_verity(struct inode *inode, loff_t data_i_size)
{
int err;
@@ -2222,7 +2222,7 @@ static const struct fsverity_operations f2fs_verityops = {
.set_verity = f2fs_set_verity,
.get_metadata_end = f2fs_get_metadata_end,
};
-#endif /* CONFIG_F2FS_FS_VERITY */
+#endif /* CONFIG_FS_VERITY */

static struct inode *f2fs_nfs_get_inode(struct super_block *sb,
u64 ino, u32 generation)
@@ -3146,7 +3146,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
#ifdef CONFIG_FS_ENCRYPTION
sb->s_cop = &f2fs_cryptops;
#endif
-#ifdef CONFIG_F2FS_FS_VERITY
+#ifdef CONFIG_FS_VERITY
sb->s_vop = &f2fs_verityops;
#endif
sb->s_xattr = f2fs_xattr_handlers;
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index 737677655bc0..949e6d87f4e3 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -444,7 +444,7 @@ F2FS_FEATURE_RO_ATTR(flexible_inline_xattr, FEAT_FLEXIBLE_INLINE_XATTR);
F2FS_FEATURE_RO_ATTR(quota_ino, FEAT_QUOTA_INO);
F2FS_FEATURE_RO_ATTR(inode_crtime, FEAT_INODE_CRTIME);
F2FS_FEATURE_RO_ATTR(lost_found, FEAT_LOST_FOUND);
-#ifdef CONFIG_F2FS_FS_VERITY
+#ifdef CONFIG_FS_VERITY
F2FS_FEATURE_RO_ATTR(verity, FEAT_VERITY);
#endif
F2FS_FEATURE_RO_ATTR(sb_checksum, FEAT_SB_CHECKSUM);
@@ -507,7 +507,7 @@ static struct attribute *f2fs_feat_attrs[] = {
ATTR_LIST(quota_ino),
ATTR_LIST(inode_crtime),
ATTR_LIST(lost_found),
-#ifdef CONFIG_F2FS_FS_VERITY
+#ifdef CONFIG_FS_VERITY
ATTR_LIST(verity),
#endif
ATTR_LIST(sb_checksum),
diff --git a/fs/verity/Kconfig b/fs/verity/Kconfig
index a7470a2e4892..b5a48a9ef0ca 100644
--- a/fs/verity/Kconfig
+++ b/fs/verity/Kconfig
@@ -1,5 +1,5 @@
config FS_VERITY
- tristate "FS Verity (read-only file-based authenticity protection)"
+ bool "FS Verity (read-only file-based authenticity protection)"
select CRYPTO
# SHA-256 is selected as it's intended to be the default hash algorithm.
# To avoid bloat, other wanted algorithms must be selected explicitly.
diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h
index c30c4f6ed411..f37132c640ee 100644
--- a/include/linux/fsverity.h
+++ b/include/linux/fsverity.h
@@ -19,8 +19,7 @@ struct fsverity_operations {
int (*get_metadata_end)(struct inode *inode, loff_t *metadata_end_ret);
};

-#if __FS_HAS_VERITY
-
+#ifdef CONFIG_FS_VERITY
/* ioctl.c */
extern int fsverity_ioctl_enable(struct file *filp, const void __user *arg);
extern int fsverity_ioctl_measure(struct file *filp, void __user *arg);
--
2.19.1

2018-11-20 07:49:05

by Jaegeuk Kim

[permalink] [raw]
Subject: Re: [f2fs-dev] [PATCH 2/7] f2fs: use IS_ENCRYPTED() to check encryption status

Hi Chandan,

Let me try to queue and test this patch separately from the patch-set in order
to avoid merge conflicts. So, I think IS_ENCRYPTED should be merged in f2fs/ext4
branches, and the others can be applied to fscrypt and fsverity into each trees.

Thanks,

On 11/19, Chandan Rajendra wrote:
> This commit removes the f2fs specific f2fs_encrypted_inode() and makes
> use of the generic IS_ENCRYPTED() macro to check for the encryption
> status of an inode.
>
> Signed-off-by: Chandan Rajendra <[email protected]>
> ---
> fs/f2fs/data.c | 4 ++--
> fs/f2fs/dir.c | 10 +++++-----
> fs/f2fs/file.c | 10 +++++-----
> fs/f2fs/namei.c | 6 +++---
> 4 files changed, 15 insertions(+), 15 deletions(-)
>
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index 09d9fc1676a7..844ec573263e 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -1491,7 +1491,7 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
> }
>
> if (size) {
> - if (f2fs_encrypted_inode(inode))
> + if (IS_ENCRYPTED(inode))
> flags |= FIEMAP_EXTENT_DATA_ENCRYPTED;
>
> ret = fiemap_fill_next_extent(fieinfo, logical,
> @@ -1764,7 +1764,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 */
> diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
> index bacc667950b6..cf9e2564388d 100644
> --- a/fs/f2fs/dir.c
> +++ b/fs/f2fs/dir.c
> @@ -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);
> }
>
> @@ -808,7 +808,7 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
> de_name.name = d->filename[bit_pos];
> de_name.len = le16_to_cpu(de->name_len);
>
> - if (f2fs_encrypted_inode(d->inode)) {
> + if (IS_ENCRYPTED(d->inode)) {
> int save_len = fstr->len;
>
> err = fscrypt_fname_disk_to_usr(d->inode,
> @@ -852,7 +852,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;
> @@ -914,7 +914,7 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
>
> 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;
> }
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 87794b2a45ff..6c7ad15000b9 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -585,7 +585,7 @@ static int truncate_partial_data_page(struct inode *inode, u64 from,
> 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);
> @@ -730,7 +730,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;
> @@ -1587,7 +1587,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;
>
> @@ -1671,7 +1671,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;
> @@ -2430,7 +2430,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) {
> diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
> index 99299ede7429..6ae37e0cf6e3 100644
> --- a/fs/f2fs/namei.c
> +++ b/fs/f2fs/namei.c
> @@ -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;
> --
> 2.19.1
>
>
>
> _______________________________________________
> Linux-f2fs-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

2018-11-27 11:25:15

by Eric Biggers

[permalink] [raw]
Subject: Re: [PATCH 5/7] ext4: use IS_VERITY() to check inode's fsverity status

On Mon, Nov 26, 2018 at 12:36:15PM -0500, Theodore Y. Ts'o wrote:
> On Mon, Nov 19, 2018 at 10:53:22AM +0530, Chandan Rajendra wrote:
> > This commit now uses IS_VERITY() macro to check if fsverity is
> > enabled on an inode.
> >
> > Signed-off-by: Chandan Rajendra <[email protected]>
>
> This patch causes a massive number of fsverity tests. I suspect it's
> due to a mismatch between the ext4's inode flags as opposed to the VFS
> inode's flags. I'll take a closer look in the next day or two.
>
> Cheers,
>
> - Ted

It's missing the following to set S_VERITY during the
FS_IOC_ENABLE_VERITY ioctl:

diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index ed933e64e95f..82b45cceb39b 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1344,6 +1344,11 @@ static int ext4_set_verity(struct inode *inode, loff_t data_i_size)
err = ext4_reserve_inode_write(handle, inode, &iloc);
if (err == 0) {
ext4_set_inode_flag(inode, EXT4_INODE_VERITY);
+ /*
+ * Update inode->i_flags - S_VERITY will be enabled,
+ * S_DAX may be disabled
+ */
+ ext4_set_inode_flags(inode);
EXT4_I(inode)->i_disksize = data_i_size;
err = ext4_mark_iloc_dirty(handle, inode, &iloc);
}

2018-11-27 11:04:34

by Eric Biggers

[permalink] [raw]
Subject: Re: [PATCH 4/7] Add S_VERITY and IS_VERITY()

Hi Chandan,

On Mon, Nov 19, 2018 at 10:53:21AM +0530, Chandan Rajendra wrote:
> Similar to S_ENCRYPTED/IS_ENCRYPTED(), this commit adds
> S_VERITY/IS_VERITY() to be able to check if a VFS inode has verity
> information associated with it.
>
> Signed-off-by: Chandan Rajendra <[email protected]>
> ---
> include/linux/fs.h | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index bcfc40062757..8129617c9718 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -1938,6 +1938,7 @@ struct super_operations {
> #define S_DAX 0 /* Make all the DAX code disappear */
> #endif
> #define S_ENCRYPTED 16384 /* Encrypted file (using fs/crypto/) */
> +#define S_VERITY 32768 /* File with fsverity info (using fs/verity) */
>

The comment for S_VERITY is misleading because IS_VERITY() is used to check
whether the verity bit is set *before* the fsverity_info is created.

Can you change it to just mirror the fscrypt comment?

#define S_VERITY 32768 /* Verity file (using fs/verity/) */

> /*
> * Note that nosuid etc flags are inode-specific: setting some file-system
> @@ -1978,6 +1979,7 @@ static inline bool sb_rdonly(const struct super_block *sb) { return sb->s_flags
> #define IS_NOSEC(inode) ((inode)->i_flags & S_NOSEC)
> #define IS_DAX(inode) ((inode)->i_flags & S_DAX)
> #define IS_ENCRYPTED(inode) ((inode)->i_flags & S_ENCRYPTED)
> +#define IS_VERITY(inode) ((inode)->i_flags & S_VERITY)
>
> #define IS_WHITEOUT(inode) (S_ISCHR(inode->i_mode) && \
> (inode)->i_rdev == WHITEOUT_DEV)
> --
> 2.19.1
>

Thanks,

- Eric

2018-11-30 16:36:06

by Chandan Rajendra

[permalink] [raw]
Subject: Re: [f2fs-dev] [PATCH 2/7] f2fs: use IS_ENCRYPTED() to check encryption status

On Friday, November 30, 2018 12:35:13 AM IST Eric Biggers wrote:
> Hi Chandan,
>
> On Thu, Nov 29, 2018 at 04:08:31PM +0530, Chandan Rajendra wrote:
> > On Monday, November 26, 2018 11:04:35 PM IST Theodore Y. Ts'o wrote:
> > > On Sun, Nov 25, 2018 at 11:00:38PM -0500, Theodore Y. Ts'o wrote:
> > > >
> > > > It might be that the simplest way to solve things is to merge the f2fs
> > > > dev branch up to 79c66e75720c. This will have the net effect of
> > > > including the five patches listed above onto the fscrypt git tree. So
> > > > long you don't plan to rebase or otherwise change these five patches,
> > > > it should avoid any merge conflicts.
> > >
> > > I've set up a git branch which has the f2fs dev branch, 4.20-rc4, the
> > > fsverity patches, and part of Chandan's patch series here:
> > >
> > > git://git.kernel.org/pub/scm/linux/kernel/git/tytso/fscrypt.git test-working
> > >
> > > There is a minor conflict when I did a trial merge with f2fs.git's dev
> > > branch, but it's pretty obvious to how to resolve it.
> > >
> > > Jaegeuk, Eric, Chandan, please take a look and let me know what you
> > > think.
> >
> > Ted,
> >
> > I have addressed the review comments provided by Eric. Hence three out of
> > the four patches in the test-working branch have new changes. I also got
> > UBIFS to use CONFIG_FS_ENCRYPTION instead of the per-filesystem config
> > symbol.
> >
> > I am currently executing fstests to verify the changes.
> >
> >
> > Eric,
> >
> > When executing generic/900, I noticed that sometimes xfs_io would get stuck
> > for an indefinite period. /proc/<pid of xfs_io>/stack showed that the task was
> > stuck in tty_read() inside the kernel. The following change fixed it,
> >
> > diff --git a/tests/generic/900 b/tests/generic/900
> > index 290889ce..0831eed4 100755
> > --- a/tests/generic/900
> > +++ b/tests/generic/900
> > @@ -83,7 +83,7 @@ _fsv_create_enable_file $fsv_file >> $seqres.full
> > echo "* reading"
> > $XFS_IO_PROG -r $fsv_file -c ''
> > echo "* xfs_io writing, should be O_RDWR"
> > -$XFS_IO_PROG $fsv_file |& _filter_scratch
> > +$XFS_IO_PROG -c '' $fsv_file 2>&1 | _filter_scratch
> > echo "* bash >>, should be O_APPEND"
> > bash -c "echo >> $fsv_file" |& _filter_scratch
> > echo "* bash >, should be O_WRONLY|O_CREAT|O_TRUNC"
> >
> > xfs_io gets into interactive mode when invoked without a "-c cmd" string.
> >
> > However, I am not able recreate the scenario once again without the above
> > changes applied. I am not sure about what changed.
> >
>
> The test is opening a verity file for read+write access, which should fail. But
> it's incorrectly succeeding, hence the test is right to not pass. Did you add
> the missing call to ext4_set_inode_flags() in ext4_set_verity() as I
> suggested?
>
> (But I'll make the suggested change to the test too, so it fails cleanly in this
> case rather than hangs reading from stdin.)

Yes, I did make the suggested changes. But the test would some times hang
indefinitely because of xfs_io waiting on input from stdin.

With the new changes made to ext4_set_verity(), I see that the fsck fails
consistency check. But the failure is seen even without my patches applied. I
have planned to debug the failure after I post the next version of the
patchset.

--
chandan

2018-11-26 14:34:22

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [f2fs-dev] [PATCH 2/7] f2fs: use IS_ENCRYPTED() to check encryption status

On Mon, Nov 19, 2018 at 01:23:32PM -0800, Jaegeuk Kim wrote:
> Hi Chandan,
>
> Let me try to queue and test this patch separately from the patch-set in order
> to avoid merge conflicts. So, I think IS_ENCRYPTED should be merged in f2fs/ext4
> branches, and the others can be applied to fscrypt and fsverity into each trees.

Hi Jaeguk,

What conflicts are you anticipating? I can't apply the rest of
Chandan's patches without unless we apply them in order, and I'd
prefer to avoid cross-merging, or spreading out this series across two
kernel releases.

- Ted

2018-11-27 11:37:14

by Eric Biggers

[permalink] [raw]
Subject: Re: [PATCH 6/7] f2fs: use IS_VERITY() to check inode's fsverity status

Hi Chandan,

On Mon, Nov 19, 2018 at 10:53:23AM +0530, Chandan Rajendra wrote:
> This commit now uses IS_VERITY() macro to check if fsverity is
> enabled on an inode.
>
> Signed-off-by: Chandan Rajendra <[email protected]>
> ---
> fs/f2fs/file.c | 6 +++---
> fs/f2fs/inode.c | 4 +++-
> 2 files changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 6c7ad15000b9..2eb4821d95d1 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -491,7 +491,7 @@ static int f2fs_file_open(struct inode *inode, struct file *filp)
> if (err)
> return err;
>
> - if (f2fs_verity_file(inode)) {
> + if (IS_VERITY(inode)) {
> err = fsverity_file_open(inode, filp);
> if (err)
> return err;
> @@ -701,7 +701,7 @@ int f2fs_getattr(const struct path *path, struct kstat *stat,
> struct f2fs_inode *ri;
> unsigned int flags;
>
> - if (f2fs_verity_file(inode)) {
> + if (IS_VERITY(inode)) {
> /*
> * For fs-verity we need to override i_size with the original
> * data i_size. This requires I/O to the file which with
> @@ -800,7 +800,7 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
> if (err)
> return err;
>
> - if (f2fs_verity_file(inode)) {
> + if (IS_VERITY(inode)) {
> err = fsverity_prepare_setattr(dentry, attr);
> if (err)
> return err;
> diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
> index ddef483ad689..02806feed64c 100644
> --- a/fs/f2fs/inode.c
> +++ b/fs/f2fs/inode.c
> @@ -45,9 +45,11 @@ void f2fs_set_inode_flags(struct inode *inode)
> new_fl |= S_DIRSYNC;
> if (f2fs_encrypted_inode(inode))
> new_fl |= S_ENCRYPTED;
> + if (f2fs_verity_file(inode))
> + new_fl |= S_VERITY;
> inode_set_flags(inode, new_fl,
> S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|
> - S_ENCRYPTED);
> + S_ENCRYPTED|S_VERITY);
> }
>
> static void __get_inode_rdev(struct inode *inode, struct f2fs_inode *ri)
> --
> 2.19.1

Like the ext4 patch, it's missing syncing the verity flag to the VFS inode
during FS_IOC_ENABLE_VERITY:

diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 4f58d5840d17..841019d8bc96 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -2207,6 +2207,7 @@ static int f2fs_set_verity(struct inode *inode, loff_t data_i_size)
return err;

file_set_verity(inode);
+ f2fs_set_inode_flags(inode);
f2fs_mark_inode_dirty_sync(inode, true);
return 0;
}

2018-11-19 15:46:19

by Chandan Rajendra

[permalink] [raw]
Subject: [PATCH 4/7] Add S_VERITY and IS_VERITY()

Similar to S_ENCRYPTED/IS_ENCRYPTED(), this commit adds
S_VERITY/IS_VERITY() to be able to check if a VFS inode has verity
information associated with it.

Signed-off-by: Chandan Rajendra <[email protected]>
---
include/linux/fs.h | 2 ++
1 file changed, 2 insertions(+)

diff --git a/include/linux/fs.h b/include/linux/fs.h
index bcfc40062757..8129617c9718 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1938,6 +1938,7 @@ struct super_operations {
#define S_DAX 0 /* Make all the DAX code disappear */
#endif
#define S_ENCRYPTED 16384 /* Encrypted file (using fs/crypto/) */
+#define S_VERITY 32768 /* File with fsverity info (using fs/verity) */

/*
* Note that nosuid etc flags are inode-specific: setting some file-system
@@ -1978,6 +1979,7 @@ static inline bool sb_rdonly(const struct super_block *sb) { return sb->s_flags
#define IS_NOSEC(inode) ((inode)->i_flags & S_NOSEC)
#define IS_DAX(inode) ((inode)->i_flags & S_DAX)
#define IS_ENCRYPTED(inode) ((inode)->i_flags & S_ENCRYPTED)
+#define IS_VERITY(inode) ((inode)->i_flags & S_VERITY)

#define IS_WHITEOUT(inode) (S_ISCHR(inode->i_mode) && \
(inode)->i_rdev == WHITEOUT_DEV)
--
2.19.1

2018-11-29 00:51:00

by Chandan Rajendra

[permalink] [raw]
Subject: Re: [PATCH 5/7] ext4: use IS_VERITY() to check inode's fsverity status

On Monday, November 26, 2018 11:06:15 PM IST Theodore Y. Ts'o wrote:
> On Mon, Nov 19, 2018 at 10:53:22AM +0530, Chandan Rajendra wrote:
> > This commit now uses IS_VERITY() macro to check if fsverity is
> > enabled on an inode.
> >
> > Signed-off-by: Chandan Rajendra <[email protected]>
>
> This patch causes a massive number of fsverity tests. I suspect it's
> due to a mismatch between the ext4's inode flags as opposed to the VFS
> inode's flags. I'll take a closer look in the next day or two.
>
> Cheers,
>
> - Ted
>
>

Hi Ted,

I have fixed the problem. I will check the fix once again tomorrow and execute
the tests. I will be able to post the patches by end of tomorrow.

I will take a look at the commits that you have added at
git://git.kernel.org/pub/scm/linux/kernel/git/tytso/fscrypt.git test-working
tomorrow.

--
chandan