From aa445f97a0ef2223df9e3346f1964a01aa8c7e4a Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Tue, 20 Oct 2020 15:26:37 -0700 Subject: [PATCH] ANDROID: fscrypt: prevent fscrypt_operations from affecting KMI 'struct fscrypt_operations' is only used by fs/crypto/ (which is always built-in) and by three filesystems (which are either built-in to GKI, in the case of ext4 and f2fs, or aren't supported by Android, in the case of ubifs). The only way a loadable module could use fscrypt_operations is if the module were a filesystem that used fs/crypto/, which isn't possible since KMI symbol list doesn't include anything in fs/crypto/. However, any change to struct fscrypt_operations changes the symbol CRC of most of the KMI functions exported by any files fs/*.c that include . This is because the definition of fscrypt_operations is visible to them, and in principle it's possible to get to fscrypt_operations from most VFS structs (e.g. inode->i_sb->s_cop), even though there's no reason to do so outside the crypto code. Work around this by putting the definition of struct fscrypt_operations behind #ifdef FSCRYPT_NEED_OPS, and only defining this in the files that actually need the definition. (It could be moved into a separate header instead, but this way keeps the diff from upstream smaller.) This will cause a one-time CRC change of all the affected KMI functions, but afterwards any changes to fscrypt_operations won't "break the KMI". Bug: 170265596 Test: re-generated the ABI, changed struct fscrypt_operations (and struct fscrypt_info as well, just in case), re-generated the ABI again, and verified it didn't change. Change-Id: Ib5dd49550aec81a64b3d6077a0aeb5747be908ff Signed-off-by: Eric Biggers Signed-off-by: Greg Kroah-Hartman --- fs/crypto/fscrypt_private.h | 1 + fs/ext4/ext4.h | 1 + fs/f2fs/f2fs.h | 1 + fs/ubifs/ubifs.h | 1 + include/linux/fscrypt.h | 6 ++++++ 5 files changed, 10 insertions(+) diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 588c61c274f5..ea28dd500d2b 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -11,6 +11,7 @@ #ifndef _FSCRYPT_PRIVATE_H #define _FSCRYPT_PRIVATE_H +#define FSCRYPT_NEED_OPS #include #include #include diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 75f97bf2e507..3ce93d7484cf 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -40,6 +40,7 @@ #include #endif +#define FSCRYPT_NEED_OPS #include #include diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 1cf0dde4799c..0ac02697ed1c 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -24,6 +24,7 @@ #include #include +#define FSCRYPT_NEED_OPS #include #include diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index bff682309fbe..5d20ba451463 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -31,6 +31,7 @@ #include #include +#define FSCRYPT_NEED_OPS #include #include "ubifs-media.h" diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 0e28e81aee8a..f226673dd447 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -53,6 +53,7 @@ struct fscrypt_name { */ #define FS_CFLG_OWN_PAGES (1U << 1) +#ifdef FSCRYPT_NEED_OPS /* * crypto operations for filesystems */ @@ -74,6 +75,7 @@ struct fscrypt_operations { void (*get_devices)(struct super_block *sb, struct request_queue **devs); }; +#endif static inline bool fscrypt_has_encryption_key(const struct inode *inode) { @@ -97,6 +99,7 @@ static inline bool fscrypt_needs_contents_encryption(const struct inode *inode) return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode); } +#ifdef FSCRYPT_NEED_OPS static inline const union fscrypt_context * fscrypt_get_dummy_context(struct super_block *sb) { @@ -104,6 +107,7 @@ fscrypt_get_dummy_context(struct super_block *sb) return NULL; return sb->s_cop->get_dummy_context(sb); } +#endif /* * When d_splice_alias() moves a directory's encrypted alias to its decrypted @@ -801,6 +805,7 @@ static inline int fscrypt_prepare_setattr(struct dentry *dentry, * -ENOKEY if the encryption key is missing, or another -errno code if a problem * occurred while setting up the encryption key. */ +#ifdef FSCRYPT_NEED_OPS static inline int fscrypt_prepare_symlink(struct inode *dir, const char *target, unsigned int len, @@ -816,6 +821,7 @@ static inline int fscrypt_prepare_symlink(struct inode *dir, return -ENAMETOOLONG; return 0; } +#endif /** * fscrypt_encrypt_symlink() - encrypt the symlink target if needed