From: Greg Wettstein <greg@enjellic.com>
To: linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: jmorris@namei.org
Subject: [PATCH v4 13/14] Implement infrastructure for loadable security models.
Date: Mon, 26 Aug 2024 05:37:27 -0500 [thread overview]
Message-ID: <20240826103728.3378-14-greg@enjellic.com> (raw)
In-Reply-To: <20240826103728.3378-1-greg@enjellic.com>
The default deterministic security model can be replaced through
the use of models that are implemented with kernel loadable
modules. Kernel loadable modules can be used to replace the
following components of the TSEM modeling infrastructure:
- event bypasses
- event initialization
- event mapping
An alternate security model is specified for a security modeling
namespace by using the following key/value pair as an argument to
the creation of the security modeling namespace:
model=MODEL_NAME
Where MODEL_NAME is the name of the model compiled into the
kernel loadable model that implements the model.
Befor any model can be used it must be registered through the
infrastructure supplied by this commit, namely the nsmgr.c file.
Addition or removal of modules can be locked, either through the
TSEM control plame or by the 'tsem_locked' kernel command-line
parameter. Locking of the registation process is an irreversible
process, once locked the registration/removal process will be
locked until the system is rebooted.
---
security/tsem/nsmgr.c | 255 ++++++++++++++++++++++++++++++++++++++++++
security/tsem/nsmgr.h | 48 ++++++++
2 files changed, 303 insertions(+)
create mode 100644 security/tsem/nsmgr.c
create mode 100644 security/tsem/nsmgr.h
diff --git a/security/tsem/nsmgr.c b/security/tsem/nsmgr.c
new file mode 100644
index 000000000000..0b34c18feb01
--- /dev/null
+++ b/security/tsem/nsmgr.c
@@ -0,0 +1,255 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * Copyright (C) 2024 Enjellic Systems Development, LLC
+ * Author: Dr. Greg Wettstein <greg@enjellic.com>
+ *
+ * This file contains infrastructure for managing the security models
+ * for TSEM that are implemented by kernel loadable modules. Any model
+ * provided by a kernel loadable module must be registered before it
+ * can be specified for a security modeling namespace.
+ *
+ * The registration of additional models, or the removal of existing
+ * models, can be prevented by 'locking' the registration process.
+ * This locking can be implemented either through the TSEM control
+ * plane or by specifying the 'tsem_locked' kernel command-line
+ * parameter.
+ */
+
+#include "tsem.h"
+#include "nsmgr.h"
+
+static bool locked;
+static bool setup_locked __ro_after_init;
+
+struct model {
+ struct list_head list;
+ const struct tsem_context_ops *ops;
+ struct module *module;
+};
+
+DEFINE_MUTEX(model_list_mutex);
+LIST_HEAD(model_list);
+
+
+static struct model *find_model(const char *name)
+{
+ struct model *found = NULL, *entry = NULL;
+
+ list_for_each_entry(entry, &model_list, list) {
+ if (!strcmp(entry->ops->name, name)) {
+ found = entry;
+ break;
+ }
+ }
+ return found;
+}
+
+/**
+ * tsem_nsmgr_put() - Release a reference to a TSEM security model.
+ *
+ * @ops: A pointer to the tsem_context_ops structure that defines
+ * this model.
+ *
+ * This function is the counter part to tsem_nsmgr_get() function.
+ * A check is made to determine if a module is supplying this model and
+ * if so the reference that was taken to the module when the security
+ * namespace is created is released.
+ */
+void tsem_nsmgr_put(const struct tsem_context_ops *ops)
+{
+ struct model *model;
+
+ if (!strcmp(tsem_model0_ops.name, ops->name))
+ return;
+
+ mutex_lock(&model_list_mutex);
+ model = find_model(ops->name);
+ if (!model) {
+ pr_warn("tsem: Attempt to put an unknown model.\n");
+ goto done;
+ }
+ if (model->module)
+ module_put(model->module);
+
+ done:
+ mutex_unlock(&model_list_mutex);
+}
+
+/**
+ * tsem_nsmgr_get() - Obtain a reference to a TSEM security model.
+ *
+ * @name: A null terminated character buffer containing the name of
+ * the security model to obtain a reference for.
+ *
+ * This function is used to determine whether or not TSEM has access
+ * to a security model named by the called. Upon success of locating
+ * the named security model a tsem_context_ops structure is returned
+ * that implements the model. In addition a reference is taken to
+ * the module in order to prevent its release while a security modeling
+ * namespace is using the model.
+ *
+ * Return: If the named security model is not available a NULL pointer
+ * is returned. If the model is available a pointer to the
+ * tsem_context_ops structure that implements the model is
+ * returned.
+ */
+const struct tsem_context_ops *tsem_nsmgr_get(const char *name)
+{
+ struct model *model;
+ const struct tsem_context_ops *retn = NULL;
+
+ mutex_lock(&model_list_mutex);
+ model = find_model(name);
+ mutex_unlock(&model_list_mutex);
+
+ if (!model) {
+ if (request_module("%s", name))
+ return NULL;
+
+ mutex_lock(&model_list_mutex);
+ model = find_model(name);
+ mutex_unlock(&model_list_mutex);
+ if (!model)
+ return NULL;
+ }
+
+ if (model && try_module_get(model->module))
+ retn = model->ops;
+ return retn;
+}
+
+/**
+ * tsem_nsmgr_lock() - Lock the TSEM loadable module infrastructure.
+ *
+ * @by_setup: This boolean value is used to signal that the request to
+ * lock the model state is being done by the system setup.
+ *
+ * This function disables the registration of additional loadable
+ * modules for model implementation. It also raises the reference count
+ * for each modules that is loaded to prevent the current modules from
+ * being unloaded.
+ *
+ * Return: This function returns 0 if the modeling infrastructure was
+ * locked or a negative value if locking fails.
+ */
+int tsem_nsmgr_lock(const bool by_setup)
+{
+ struct model *entry = NULL;
+
+ if (by_setup) {
+ setup_locked = true;
+ return 0;
+ }
+
+ if (setup_locked)
+ return -EINVAL;
+ if (!capable(CAP_MAC_ADMIN))
+ return -EPERM;
+ if (tsem_context(current)->id)
+ return -EINVAL;
+ if (locked)
+ return -EINVAL;
+ locked = true;
+
+ mutex_lock(&model_list_mutex);
+ list_for_each_entry(entry, &model_list, list) {
+ __module_get(entry->module);
+ }
+ mutex_unlock(&model_list_mutex);
+
+ pr_info("tsem: Model state is now locked.\n");
+ return 0;
+}
+
+/**
+ * tsem_nsmgr_register() - Register a TSEM security namespace model.
+ * @ops: A pointer to a tsem_context_ops structure that describes
+ * the model that will be implemented.
+ * @module: A pointer to the module implementing the security namespace
+ * model.
+ *
+ * This function is used by loadable modules to register a security
+ * model that is to be available for use by security modeling namespaces.
+ *
+ * Return: This function returns 0 if the model was successfully registered
+ * or a negative error value if registration failed.
+ */
+int tsem_nsmgr_register(const struct tsem_context_ops *ops,
+ struct module *module)
+{
+ int retn = 0;
+ struct model *model = NULL;
+
+ if (setup_locked || locked) {
+ pr_warn("tsem: Attempt to register model in locked state.\n");
+ return -EINVAL;
+ }
+ if (!capable(CAP_MAC_ADMIN))
+ return -EPERM;
+ if (!strcmp(tsem_model0_ops.name, ops->name))
+ return -EINVAL;
+
+ mutex_lock(&model_list_mutex);
+ if (find_model(ops->name)) {
+ pr_warn("tsem: Attempt to insert identical model: %s\n",
+ ops->name);
+ retn = -EEXIST;
+ goto done;
+ }
+
+ model = kzalloc(sizeof(*model), GFP_KERNEL);
+ if (!model) {
+ retn = -ENOMEM;
+ goto done;
+ }
+
+ model->ops = ops;
+ model->module = module;
+ list_add_tail(&model->list, &model_list);
+ pr_info("tsem: Registered model: '%s'\n", ops->name);
+
+ done:
+ mutex_unlock(&model_list_mutex);
+ return retn;
+}
+EXPORT_SYMBOL_GPL(tsem_nsmgr_register);
+
+/**
+ * tsem_nsmgr_release() - Release a TSEM security namespace model.
+ * @name: A null terminated character buffer containing the name
+ * of the model being implemented.
+ *
+ * This function is used to release the use of security modeling
+ * namespace model.
+ *
+ * Return: This function returns 0 if the model was successfully released
+ * or a negative error value if release failed.
+ */
+int tsem_nsmgr_release(const struct tsem_context_ops *ops)
+{
+ int retn = 0;
+ struct model *model;
+
+ if (setup_locked || locked) {
+ pr_warn("tsem: Attempt to release model in locked state.\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&model_list_mutex);
+
+ model = find_model(ops->name);
+ if (!model) {
+ pr_warn("tsem: Model '%s' not found for release.\n",
+ ops->name);
+ retn = -EINVAL;
+ goto done;
+ }
+ list_del(&model->list);
+
+ done:
+ mutex_unlock(&model_list_mutex);
+ pr_info("tsem: Released model: '%s'\n", ops->name);
+ return retn;
+}
+EXPORT_SYMBOL_GPL(tsem_nsmgr_release);
diff --git a/security/tsem/nsmgr.h b/security/tsem/nsmgr.h
new file mode 100644
index 000000000000..cb4d30a4962d
--- /dev/null
+++ b/security/tsem/nsmgr.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * Copyright (C) 2024 Enjellic Systems Development, LLC
+ * Author: Dr. Greg Wettstein <greg@enjellic.com>
+ *
+ * This header file contains declarations for globally visible
+ * functionality surrounding the registration of security models
+ * provided in the form of loadable modules.
+ *
+ * This header file detects whether or not kernel modules are enabled
+ * and if not provides a stub function that causes an attempt to
+ * specify an alternate security model to fail.
+ */
+
+#ifdef CONFIG_MODULES
+extern void tsem_nsmgr_put(const struct tsem_context_ops *ops);
+extern const struct tsem_context_ops *tsem_nsmgr_get(const char *name);
+extern int tsem_nsmgr_lock(const bool);
+extern int tsem_nsmgr_register(const struct tsem_context_ops *ops,
+ struct module *module);
+extern int tsem_nsmgr_release(const struct tsem_context_ops *ops);
+#else
+static inline void tsem_nsmgr_put(const struct tsem_context_ops *ops)
+{
+}
+
+static inline int tsem_nsmgr_lock(const bool by_setup)
+{
+ return EOPNOTSUPP;
+}
+
+static inline const struct tsem_context_ops *tsem_nsmgr_get(const char *name)
+{
+ return NULL;
+}
+
+static inline int tsem_nsmgr_register(const struct tsem_context_ops *ops,
+ struct module *module)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int tsem_nsmgr_release(const struct tsem_context_ops *ops)
+{
+ return -EOPNOTSUPP;
+}
+#endif
--
2.39.1
next prev parent reply other threads:[~2024-08-26 10:50 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-26 10:37 [PATCH v4 00/14] Implement Trusted Security Event Modeling Greg Wettstein
2024-08-26 10:37 ` [PATCH v4 01/14] Update MAINTAINERS file Greg Wettstein
2024-08-26 10:37 ` [PATCH v4 02/14] Add TSEM specific documentation Greg Wettstein
2025-01-14 1:29 ` [PATCH v4 2/14] " Paul Moore
2025-01-17 4:47 ` Dr. Greg
2025-01-17 18:10 ` Casey Schaufler
2025-01-18 19:03 ` Dr. Greg
2025-01-21 18:09 ` Casey Schaufler
2025-01-26 18:40 ` Dr. Greg
2025-01-28 22:23 ` Paul Moore
2025-01-31 17:11 ` Dr. Greg
2025-02-25 12:01 ` Dr. Greg
2025-02-25 15:48 ` Casey Schaufler
2025-02-27 12:12 ` Dr. Greg
2025-02-27 16:47 ` Casey Schaufler
2025-03-03 10:14 ` Dr. Greg
2025-03-03 16:23 ` Casey Schaufler
2025-02-05 12:00 ` Dr. Greg
2025-02-05 19:58 ` Casey Schaufler
2025-02-06 12:45 ` Dr. Greg
2025-02-06 15:48 ` Paul Moore
2025-02-07 10:20 ` Dr. Greg
2025-02-07 17:42 ` Casey Schaufler
2025-02-08 0:29 ` Paul Moore
2025-02-17 12:53 ` Dr. Greg
2025-02-17 23:09 ` Paul Moore
2024-08-26 10:37 ` [PATCH v4 03/14] TSEM global declarations Greg Wettstein
2024-08-26 10:37 ` [PATCH v4 04/14] Add primary TSEM implementation file Greg Wettstein
2024-08-26 15:53 ` Casey Schaufler
2024-08-27 10:52 ` Dr. Greg
2024-08-27 17:51 ` Casey Schaufler
2024-08-26 10:37 ` [PATCH v4 05/14] Add root domain trust implementation Greg Wettstein
2024-08-26 10:37 ` [PATCH v4 06/14] Implement TSEM control plane Greg Wettstein
2024-08-26 10:37 ` [PATCH v4 07/14] Add namespace implementation Greg Wettstein
2024-08-26 10:37 ` [PATCH v4 08/14] Add security event description export facility Greg Wettstein
2024-08-26 10:37 ` [PATCH v4 09/14] Add event processing implementation Greg Wettstein
2024-08-26 10:37 ` [PATCH v4 10/14] Implement security event mapping Greg Wettstein
2024-08-26 10:37 ` [PATCH v4 11/14] Implement the internal Trusted Modeling Agent Greg Wettstein
2024-08-26 10:37 ` [PATCH v4 12/14] Implement configuration and methods for default model Greg Wettstein
2024-08-26 10:37 ` Greg Wettstein [this message]
2024-08-26 10:37 ` [PATCH v4 14/14] Activate the configuration and build of the TSEM LSM Greg Wettstein
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=20240826103728.3378-14-greg@enjellic.com \
--to=greg@enjellic.com \
--cc=jmorris@namei.org \
--cc=linux-kernel@vger.kernel.org \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).