All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Dr. Greg" <greg@enjellic.com>
To: linux-security-module@vger.kernel.org
Subject: [PATCH 09/14] Add namespace implementation.
Date: Fri,  3 Feb 2023 23:09:49 -0600	[thread overview]
Message-ID: <20230204050954.11583-10-greg@enjellic.com> (raw)
In-Reply-To: <20230204050954.11583-1-greg@enjellic.com>

The TSEM LSM has its own 'namespace' implementation for security
modeling domains that is independent of other resource namespaces
but which is designed to act in much the same manner.

The sysfs control plane is used to signal that a process should
leave its current modeling domain/namespace and institute a new
domain.  Additional processes that derive from this process
inherit the modeling domain.

Each modeling domain has a unique numeric identifier that is
implemented as an incremented unsigned 64 bit value in order to
preclude overflow.  The id value of 0 is reserved for the root
modeling domain.

Each modeling domain is designated as either internally or
externally modeled.  An internally modeled domain has its
security model implemented by a Trusted Modeling Agent (TMA)
implementation that is run in the context of the kernel.

Externally modeled domains have a description of the security
event exported to an trust orchestrator running in userspace.
That trust orchestrator has an associated Trusted Modeling Agent
run in a context that implements the root of trust for the
security model.

A process that exports a security event description is scheduled
away into an interruptible sleep state.  The trust orchestrator
that created the external modeling domain is responsible for
using the TSEM control plane to wake the process up and set the
trust status of the process to be trusted or untrusted.  Only
process that carries the CAP_TRUST capability can wake up a
process and set its trust status.

An init function is surfaced from this file that is called by the
TSEM initialization function.  This function is responsible for
creating a workqueue that will handle asynchronous release of
resources that were allocated for a modeling domain, including
the release of the pseudo-file that was created for exporting
domain events.

Only processes that carry the CAP_TRUST capability are allowed to
create subordinate modeling domains.  The modeling domains are
independent entities whose trust state is designed to be managed
exclusively by its associated TMA.

Signed-off-by: Greg Wettstein <greg@enjellic.com>
---
 security/tsem/namespace.c | 226 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 226 insertions(+)
 create mode 100644 security/tsem/namespace.c

