[RFC 2/2] evm: Add kernel parameter to disable EVM

Song Liu
2024-12-17T20:25:53Z

This patch provides kernel parameter 'evm=' that disables EVM.
This will reduce memory consumption by the EVM when it is not needed.
Specifically, this saves one evm_iint_cache per inode in the system.

Originally-by: Dmitry Kasatkin <dmitry.kasatkin@gmail.com>
Signed-off-by: Song Liu <song@kernel.org>
---
security/integrity/evm/evm.h | 6 ++++++
security/integrity/evm/evm_main.c | 22 ++++++++++++++--------
security/integrity/evm/evm_secfs.c | 3 ++-
3 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h
index 51aba5a54275..64428c35e4cf 100644
--- a/security/integrity/evm/evm.h
+++ b/security/integrity/evm/evm.h
@@ -17,6 +17,10 @@

#include "../integrity.h"

+#define EVM_MODE_OFF 0
+#define EVM_MODE_ON 1
+#define EVM_MODE_FIX 2
+
#define EVM_INIT_HMAC 0x0001
#define EVM_INIT_X509 0x0002
#define EVM_ALLOW_METADATA_WRITES 0x0004
@@ -26,6 +30,8 @@
#define EVM_INIT_MASK (EVM_INIT_HMAC | EVM_INIT_X509 | EVM_SETUP_COMPLETE | \
EVM_ALLOW_METADATA_WRITES)

+extern int evm_mode;
+
struct xattr_list {
struct list_head list;
char *name;
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index 377e57e9084f..738c38f8190d 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -72,17 +72,19 @@ static struct xattr_list evm_config_default_xattrnames[] = {

LIST_HEAD(evm_config_xattrnames);

-static int evm_fixmode __ro_after_init;
-static int __init evm_set_fixmode(char *str)
+int evm_mode __ro_after_init = EVM_MODE_ON;
+
+static int __init evm_setup(char *str)
{
- if (strncmp(str, "fix", 3) == 0)
- evm_fixmode = 1;
+ if (strncmp(str, "off", 3) == 0)
+ evm_mode = EVM_MODE_OFF;
+ else if (strncmp(str, "fix", 3) == 0)
+ evm_mode = EVM_MODE_FIX;
else
pr_err("invalid \"%s\" mode", str);
-
- return 1;
+ return 0;
}
-__setup("evm=", evm_set_fixmode);
+__setup("evm=", evm_setup);

static void __init evm_init_config(void)
{
@@ -441,7 +443,7 @@ static enum integrity_status evm_verify_current_integrity(struct dentry *dentry)
{
struct inode *inode = d_backing_inode(dentry);

- if (!evm_key_loaded() || !S_ISREG(inode->i_mode) || evm_fixmode)
+ if (!evm_key_loaded() || !S_ISREG(inode->i_mode) || evm_mode == EVM_MODE_FIX)
return INTEGRITY_PASS;
return evm_verify_hmac(dentry, NULL, NULL, 0);
}
@@ -1117,6 +1119,9 @@ static int __init init_evm(void)
int error;
struct list_head *pos, *q;

+ if (evm_mode == EVM_MODE_OFF)
+ return 0;
+
evm_init_config();

error = integrity_init_keyring(INTEGRITY_KEYRING_EVM);
@@ -1178,6 +1183,7 @@ DEFINE_LSM(evm) = {
.name = "evm",
.init = init_evm_lsm,
.order = LSM_ORDER_LAST,
+ .enabled = &evm_mode,
.blobs = &evm_blob_sizes,
};

diff --git a/security/integrity/evm/evm_secfs.c b/security/integrity/evm/evm_secfs.c
index 9b907c2fee60..65f896cb838e 100644
--- a/security/integrity/evm/evm_secfs.c
+++ b/security/integrity/evm/evm_secfs.c
@@ -69,7 +69,8 @@ static ssize_t evm_write_key(struct file *file, const char __user *buf,
unsigned int i;
int ret;

- if (!capable(CAP_SYS_ADMIN) || (evm_initialized & EVM_SETUP_COMPLETE))
+ if (!capable(CAP_SYS_ADMIN) || (evm_initialized & EVM_SETUP_COMPLETE) ||
+ evm_mode == EVM_MODE_OFF)
return -EPERM;

ret = kstrtouint_from_user(buf, count, 0, &i);
--
2.43.5