fs, fscrypt: add an S_ENCRYPTED inode flag
authorEric Biggers <ebiggers@google.com>
Mon, 9 Oct 2017 19:15:35 +0000 (12:15 -0700)
committerJaegeuk Kim <jaegeuk@kernel.org>
Fri, 5 Jan 2018 00:17:15 +0000 (16:17 -0800)
Introduce a flag S_ENCRYPTED which can be set in ->i_flags to indicate
that the inode is encrypted using the fscrypt (fs/crypto/) mechanism.

Checking this flag will give the same information that
inode->i_sb->s_cop->is_encrypted(inode) currently does, but will be more
efficient.  This will be useful for adding higher-level helper functions
for filesystems to use.  For example we'll be able to replace this:

if (ext4_encrypted_inode(inode)) {
ret = fscrypt_get_encryption_info(inode);
if (ret)
return ret;
if (!fscrypt_has_encryption_key(inode))
return -ENOKEY;
}

with this:

ret = fscrypt_require_key(inode);
if (ret)
return ret;

... since we'll be able to retain the fast path for unencrypted files as
a single flag check, using an inline function.  This wasn't possible
before because we'd have had to frequently call through the
->i_sb->s_cop->is_encrypted function pointer, even when the encryption
support was disabled or not being used.

Note: we don't define S_ENCRYPTED to 0 if CONFIG_FS_ENCRYPTION is
disabled because we want to continue to return an error if an encrypted
file is accessed without encryption support, rather than pretending that
it is unencrypted.

Reviewed-by: Chao Yu <yuchao0@huawei.com>
Acked-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
fs/ext4/inode.c
fs/ext4/super.c
fs/f2fs/f2fs.h
fs/f2fs/inode.c
fs/ubifs/ioctl.c
fs/ubifs/xattr.c
include/linux/fs.h

index 38eb621edd80c95f902145fbe0ec164e1314822c..a9df4d50a4260c554178919d865d3ff45de6e8c4 100644 (file)
@@ -4590,10 +4590,13 @@ void ext4_set_inode_flags(struct inode *inode)
                new_fl |= S_DIRSYNC;
        if (test_opt(inode->i_sb, DAX) && S_ISREG(inode->i_mode) &&
            !ext4_should_journal_data(inode) && !ext4_has_inline_data(inode) &&
-           !ext4_encrypted_inode(inode))
+           !(flags & EXT4_ENCRYPT_FL))
                new_fl |= S_DAX;
+       if (flags & EXT4_ENCRYPT_FL)
+               new_fl |= S_ENCRYPTED;
        inode_set_flags(inode, new_fl,
-                       S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|S_DAX);
+                       S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|S_DAX|
+                       S_ENCRYPTED);
 }
 
 static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode,
index f29351c666109752c09b64ba9f9ea47f55095971..aa94c3885170bb6c95ffe2414de4fd6dfa29219e 100644 (file)
@@ -1181,7 +1181,8 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
                        ext4_clear_inode_state(inode,
                                        EXT4_STATE_MAY_INLINE_DATA);
                        /*
-                        * Update inode->i_flags - e.g. S_DAX may get disabled
+                        * Update inode->i_flags - S_ENCRYPTED will be enabled,
+                        * S_DAX may be disabled
                         */
                        ext4_set_inode_flags(inode);
                }
@@ -1206,7 +1207,10 @@ retry:
                                    ctx, len, 0);
        if (!res) {
                ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
-               /* Update inode->i_flags - e.g. S_DAX may get disabled */
+               /*
+                * Update inode->i_flags - S_ENCRYPTED will be enabled,
+                * S_DAX may be disabled
+                */
                ext4_set_inode_flags(inode);
                res = ext4_mark_inode_dirty(handle, inode);
                if (res)
index ea76751ab2d0d93e6ce1d224bf3885d969fa24d7..f4e094e816c63df79bd40f62b097147826037dae 100644 (file)
@@ -3065,6 +3065,7 @@ static inline void f2fs_set_encrypted_inode(struct inode *inode)
 {
 #ifdef CONFIG_F2FS_FS_ENCRYPTION
        file_set_encrypt(inode);
+       inode->i_flags |= S_ENCRYPTED;
 #endif
 }
 
index 9684d53563f13b1654c12ae4027d9366480d23b7..b4c4f2b2530404d5dc5b60bafab86a910c1a7879 100644 (file)
@@ -43,8 +43,11 @@ void f2fs_set_inode_flags(struct inode *inode)
                new_fl |= S_NOATIME;
        if (flags & FS_DIRSYNC_FL)
                new_fl |= S_DIRSYNC;
+       if (f2fs_encrypted_inode(inode))
+               new_fl |= S_ENCRYPTED;
        inode_set_flags(inode, new_fl,
-                       S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
+                       S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|
+                       S_ENCRYPTED);
 }
 
 static void __get_inode_rdev(struct inode *inode, struct f2fs_inode *ri)
index fdc311246807a4c3a018ff53e06f44614f5c6800..0164bcc827f891cf7d3e2cbead41989336244786 100644 (file)
@@ -38,7 +38,8 @@ void ubifs_set_inode_flags(struct inode *inode)
 {
        unsigned int flags = ubifs_inode(inode)->flags;
 
-       inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE | S_DIRSYNC);
+       inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE | S_DIRSYNC |
+                           S_ENCRYPTED);
        if (flags & UBIFS_SYNC_FL)
                inode->i_flags |= S_SYNC;
        if (flags & UBIFS_APPEND_FL)
@@ -47,6 +48,8 @@ void ubifs_set_inode_flags(struct inode *inode)
                inode->i_flags |= S_IMMUTABLE;
        if (flags & UBIFS_DIRSYNC_FL)
                inode->i_flags |= S_DIRSYNC;
+       if (flags & UBIFS_CRYPT_FL)
+               inode->i_flags |= S_ENCRYPTED;
 }
 
 /*
index c13eae819cbc889ffe245dc5928278b1ccc2f4c5..5ddc89d564fd4827f3d95beb6e4ce64d8fe963c3 100644 (file)
@@ -170,6 +170,7 @@ static int create_xattr(struct ubifs_info *c, struct inode *host,
        err = ubifs_jnl_update(c, host, nm, inode, 0, 1);
        if (err)
                goto out_cancel;
+       ubifs_set_inode_flags(host);
        mutex_unlock(&host_ui->ui_mutex);
 
        ubifs_release_budget(c, &req);
index 440281f8564d8aadb3fd8d7e2286d6e9189824f3..ef0fc9ab6876d73097ccc2fcb5e3a6d7fd7ac246 100644 (file)
@@ -1854,6 +1854,7 @@ struct super_operations {
 #else
 #define S_DAX          0       /* Make all the DAX code disappear */
 #endif
+#define S_ENCRYPTED    16384   /* Encrypted file (using fs/crypto/) */
 
 /*
  * Note that nosuid etc flags are inode-specific: setting some file-system
@@ -1893,6 +1894,7 @@ static inline bool sb_rdonly(const struct super_block *sb) { return sb->s_flags
 #define IS_AUTOMOUNT(inode)    ((inode)->i_flags & S_AUTOMOUNT)
 #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_WHITEOUT(inode)     (S_ISCHR(inode->i_mode) && \
                                 (inode)->i_rdev == WHITEOUT_DEV)