diff --git a/security/tsem/namespace.c b/security/tsem/namespace.c
new file mode 100644
index 000000000000..632d5d4d967c
--- /dev/null
+++ b/security/tsem/namespace.c
@@ -0,0 +1,226 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * Copyright (C) 2022 Enjellic Systems Development, LLC
+ * Author: Dr. Greg Wettstein <greg@enjellic.com>
+ *
+ * This file implements TSEM namespaces.
+ */
+
+#include "tsem.h"
+
+static u64 context_id;
+
+static struct workqueue_struct *release_wq;
+
+struct lsm_blob_sizes tsem_blob_sizes __lsm_ro_after_init = {
+	.lbs_task = sizeof(struct tsem_task),
+	.lbs_inode = sizeof(struct tsem_inode)
+};
+
+enum tsem_action_type tsem_root_actions[TSEM_EVENT_CNT] = {
+	TSEM_ACTION_EPERM	/* Undefined. */
+};
+
+struct tsem_model root_model = {
+	.point_mutex = __MUTEX_INITIALIZER(root_model.point_mutex),
+	.point_list = LIST_HEAD_INIT(root_model.point_list),
+	.state_list = LIST_HEAD_INIT(root_model.state_list),
+
+	.trajectory_mutex = __MUTEX_INITIALIZER(root_model.trajectory_mutex),
+	.trajectory_list = LIST_HEAD_INIT(root_model.trajectory_list),
+
+	.max_forensics_count = 100,
+	.forensics_mutex = __MUTEX_INITIALIZER(root_model.forensics_mutex),
+	.forensics_list = LIST_HEAD_INIT(root_model.forensics_list),
+
+	.pseudonym_mutex = __MUTEX_INITIALIZER(root_model.pseudonym_mutex),
+	.pseudonym_list = LIST_HEAD_INIT(root_model.pseudonym_list)
+};
+
+struct tsem_TMA_context root_TMA_context = {
+	.kref = KREF_INIT(2),
+	.id = 0,
+	.external = false,
+	.model = &root_model
+};
+
+static struct tsem_external *allocate_external(void)
+{
+	int retn = -ENOMEM;
+	struct tsem_external *external;
+	char bufr[20 + 1];
+
+	external = kzalloc(sizeof(struct tsem_external), GFP_KERNEL);
+	if (!external)
+		return NULL;
+
+	mutex_init(&external->measurement_mutex);
+	INIT_LIST_HEAD(&external->measurement_list);
+
+	init_waitqueue_head(&external->wq);
+
+	scnprintf(bufr, sizeof(bufr), "%llu", context_id + 1);
+	external->dentry = tsem_fs_create_external(bufr);
+	if (IS_ERR(external->dentry)) {
+		retn = PTR_ERR(external->dentry);
+		external->dentry = NULL;
+	} else
+		retn = 0;
+
+	if (retn) {
+		kfree(external);
+		external = NULL;
+	}
+
+	return external;
+}
+
+/**
+ * tsem_ns_free() - Releases the namespace model infrastructure.
+ * @kref: A pointer to the reference counting structure for the namespace.
+ *
+ * This function is called when the last reference to a kernel
+ * based TMA model structure is released.
+ */
+void tsem_ns_free(struct kref *kref)
+{
+	struct tsem_TMA_context *ctx;
+
+	ctx = container_of(kref, struct tsem_TMA_context, kref);
+
+	if (ctx->external) {
+		tsem_fs_remove_external(ctx->external->dentry);
+		kfree(ctx->external);
+	} else
+		tsem_model_free(ctx);
+
+	kfree(ctx);
+}
+
+static void wq_put(struct work_struct *work)
+{
+	struct tsem_TMA_work *tsem_work;
+	struct tsem_TMA_context *ctx;
+
+	tsem_work = container_of(work, struct tsem_TMA_work, work);
+	ctx = tsem_work->ctx;
+	kref_put(&ctx->kref, tsem_ns_free);
+}
+
+/**
+ * tsem_ns_get() - Obtain a reference on a TSEM TMA namespace.
+ * @ctx: A pointer to the TMA modeling context for which a reference is
+ *	 to be released.
+ *
+ * This function is called to release a reference to a TMA modeling
+ * domain.
+ */
+void tsem_ns_put(struct tsem_TMA_context *ctx)
+{
+	if (kref_read(&ctx->kref) > 1) {
+		kref_put(&ctx->kref, tsem_ns_free);
+		return;
+	}
+
+	INIT_WORK(&ctx->work.work, wq_put);
+	ctx->work.ctx = ctx;
+	if (!queue_work(release_wq, &ctx->work.work))
+		WARN_ON_ONCE(1);
+}
+
+/**
+ * tsem_ns_put() - Obtain a reference on a TSEM TMA namespace.
+ * @ctx: A pointer to the TMA modeling context for which a reference is
+ *	 to be acquired.
+ *
+ * This function is called on each invocation of the tsem_task_alloc
+ * event to obtain a reference against the current modeling domain.
+ */
+void tsem_ns_get(struct tsem_TMA_context *ctx)
+{
+	kref_get(&ctx->kref);
+}
+
+/**
+ * tsem_ns_namespace() - Create a TSEM modeling namespace.
+ * @event: The numeric identifer of the control message that is to
+ *	   be processed.
+ *
+ * This function is used to create either an internally or externally
+ * modeled TSEM namespace.  The boolean argument to this function
+ * selects the type of namespace that is being created.  Specification
+ * of an internal namespace causes the ->model pointer to be initialized
+ * with a tsem_model structure.
+ *
+ * Return: This function returns 0 if the namespace was created and
+ *	   a negative error value on error.
+ */
+int tsem_ns_create(enum tsem_control_type event)
+{
+	int retn = -ENOMEM;
+	struct tsem_task *tsk = tsem_task(current);
+	struct tsem_TMA_context *new_ctx;
+	struct tsem_model *model = NULL;
+
+	new_ctx = kzalloc(sizeof(struct tsem_TMA_context), GFP_KERNEL);
+	if (!new_ctx)
+		goto done;
+
+	if (event == TSEM_CONTROL_INTERNAL) {
+		model = tsem_model_allocate();
+		if (!model)
+			goto done;
+		new_ctx->model = model;
+	}
+	if (event == TSEM_CONTROL_EXTERNAL) {
+		new_ctx->external = allocate_external();
+		if (!new_ctx->external)
+			goto done;
+	}
+
+	kref_init(&new_ctx->kref);
+	new_ctx->id = ++context_id;
+	memcpy(new_ctx->actions, tsk->context->actions,
+	       sizeof(new_ctx->actions));
+	retn = 0;
+
+ done:
+	if (retn) {
+		kfree(new_ctx->external);
+		kfree(new_ctx);
+		kfree(model);
+	} else {
+		tsk->context = new_ctx;
+		if (event == TSEM_CONTROL_EXTERNAL)
+			retn = tsem_export_aggregate();
+		else
+			retn = tsem_model_add_aggregate();
+	}
+
+	return retn;
+}
+
+/**
+ * tsem_ns_init() - Initialize TSEM namespace processing.
+ *
+ * This function is called as part of the TSEM LSM initialization
+ * process.  It initializes the workqueue that will be used to
+ * conduct the asynchronous release of modeling contexts.  The
+ * deferral of the namespace clean is needed in order to address
+ * the fact that the /sys/fs/tsem pseudo-files cannot be done
+ * in atomic context.
+ *
+ * Return: If the initialization succeeds a return code of 0 is returned.
+ *	   A negative return value is returned on failure.
+ */
+int __init tsem_ns_init(void)
+{
+	int retn = 0;
+
+	release_wq = create_workqueue("tsem_ns_release");
+	if (IS_ERR(release_wq))
+		retn = PTR_ERR(release_wq);
+
+	return retn;
+}
-- 
2.39.1


  parent reply	other threads:[~2023-02-04  5:32 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-04  5:09 [PATCH 00/14] Implement Trusted Security Event Modeling Dr. Greg
2023-02-04  5:09 ` [PATCH 01/14] Update MAINTAINERS file Dr. Greg
2023-02-04  5:09 ` [PATCH 02/14] Add TSEM specific documentation Dr. Greg
2023-02-09 11:47   ` Greg KH
2023-02-09 23:47     ` Dr. Greg
2023-02-13  4:33   ` Paul Moore
2023-02-14 11:58     ` Dr. Greg
2023-02-14 12:18       ` Roberto Sassu
2023-02-15 16:26         ` Dr. Greg
2023-03-03  4:15       ` Paul Moore
2023-03-13 22:52         ` Dr. Greg
2023-03-22 23:45           ` Paul Moore
2023-03-30  3:34             ` Dr. Greg
2023-04-05 20:45               ` Paul Moore
2023-04-07 14:10                 ` Dr. Greg
2023-02-04  5:09 ` [PATCH 03/14] Add magic number for tsemfs Dr. Greg
2023-02-04  5:09 ` [PATCH 04/14] Implement CAP_TRUST capability Dr. Greg
2023-02-06 17:28   ` Serge Hallyn (shallyn)
2023-02-11  0:32     ` Dr. Greg
     [not found]   ` <a12483d1-9d57-d429-789b-9e47ff575546@schaufler-ca.com>
2023-02-13 11:43     ` Dr. Greg
2023-02-13 18:02       ` Casey Schaufler
2023-02-16 21:47         ` Dr. Greg
2023-02-04  5:09 ` [PATCH 05/14] Add TSEM master header file Dr. Greg
     [not found]   ` <ecb168ef-b82d-fd61-f2f8-54a4ef8c3b48@schaufler-ca.com>
2023-02-06  0:10     ` Dr. Greg
2023-02-04  5:09 ` [PATCH 06/14] Add primary TSEM implementation file Dr. Greg
2023-02-04  5:09 ` [PATCH 07/14] Add root domain trust implementation Dr. Greg
2023-02-04  5:09 ` [PATCH 08/14] Implement TSEM control plane Dr. Greg
2023-02-09 11:30   ` Greg KH
2023-02-11  0:18     ` Dr. Greg
2023-02-11 10:59       ` Greg KH
2023-02-12  6:54         ` Dr. Greg
2023-02-16  6:53           ` Greg KH
2023-02-18 18:03             ` Dr. Greg
2023-02-04  5:09 ` Dr. Greg [this message]
2023-02-04  5:09 ` [PATCH 10/14] Add security event description export facility Dr. Greg
2023-02-04  5:09 ` [PATCH 11/14] Add event description implementation Dr. Greg
2023-02-04  5:09 ` [PATCH 12/14] Implement security event mapping Dr. Greg
2023-02-04  5:09 ` [PATCH 13/14] Implement an internal Trusted Modeling Agent Dr. Greg
2023-02-04  5:09 ` [PATCH 14/14] Activate the configuration and build of the TSEM LSM Dr. Greg
2023-02-08 22:15   ` Casey Schaufler
2023-02-09 22:21     ` Dr. Greg
     [not found] ` <20230204115917.1015-1-hdanton@sina.com>
2023-02-23 18:41   ` [PATCH 09/14] Add namespace implementation Dr. Greg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230204050954.11583-10-greg@enjellic.com \
    --to=greg@enjellic.com \
    --cc=linux-security-module@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.