public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: "Dr. Greg" <greg@enjellic.com>
To: linux-security-module@vger.kernel.org,
	linux-kernel@vger.kernel.org, corbet@lwn.net
Subject: [PATCH 11/13] Implement security event mapping.
Date: Mon, 10 Jul 2023 05:23:17 -0500	[thread overview]
Message-ID: <20230710102319.19716-12-greg@enjellic.com> (raw)
In-Reply-To: <20230710102319.19716-1-greg@enjellic.com>

The map.c file is responsible for implenting the description of a
security event into a security state coefficient.  The following
documentation file provided as a part of the TSEM implementation
contains a description of this mapping process:

Documentation/admin-guide/LSM/tsem.rst

The mapping process takes a security event description, that was
described in the event.c file, and uses that to drive the mapping
process.  The allocation and mapping of the event is unified
through the tsem_map_event() function provided in this file.

The function for a security event state coefficient mapping is as
follows:

Sp = HF(HF(EVENT_ID) || TASK_ID || HF(COE) || HF(CELL))

Where HF is the cryptographic hash function that has been
designated for use by a security modeling namespace.

This function is fully described in the previously noted
documentation file.

The TASK_ID is the security state coefficient for the
bprm_creds_for_exec security event hook.  It is generated by the
tsem_map_task() function that is implemented in this file.

The TASK_ID mapping function uses the same functional expression
as the security state coefficient mapping but substitutes a
TASK_ID that consists of a buffer of null bytes equal in size to
the digest size of the cryptographic hash function being used in
the model.

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

