[PATCH v1] ipe: add 'anonymous_memory' property for policy decisions

From: Fan Wu
Date: Thu Oct 10 2024 - 13:43:48 EST


Currently, all existing IPE properties evaluate to FALSE for
operations triggered by anonymous memory regions. As a result,
IPE falls back to the policy's default action for such operations.

In policies where the default action is DENY, this behavior blocks
all anonymous memory operations, rendering binaries that rely on
anonymous memory unusable.

This commit introduces a new IPE property, 'anonymous_memory',
which evaluates to TRUE when an operation is triggered by an
anonymous memory region. This allows administrators to explicitly
allow or deny operations involving anonymous memory.

Signed-off-by: Fan Wu <wufan@xxxxxxxxxxxxxxxxxxx>
---
Documentation/admin-guide/LSM/ipe.rst | 11 +++++++++++
Documentation/security/ipe.rst | 9 +++++----
security/ipe/Kconfig | 10 ++++++++++
security/ipe/audit.c | 2 ++
security/ipe/eval.c | 26 ++++++++++++++++++++++++++
security/ipe/policy.h | 2 ++
security/ipe/policy_parser.c | 4 ++++
7 files changed, 60 insertions(+), 4 deletions(-)

diff --git a/Documentation/admin-guide/LSM/ipe.rst b/Documentation/admin-guide/LSM/ipe.rst
index f93a467db628..356f0dd6e4c3 100644
--- a/Documentation/admin-guide/LSM/ipe.rst
+++ b/Documentation/admin-guide/LSM/ipe.rst
@@ -669,6 +669,17 @@ fsverity_signature

fsverity_signature=(TRUE|FALSE)

+anonymous_memory
+~~~~~~~~~~~~~~~~
+
+ This property can be used to allow or deny operations triggered by
+ anonymous memory. It evaluates to TRUE when a memory region
+ in the evaluation context is not backed by a file. It is controlled by
+ the ``IPE_PROP_ANONYMOUS_MEMORY`` config option.
+ The format of this property is::
+
+ anonymous_memory=(TRUE|FALSE)
+
Policy Examples
---------------

diff --git a/Documentation/security/ipe.rst b/Documentation/security/ipe.rst
index 4a7d953abcdc..1606484241cb 100644
--- a/Documentation/security/ipe.rst
+++ b/Documentation/security/ipe.rst
@@ -385,15 +385,16 @@ Anonymous Memory
Anonymous memory isn't treated any differently from any other access in IPE.
When anonymous memory is mapped with ``+X``, it still comes into the ``file_mmap``
or ``file_mprotect`` hook, but with a ``NULL`` file object. This is submitted to
-the evaluation, like any other file. However, all current trust properties will
-evaluate to false, as they are all file-based and the operation is not
-associated with a file.
+the evaluation, like any other file. However, except the ``anonymous_memory`` property,
+all current trust properties will evaluate to false, as they are all file-based and
+the operation is not associated with a file.

.. WARNING::

This also occurs with the ``kernel_load_data`` hook, when the kernel is
loading data from a userspace buffer that is not backed by a file. In this
- scenario all current trust properties will also evaluate to false.
+ scenario, all current trust properties except ``anonymous_memory`` will also evaluate
+ to false.

Securityfs Interface
~~~~~~~~~~~~~~~~~~~~
diff --git a/security/ipe/Kconfig b/security/ipe/Kconfig
index ee6beca5494a..839a554f4e17 100644
--- a/security/ipe/Kconfig
+++ b/security/ipe/Kconfig
@@ -94,6 +94,16 @@ config IPE_PROP_FS_VERITY_BUILTIN_SIG

if unsure, answer Y.

+config IPE_PROP_ANONYMOUS_MEMORY
+ bool "Enable support for anonymous memory"
+ default y
+ help
+ This option enables the 'anonymous_memory' property within IPE
+ policies. The property evaluates to TRUE when a memory region
+ in the evaluation context is not backed by a file (i.e., it is
+ anonymous memory).
+
+ if unsure, answer Y.
endmenu

