From nobody Mon Feb 9 01:46:16 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EB965EB64D9 for ; Mon, 10 Jul 2023 11:03:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232184AbjGJLD0 (ORCPT ); Mon, 10 Jul 2023 07:03:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57628 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229959AbjGJLDW (ORCPT ); Mon, 10 Jul 2023 07:03:22 -0400 Received: from blizzard.enjellic.com (wind.enjellic.com [76.10.64.91]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 19F1BE5; Mon, 10 Jul 2023 04:03:01 -0700 (PDT) Received: from blizzard.enjellic.com (localhost [127.0.0.1]) by blizzard.enjellic.com (8.15.2/8.15.2) with ESMTP id 36AANS4r019794; Mon, 10 Jul 2023 05:23:28 -0500 Received: (from greg@localhost) by blizzard.enjellic.com (8.15.2/8.15.2/Submit) id 36AANSso019792; Mon, 10 Jul 2023 05:23:28 -0500 X-Authentication-Warning: blizzard.enjellic.com: greg set sender to greg@enjellic.com using -f From: "Dr. Greg" 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 Message-Id: <20230710102319.19716-12-greg@enjellic.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20230710102319.19716-1-greg@enjellic.com> References: <20230710102319.19716-1-greg@enjellic.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" 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 =3D 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 --- 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 + * + * 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 =3D 0, size; + u8 *p; + SHASH_DESC_ON_STACK(shash, tfm); + + shash->tfm =3D tsem_digest(); + retn =3D crypto_shash_init(shash); + if (retn) + goto done; + + p =3D (u8 *) &ep->COE.uid; + size =3D sizeof(ep->COE.uid); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ep->COE.euid; + size =3D sizeof(ep->COE.euid); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ep->COE.suid; + size =3D sizeof(ep->COE.suid); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ep->COE.gid; + size =3D sizeof(ep->COE.gid); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ep->COE.egid; + size =3D sizeof(ep->COE.egid); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ep->COE.sgid; + size =3D sizeof(ep->COE.sgid); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ep->COE.fsuid; + size =3D sizeof(ep->COE.fsuid); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ep->COE.fsgid; + size =3D sizeof(ep->COE.fsgid); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ep->COE.capeff; + size =3D sizeof(ep->COE.capeff); + retn =3D crypto_shash_finup(shash, p, size, mapping); + + done: + return retn; +} + +static int get_cell_mapping(struct tsem_event *ep, u8 *mapping) +{ + int retn =3D 0, size; + u8 *p; + struct sockaddr_in *ipv4; + struct sockaddr_in6 *ipv6; + struct tsem_mmap_file_args *mm_args =3D &ep->CELL.mmap_file; + struct tsem_socket_connect_args *scp =3D &ep->CELL.socket_connect; + struct tsem_socket_accept_args *sap =3D &ep->CELL.socket_accept; + SHASH_DESC_ON_STACK(shash, tfm); + + shash->tfm =3D tsem_digest(); + retn =3D crypto_shash_init(shash); + if (retn) + goto done; + + if (ep->event =3D=3D TSEM_MMAP_FILE) { + p =3D (u8 *) &mm_args->reqprot; + size =3D sizeof(mm_args->reqprot); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &mm_args->prot; + size =3D sizeof(mm_args->prot); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &mm_args->flags; + size =3D sizeof(mm_args->flags); + if (!mm_args->file) { + retn =3D crypto_shash_finup(shash, p, size, mapping); + goto done; + } + + retn =3D 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 =3D (u8 *) &ep->file.flags; + size =3D sizeof(ep->file.flags); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ep->file.uid; + size =3D sizeof(ep->file.uid); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ep->file.gid; + size =3D sizeof(ep->file.gid); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ep->file.mode; + size =3D sizeof(ep->file.mode); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ep->file.name_length; + size =3D sizeof(ep->file.name_length); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ep->file.name; + size =3D tsem_digestsize(); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ep->file.s_magic; + size =3D sizeof(ep->file.s_magic); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ep->file.s_id; + size =3D sizeof(ep->file.s_id); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ep->file.s_uuid; + size =3D sizeof(ep->file.s_uuid); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ep->file.digest; + size =3D tsem_digestsize(); + retn =3D crypto_shash_finup(shash, p, size, mapping); + break; + + case TSEM_SOCKET_CREATE: + p =3D (u8 *) &ep->CELL.socket_create.family; + size =3D sizeof(ep->CELL.socket_create.family); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ep->CELL.socket_create.type; + size =3D sizeof(ep->CELL.socket_create.type); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ep->CELL.socket_create.protocol; + size =3D sizeof(ep->CELL.socket_create.protocol); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ep->CELL.socket_create.kern; + size =3D sizeof(ep->CELL.socket_create.kern); + retn =3D crypto_shash_finup(shash, p, size, mapping); + if (retn) + goto done; + break; + + case TSEM_SOCKET_CONNECT: + case TSEM_SOCKET_BIND: + p =3D (u8 *) &scp->family; + size =3D sizeof(scp->family); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + switch (scp->family) { + case AF_INET: + ipv4 =3D (struct sockaddr_in *) &scp->u.ipv4; + p =3D (u8 *) &ipv4->sin_port; + size =3D sizeof(ipv4->sin_port); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ipv4->sin_addr.s_addr; + size =3D sizeof(ipv4->sin_addr.s_addr); + retn =3D crypto_shash_finup(shash, p, size, mapping); + break; + + case AF_INET6: + ipv6 =3D (struct sockaddr_in6 *) &scp->u.ipv6; + p =3D (u8 *) &ipv6->sin6_port; + size =3D sizeof(ipv6->sin6_port); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) ipv6->sin6_addr.in6_u.u6_addr8; + size =3D sizeof(ipv6->sin6_addr.in6_u.u6_addr8); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ipv6->sin6_flowinfo; + size =3D sizeof(ipv6->sin6_flowinfo); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ipv6->sin6_scope_id; + size =3D sizeof(ipv6->sin6_scope_id); + retn =3D crypto_shash_finup(shash, p, size, mapping); + if (retn) + goto done; + break; + + case AF_UNIX: + p =3D scp->u.path; + size =3D strlen(scp->u.path); + retn =3D crypto_shash_finup(shash, p, size, mapping); + if (retn) + goto done; + break; + + default: + p =3D (u8 *) scp->u.mapping; + size =3D tsem_digestsize(); + retn =3D crypto_shash_finup(shash, p, size, mapping); + if (retn) + goto done; + break; + } + break; + + case TSEM_SOCKET_ACCEPT: + p =3D (u8 *) &sap->family; + size =3D sizeof(sap->family); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &sap->type; + size =3D sizeof(sap->type); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &sap->port; + size =3D sizeof(sap->port); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + switch (sap->family) { + case AF_INET: + p =3D (u8 *) &sap->u.ipv4; + size =3D sizeof(sap->u.ipv4); + retn =3D crypto_shash_finup(shash, p, size, mapping); + if (retn) + goto done; + break; + + case AF_INET6: + p =3D (u8 *) sap->u.ipv6.in6_u.u6_addr8; + size =3D sizeof(sap->u.ipv6.in6_u.u6_addr8); + retn =3D crypto_shash_finup(shash, p, size, mapping); + if (retn) + goto done; + break; + + case AF_UNIX: + p =3D sap->u.path; + size =3D strlen(sap->u.path); + retn =3D crypto_shash_finup(shash, p, size, mapping); + if (retn) + goto done; + break; + + default: + p =3D sap->u.mapping; + size =3D tsem_digestsize(); + retn =3D crypto_shash_finup(shash, p, size, mapping); + if (retn) + goto done; + break; + } + break; + + case TSEM_TASK_KILL: + p =3D (u8 *) &ep->CELL.task_kill.cross_model; + size =3D sizeof(ep->CELL.task_kill.cross_model); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ep->CELL.task_kill.signal; + size =3D sizeof(ep->CELL.task_kill.signal); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D (u8 *) &ep->CELL.task_kill.target; + size =3D sizeof(ep->CELL.task_kill.target); + retn =3D crypto_shash_finup(shash, p, size, mapping); + if (retn) + goto done; + break; + + case TSEM_GENERIC_EVENT: + p =3D (u8 *) tsem_names[ep->CELL.event_type]; + size =3D strlen(tsem_names[ep->CELL.event_type]); + retn =3D crypto_shash_update(shash, p, size); + if (retn) + goto done; + + p =3D tsem_context(current)->zero_digest; + size =3D tsem_digestsize(); + retn =3D 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 =3D 0; + u32 event_id =3D (u32) event; + SHASH_DESC_ON_STACK(shash, tfm); + + shash->tfm =3D tsem_digest(); + retn =3D crypto_shash_init(shash); + if (retn) + goto done; + + retn =3D crypto_shash_update(shash, tsem_names[event_id], + strlen(tsem_names[event_id])); + if (retn) + goto done; + if (task_id) { + retn =3D crypto_shash_update(shash, task_id, tsem_digestsize()); + if (retn) + goto done; + } + retn =3D crypto_shash_update(shash, COE_id, tsem_digestsize()); + if (retn) + goto done; + retn =3D 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 =3D get_COE_mapping(ep, COE_mapping); + if (retn) + goto done; + + retn =3D get_cell_mapping(ep, cell_mapping); + if (retn) + goto done; + + retn =3D 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 =3D 0; + u8 null_taskid[HASH_MAX_DIGESTSIZE]; + struct tsem_event *ep; + struct tsem_event_parameters params; + + params.u.file =3D file; + ep =3D tsem_event_init(TSEM_BPRM_SET_CREDS, ¶ms, false); + if (IS_ERR(ep)) { + retn =3D PTR_ERR(ep); + ep =3D NULL; + goto done; + } + + memset(null_taskid, '\0', tsem_digestsize()); + retn =3D 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 =3D 0; + struct tsem_event *ep; + struct tsem_task *task =3D tsem_task(current); + + ep =3D tsem_event_init(event, params, false); + if (IS_ERR(ep)) + goto done; + + if (task->context->external) + goto done; + + retn =3D map_event(event, ep, task->task_id, ep->mapping); + if (retn) { + tsem_event_put(ep); + ep =3D 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 =3D 0; + struct tsem_event *ep; + struct tsem_task *task =3D tsem_task(current); + + ep =3D tsem_event_init(event, params, true); + if (IS_ERR(ep)) + goto done; + + if (task->context->external) + goto done; + + retn =3D map_event(event, ep, task->task_id, ep->mapping); + if (retn) { + tsem_event_put(ep); + ep =3D ERR_PTR(retn); + } + + done: + return ep; +} --=20 2.39.1