diff --git a/security/tsem/map.c b/security/tsem/map.c
new file mode 100644
index 000000000000..45f8ee6eca89
--- /dev/null
+++ b/security/tsem/map.c
@@ -0,0 +1,531 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * Copyright (C) 2023 Enjellic Systems Development, LLC
+ * Author: Dr. Greg Wettstein <greg@enjellic.com>
+ *
+ * This file implements mapping of events into security event points.
+ */
+
+#include "tsem.h"
+
+static int get_COE_mapping(struct tsem_event *ep, u8 *mapping)
+{
+	int retn = 0, size;
+	u8 *p;
+	SHASH_DESC_ON_STACK(shash, tfm);
+
+	shash->tfm = tsem_digest();
+	retn = crypto_shash_init(shash);
+	if (retn)
+		goto done;
+
+	p = (u8 *) &ep->COE.uid;
+	size = sizeof(ep->COE.uid);
+	retn = crypto_shash_update(shash, p, size);
+	if (retn)
+		goto done;
+
+	p = (u8 *) &ep->COE.euid;
+	size = sizeof(ep->COE.euid);
+	retn = crypto_shash_update(shash, p, size);
+	if (retn)
+		goto done;
+
+	p = (u8 *) &ep->COE.suid;
+	size = sizeof(ep->COE.suid);
+	retn = crypto_shash_update(shash, p, size);
+	if (retn)
+		goto done;
+
+	p = (u8 *) &ep->COE.gid;
+	size = sizeof(ep->COE.gid);
+	retn = crypto_shash_update(shash, p, size);
+	if (retn)
+		goto done;
+
+	p = (u8 *) &ep->COE.egid;
+	size = sizeof(ep->COE.egid);
+	retn = crypto_shash_update(shash, p, size);
+	if (retn)
+		goto done;
+
+	p = (u8 *) &ep->COE.sgid;
+	size = sizeof(ep->COE.sgid);
+	retn = crypto_shash_update(shash, p, size);
+	if (retn)
+		goto done;
+
+	p = (u8 *) &ep->COE.fsuid;
+	size = sizeof(ep->COE.fsuid);
+	retn = crypto_shash_update(shash, p, size);
+	if (retn)
+		goto done;
+
+	p = (u8 *) &ep->COE.fsgid;
+	size = sizeof(ep->COE.fsgid);
+	retn = crypto_shash_update(shash, p, size);
+	if (retn)
+		goto done;
+
+	p = (u8 *) &ep->COE.capeff;
+	size = sizeof(ep->COE.capeff);
+	retn = crypto_shash_finup(shash, p, size, mapping);
+
+ done:
+	return retn;
+}
+
+static int get_cell_mapping(struct tsem_event *ep, u8 *mapping)
+{
+	int retn = 0, size;
+	u8 *p;
+	struct sockaddr_in *ipv4;
+	struct sockaddr_in6 *ipv6;
+	struct tsem_mmap_file_args *mm_args = &ep->CELL.mmap_file;
+	struct tsem_socket_connect_args *scp = &ep->CELL.socket_connect;
+	struct tsem_socket_accept_args *sap = &ep->CELL.socket_accept;
+	SHASH_DESC_ON_STACK(shash, tfm);
+
+	shash->tfm = tsem_digest();
+	retn = crypto_shash_init(shash);
+	if (retn)
+		goto done;
+
+	if (ep->event == TSEM_MMAP_FILE) {
+		p = (u8 *) &mm_args->reqprot;
+		size = sizeof(mm_args->reqprot);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &mm_args->prot;
+		size = sizeof(mm_args->prot);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &mm_args->flags;
+		size = sizeof(mm_args->flags);
+		if (!mm_args->file) {
+			retn = crypto_shash_finup(shash, p, size, mapping);
+			goto done;
+		}
+
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+	}
+
+	switch (ep->event) {
+	case TSEM_FILE_OPEN:
+	case TSEM_MMAP_FILE:
+	case TSEM_BPRM_SET_CREDS:
+		p = (u8 *) &ep->file.flags;
+		size = sizeof(ep->file.flags);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->file.uid;
+		size = sizeof(ep->file.uid);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->file.gid;
+		size = sizeof(ep->file.gid);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->file.mode;
+		size = sizeof(ep->file.mode);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->file.name_length;
+		size = sizeof(ep->file.name_length);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->file.name;
+		size = tsem_digestsize();
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->file.s_magic;
+		size = sizeof(ep->file.s_magic);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->file.s_id;
+		size = sizeof(ep->file.s_id);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->file.s_uuid;
+		size = sizeof(ep->file.s_uuid);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->file.digest;
+		size = tsem_digestsize();
+		retn = crypto_shash_finup(shash, p, size, mapping);
+		break;
+
+	case TSEM_SOCKET_CREATE:
+		p = (u8 *) &ep->CELL.socket_create.family;
+		size = sizeof(ep->CELL.socket_create.family);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->CELL.socket_create.type;
+		size = sizeof(ep->CELL.socket_create.type);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->CELL.socket_create.protocol;
+		size = sizeof(ep->CELL.socket_create.protocol);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->CELL.socket_create.kern;
+		size = sizeof(ep->CELL.socket_create.kern);
+		retn = crypto_shash_finup(shash, p, size, mapping);
+		if (retn)
+			goto done;
+		break;
+
+	case TSEM_SOCKET_CONNECT:
+	case TSEM_SOCKET_BIND:
+		p = (u8 *) &scp->family;
+		size = sizeof(scp->family);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		switch (scp->family) {
+		case AF_INET:
+			ipv4 = (struct sockaddr_in *) &scp->u.ipv4;
+			p = (u8 *) &ipv4->sin_port;
+			size = sizeof(ipv4->sin_port);
+			retn = crypto_shash_update(shash, p, size);
+			if (retn)
+				goto done;
+
+			p = (u8 *) &ipv4->sin_addr.s_addr;
+			size = sizeof(ipv4->sin_addr.s_addr);
+			retn = crypto_shash_finup(shash, p, size, mapping);
+			break;
+
+		case AF_INET6:
+			ipv6 = (struct sockaddr_in6 *) &scp->u.ipv6;
+			p = (u8 *) &ipv6->sin6_port;
+			size = sizeof(ipv6->sin6_port);
+			retn = crypto_shash_update(shash, p, size);
+			if (retn)
+				goto done;
+
+			p = (u8 *) ipv6->sin6_addr.in6_u.u6_addr8;
+			size = sizeof(ipv6->sin6_addr.in6_u.u6_addr8);
+			retn = crypto_shash_update(shash, p, size);
+			if (retn)
+				goto done;
+
+			p = (u8 *) &ipv6->sin6_flowinfo;
+			size = sizeof(ipv6->sin6_flowinfo);
+			retn = crypto_shash_update(shash, p, size);
+			if (retn)
+				goto done;
+
+			p = (u8 *) &ipv6->sin6_scope_id;
+			size = sizeof(ipv6->sin6_scope_id);
+			retn = crypto_shash_finup(shash, p, size, mapping);
+			if (retn)
+				goto done;
+			break;
+
+		case AF_UNIX:
+			p = scp->u.path;
+			size = strlen(scp->u.path);
+			retn = crypto_shash_finup(shash, p, size, mapping);
+			if (retn)
+				goto done;
+			break;
+
+		default:
+			p = (u8 *) scp->u.mapping;
+			size = tsem_digestsize();
+			retn = crypto_shash_finup(shash, p, size, mapping);
+			if (retn)
+				goto done;
+			break;
+		}
+		break;
+
+	case TSEM_SOCKET_ACCEPT:
+		p = (u8 *) &sap->family;
+		size = sizeof(sap->family);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &sap->type;
+		size = sizeof(sap->type);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &sap->port;
+		size = sizeof(sap->port);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		switch (sap->family) {
+		case AF_INET:
+			p = (u8 *) &sap->u.ipv4;
+			size = sizeof(sap->u.ipv4);
+			retn = crypto_shash_finup(shash, p, size, mapping);
+			if (retn)
+				goto done;
+			break;
+
+		case AF_INET6:
+			p = (u8 *) sap->u.ipv6.in6_u.u6_addr8;
+			size = sizeof(sap->u.ipv6.in6_u.u6_addr8);
+			retn = crypto_shash_finup(shash, p, size, mapping);
+			if (retn)
+				goto done;
+			break;
+
+		case AF_UNIX:
+			p = sap->u.path;
+			size = strlen(sap->u.path);
+			retn = crypto_shash_finup(shash, p, size, mapping);
+			if (retn)
+				goto done;
+			break;
+
+		default:
+			p = sap->u.mapping;
+			size = tsem_digestsize();
+			retn = crypto_shash_finup(shash, p, size, mapping);
+			if (retn)
+				goto done;
+			break;
+		}
+		break;
+
+	case TSEM_TASK_KILL:
+		p = (u8 *) &ep->CELL.task_kill.cross_model;
+		size = sizeof(ep->CELL.task_kill.cross_model);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->CELL.task_kill.signal;
+		size = sizeof(ep->CELL.task_kill.signal);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->CELL.task_kill.target;
+		size = sizeof(ep->CELL.task_kill.target);
+		retn = crypto_shash_finup(shash, p, size, mapping);
+		if (retn)
+			goto done;
+		break;
+
+	case TSEM_GENERIC_EVENT:
+		p = (u8 *) tsem_names[ep->CELL.event_type];
+		size = strlen(tsem_names[ep->CELL.event_type]);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = tsem_context(current)->zero_digest;
+		size = tsem_digestsize();
+		retn = crypto_shash_finup(shash, p, size, mapping);
+		if (retn)
+			goto done;
+		break;
+
+	default:
+		break;
+	}
+
+ done:
+	return retn;
+}
+
+static int get_event_mapping(int event, u8 *task_id, u8 *COE_id, u8 *cell_id,
+			     u8 *mapping)
+{
+	int retn = 0;
+	u32 event_id = (u32) event;
+	SHASH_DESC_ON_STACK(shash, tfm);
+
+	shash->tfm = tsem_digest();
+	retn = crypto_shash_init(shash);
+	if (retn)
+		goto done;
+
+	retn = crypto_shash_update(shash, tsem_names[event_id],
+				   strlen(tsem_names[event_id]));
+	if (retn)
+		goto done;
+	if (task_id) {
+		retn = crypto_shash_update(shash, task_id, tsem_digestsize());
+		if (retn)
+			goto done;
+	}
+	retn = crypto_shash_update(shash, COE_id, tsem_digestsize());
+	if (retn)
+		goto done;
+	retn = crypto_shash_finup(shash, cell_id, tsem_digestsize(), mapping);
+
+ done:
+	return retn;
+}
+
+static int map_event(enum tsem_event_type event, struct tsem_event *ep,
+		     u8 *task_id, u8 *event_mapping)
+{
+	int retn;
+	u8 COE_mapping[HASH_MAX_DIGESTSIZE];
+	u8 cell_mapping[HASH_MAX_DIGESTSIZE];
+
+	retn = get_COE_mapping(ep, COE_mapping);
+	if (retn)
+		goto done;
+
+	retn = get_cell_mapping(ep, cell_mapping);
+	if (retn)
+		goto done;
+
+	retn = get_event_mapping(event, task_id, COE_mapping, cell_mapping,
+				 event_mapping);
+ done:
+	return retn;
+}
+
+/**
+ * tsem_map_task() - Create the task identity description structure.
+ * @file: A pointer to the file structure defining the executable.
+ * @task_id: Pointer to the buffer that the task id will be copied to.
+ *
+ * This function creates the security event state point that will be used
+ * as the task identifier for the generation of security state points
+ * that are created by the process that task identifier is assigned to.
+ *
+ * Return: This function returns 0 if the mapping was successfully
+ *	   created and an error value otherwise.
+ */
+int tsem_map_task(struct file *file, u8 *task_id)
+{
+	int retn = 0;
+	u8 null_taskid[HASH_MAX_DIGESTSIZE];
+	struct tsem_event *ep;
+	struct tsem_event_parameters params;
+
+	params.u.file = file;
+	ep = tsem_event_init(TSEM_BPRM_SET_CREDS, &params, false);
+	if (IS_ERR(ep)) {
+		retn = PTR_ERR(ep);
+		ep = NULL;
+		goto done;
+	}
+
+	memset(null_taskid, '\0', tsem_digestsize());
+	retn = map_event(TSEM_BPRM_SET_CREDS, ep, null_taskid, task_id);
+	tsem_event_put(ep);
+
+ done:
+	return retn;
+}
+
+/**
+ * tsem_map_event() - Create a security event mapping.
+ * @event: The number of the event to be mapped.
+ * @params: A pointer to the structure containing the event description
+ *	    parameters.
+ *
+ * This function creates a structure to describe a security event
+ * and maps the event into a security state coefficient.
+ *
+ * Return: On success the function returns a pointer to the tsem_event
+ *	   structure that describes the event.  If an error is encountered
+ *	   an error return value is encoded in the pointer.
+ */
+struct tsem_event *tsem_map_event(enum tsem_event_type event,
+				  struct tsem_event_parameters *params)
+{
+	int retn = 0;
+	struct tsem_event *ep;
+	struct tsem_task *task = tsem_task(current);
+
+	ep = tsem_event_init(event, params, false);
+	if (IS_ERR(ep))
+		goto done;
+
+	if (task->context->external)
+		goto done;
+
+	retn = map_event(event, ep, task->task_id, ep->mapping);
+	if (retn) {
+		tsem_event_put(ep);
+		ep = ERR_PTR(retn);
+	}
+
+ done:
+	return ep;
+}
+
+
+/**
+ * tsem_map_event_locked() - Create a security event mapping while atomic.
+ * @event: The number of the event to be mapped.
+ * @params: A pointer to the structure containing the event description
+ *	    parameters.
+ *
+ * This function creates a structure to describe a security event
+ * and maps the event into a security state coefficient.
+ *
+ * Return: On success the function returns a pointer to the tsem_event
+ *	   structure that describes the event.  If an error is encountered
+ *	   an error return value is encoded in the pointer.
+ */
+struct tsem_event *tsem_map_event_locked(enum tsem_event_type event,
+					 struct tsem_event_parameters *params)
+{
+	int retn = 0;
+	struct tsem_event *ep;
+	struct tsem_task *task = tsem_task(current);
+
+	ep = tsem_event_init(event, params, true);
+	if (IS_ERR(ep))
+		goto done;
+
+	if (task->context->external)
+		goto done;
+
+	retn = map_event(event, ep, task->task_id, ep->mapping);
+	if (retn) {
+		tsem_event_put(ep);
+		ep = ERR_PTR(retn);
+	}
+
+ done:
+	return ep;
+}
-- 
2.39.1


  parent reply	other threads:[~2023-07-10 11:03 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-10 10:23 [PATCH 00/13] Implement Trusted Security Event Modeling Dr. Greg
2023-07-10 10:23 ` [PATCH 01/13] Update MAINTAINERS file Dr. Greg
2023-07-10 20:00   ` Randy Dunlap
2023-07-15 22:45     ` Dr. Greg
2023-07-10 10:23 ` [PATCH 02/13] Add TSEM specific documentation Dr. Greg
2023-07-11  4:37   ` Randy Dunlap
2023-07-17  0:36     ` Dr. Greg
2023-07-17  1:56       ` Randy Dunlap
2023-08-08 18:48   ` Serge Hallyn
2023-08-11 20:22     ` Dr. Greg
2024-01-04 15:54       ` Paul Moore
2024-01-05  3:54         ` Dr. Greg
2024-01-04  4:00   ` [PATCH 2/13] " Paul Moore
2024-01-05  2:55     ` Dr. Greg
2024-01-08 11:43     ` Dr. Greg
2024-02-05 16:09       ` Paul Moore
2024-02-19 11:16         ` Dr. Greg
2023-07-10 10:23 ` [PATCH 03/13] Implement CAP_TRUST capability Dr. Greg
2023-08-07 20:21   ` Casey Schaufler
2023-08-15 10:19     ` Dr. Greg
2023-08-15 17:15       ` Casey Schaufler
2023-07-10 10:23 ` [PATCH 04/13] Add TSEM master header file Dr. Greg
2023-08-07 20:39   ` Casey Schaufler
2023-08-10  2:57     ` Dr. Greg
2023-08-10 15:03       ` Casey Schaufler
2023-07-10 10:23 ` [PATCH 05/13] Add primary TSEM implementation file Dr. Greg
2023-08-07 21:00   ` Casey Schaufler
2023-08-11  7:21     ` Dr. Greg
2023-07-10 10:23 ` [PATCH 06/13] Add root domain trust implementation Dr. Greg
2023-07-10 10:23 ` [PATCH 07/13] Implement TSEM control plane Dr. Greg
2023-07-10 10:23 ` [PATCH 08/13] Add namespace implementation Dr. Greg
2023-07-10 10:23 ` [PATCH 09/13] Add security event description export facility Dr. Greg
2023-07-10 10:23 ` [PATCH 10/13] Add event description implementation Dr. Greg
2023-07-10 10:23 ` Dr. Greg [this message]
2023-07-10 10:23 ` [PATCH 12/13] Implement an internal Trusted Modeling Agent Dr. Greg
2023-07-10 10:23 ` [PATCH 13/13] Activate the configuration and build of the TSEM LSM 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=20230710102319.19716-12-greg@enjellic.com \
    --to=greg@enjellic.com \
    --cc=corbet@lwn.net \
    --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