config SECURITY_IPE_KUNIT_TEST
diff --git a/security/ipe/audit.c b/security/ipe/audit.c
index f05f0caa4850..ab5217655910 100644
--- a/security/ipe/audit.c
+++ b/security/ipe/audit.c
@@ -59,6 +59,8 @@ static const char *const audit_prop_names[__IPE_PROP_MAX] = {
"fsverity_digest=",
"fsverity_signature=FALSE",
"fsverity_signature=TRUE",
+ "anonymous_memory=FALSE",
+ "anonymous_memory=TRUE",
};

/**
diff --git a/security/ipe/eval.c b/security/ipe/eval.c
index 21439c5be336..e2ab7a8d7d8c 100644
--- a/security/ipe/eval.c
+++ b/security/ipe/eval.c
@@ -265,6 +265,28 @@ static bool evaluate_fsv_sig_true(const struct ipe_eval_ctx *const ctx)
}
#endif /* CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG */

+#ifdef CONFIG_IPE_PROP_ANONYMOUS_MEMORY
+static bool evaluate_anonymous_memory_false(const struct ipe_eval_ctx *const ctx)
+{
+ return !ctx->file;
+}
+
+static bool evaluate_anonymous_memory_true(const struct ipe_eval_ctx *const ctx)
+{
+ return !evaluate_anonymous_memory_false(ctx);
+}
+#else
+static bool evaluate_anonymous_memory_false(const struct ipe_eval_ctx *const ctx)
+{
+ return false;
+}
+
+static bool evaluate_anonymous_memory_true(const struct ipe_eval_ctx *const ctx)
+{
+ return false;
+}
+#endif /* CONFIG_IPE_PROP_ANONYMOUS_MEMORY */
+
/**
* evaluate_property() - Analyze @ctx against a rule property.
* @ctx: Supplies a pointer to the context to be evaluated.
@@ -297,6 +319,10 @@ static bool evaluate_property(const struct ipe_eval_ctx *const ctx,
return evaluate_fsv_sig_false(ctx);
case IPE_PROP_FSV_SIG_TRUE:
return evaluate_fsv_sig_true(ctx);
+ case IPE_PROP_ANON_MEM_FALSE:
+ return evaluate_anonymous_memory_false(ctx);
+ case IPE_PROP_ANON_MEM_TRUE:
+ return evaluate_anonymous_memory_true(ctx);
default:
return false;
}
diff --git a/security/ipe/policy.h b/security/ipe/policy.h
index 5bfbdbddeef8..0becc2d2bd33 100644
--- a/security/ipe/policy.h
+++ b/security/ipe/policy.h
@@ -39,6 +39,8 @@ enum ipe_prop_type {
IPE_PROP_FSV_DIGEST,
IPE_PROP_FSV_SIG_FALSE,
IPE_PROP_FSV_SIG_TRUE,
+ IPE_PROP_ANON_MEM_FALSE,
+ IPE_PROP_ANON_MEM_TRUE,
__IPE_PROP_MAX
};

diff --git a/security/ipe/policy_parser.c b/security/ipe/policy_parser.c
index 7f27e39931d6..5c83095e7c37 100644
--- a/security/ipe/policy_parser.c
+++ b/security/ipe/policy_parser.c
@@ -281,6 +281,8 @@ static const match_table_t property_tokens = {
{IPE_PROP_FSV_DIGEST, "fsverity_digest=%s"},
{IPE_PROP_FSV_SIG_FALSE, "fsverity_signature=FALSE"},
{IPE_PROP_FSV_SIG_TRUE, "fsverity_signature=TRUE"},
+ {IPE_PROP_ANON_MEM_FALSE, "anonymous_memory=FALSE"},
+ {IPE_PROP_ANON_MEM_TRUE, "anonymous_memory=TRUE"},
{IPE_PROP_INVALID, NULL}
};

@@ -331,6 +333,8 @@ static int parse_property(char *t, struct ipe_rule *r)
case IPE_PROP_DMV_SIG_TRUE:
case IPE_PROP_FSV_SIG_FALSE:
case IPE_PROP_FSV_SIG_TRUE:
+ case IPE_PROP_ANON_MEM_FALSE:
+ case IPE_PROP_ANON_MEM_TRUE:
p->type = token;
break;
default:
--
2.46.2