@@ -669,6 +669,18 @@ 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 physical file or it
+ is from a memory file descriptor. It is controlled by
+ the ``IPE_PROP_ANONYMOUS_MEMORY`` config option.
+ The format of this property is::
+
+ anonymous_memory=(TRUE|FALSE)
+
Policy Examples
---------------
@@ -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
~~~~~~~~~~~~~~~~~~~~
@@ -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 physical file
+ or it is from a memory file descriptor.
+
+ if unsure, answer Y.
endmenu
config SECURITY_IPE_KUNIT_TEST
@@ -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",
};
/**
@@ -52,8 +52,8 @@ static void build_ipe_bdev_ctx(struct ipe_eval_ctx *ctx, const struct inode *con
}
#endif /* CONFIG_IPE_PROP_DM_VERITY */
-#ifdef CONFIG_IPE_PROP_FS_VERITY
-#ifdef CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG
+#if defined(CONFIG_IPE_PROP_FS_VERITY) || defined(CONFIG_IPE_PROP_ANONYMOUS_MEMORY)
+#if defined(CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG) || defined(CONFIG_IPE_PROP_ANONYMOUS_MEMORY)
static void build_ipe_inode_blob_ctx(struct ipe_eval_ctx *ctx,
const struct inode *const ino)
{
@@ -64,7 +64,7 @@ static inline void build_ipe_inode_blob_ctx(struct ipe_eval_ctx *ctx,
const struct inode *const ino)
{
}
-#endif /* CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG */
+#endif
/**
* build_ipe_inode_ctx() - Build inode fields of an evaluation context.
@@ -80,7 +80,7 @@ static void build_ipe_inode_ctx(struct ipe_eval_ctx *ctx, const struct inode *co
static void build_ipe_inode_ctx(struct ipe_eval_ctx *ctx, const struct inode *const ino)
{
}
-#endif /* CONFIG_IPE_PROP_FS_VERITY */
+#endif
/**
* ipe_build_eval_ctx() - Build an ipe evaluation context.
@@ -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 && !ctx->ipe_inode->memfd;
+}
+
+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;
}
@@ -31,11 +31,16 @@ struct ipe_bdev {
};
#endif /* CONFIG_IPE_PROP_DM_VERITY */
-#ifdef CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG
+#if defined(CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG) || defined(CONFIG_IPE_PROP_ANONYMOUS_MEMORY)
struct ipe_inode {
+#ifdef CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG
bool fs_verity_signed;
-};
#endif /* CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG */
+#ifdef CONFIG_IPE_PROP_ANONYMOUS_MEMORY
+ bool memfd;
+#endif /* CONFIG_IPE_PROP_ANONYMOUS_MEMORY */
+};
+#endif
struct ipe_eval_ctx {
enum ipe_op_type op;
@@ -49,9 +54,9 @@ struct ipe_eval_ctx {
#ifdef CONFIG_IPE_PROP_FS_VERITY
const struct inode *ino;
#endif /* CONFIG_IPE_PROP_FS_VERITY */
-#ifdef CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG
+#if defined(CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG) || defined(CONFIG_IPE_PROP_ANONYMOUS_MEMORY)
const struct ipe_inode *ipe_inode;
-#endif /* CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG */
+#endif
};
enum ipe_match {
@@ -312,3 +312,15 @@ int ipe_inode_setintegrity(const struct inode *inode,
return -EINVAL;
}
#endif /* CONFIG_CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG */
+
+#ifdef CONFIG_IPE_PROP_ANONYMOUS_MEMORY
+/**
+ * ipe_memfd_created() - Mark the current file as a memfd.
+ * @file: Supplies a pointer to the file structure being created.
+ */
+void ipe_memfd_created(struct file *file)
+{
+ ipe_inode(file->f_inode)->memfd = true;
+}
+#endif /* CONFIG_IPE_PROP_ANONYMOUS_MEMORY */
+
@@ -49,4 +49,8 @@ int ipe_inode_setintegrity(const struct inode *inode, enum lsm_integrity_type ty
const void *value, size_t size);
#endif /* CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG */
+#ifdef CONFIG_IPE_PROP_ANONYMOUS_MEMORY
+void ipe_memfd_created(struct file *file);
+#endif /* CONFIG_IPE_PROP_ANONYMOUS_MEMORY */
+
#endif /* _IPE_HOOKS_H */
@@ -16,9 +16,9 @@ static struct lsm_blob_sizes ipe_blobs __ro_after_init = {
#ifdef CONFIG_IPE_PROP_DM_VERITY
.lbs_bdev = sizeof(struct ipe_bdev),
#endif /* CONFIG_IPE_PROP_DM_VERITY */
-#ifdef CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG
+#if defined(CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG) || defined(CONFIG_IPE_PROP_ANONYMOUS_MEMORY)
.lbs_inode = sizeof(struct ipe_inode),
-#endif /* CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG */
+#endif
};
static const struct lsm_id ipe_lsmid = {
@@ -59,6 +59,9 @@ static struct security_hook_list ipe_hooks[] __ro_after_init = {
#ifdef CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG
LSM_HOOK_INIT(inode_setintegrity, ipe_inode_setintegrity),
#endif /* CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG */
+#ifdef CONFIG_IPE_PROP_ANONYMOUS_MEMORY
+ LSM_HOOK_INIT(memfd_created, ipe_memfd_created),
+#endif /* CONFIG_IPE_PROP_ANONYMOUS_MEMORY */
};
/**
@@ -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
};
@@ -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: