diff mbox series

[04/13] Add TSEM master header file.

Message ID 20230710102319.19716-5-greg@enjellic.com (mailing list archive)
State Changes Requested
Delegated to: Paul Moore
Headers show
Series Implement Trusted Security Event Modeling. | expand

Commit Message

Dr. Greg July 10, 2023, 10:23 a.m. UTC
TSEM is designed, from a functional perspective, to be contained
entirely in its own directory.

The tsem.h header file defines the enumeration types, structure
definitions and externally visiable functions that are referenced
by all of the compilation units of the TSEM LSM implementation in
that directory.

The structure and enumeration types are extensively documented
and are the recommended starting point for understanding TSEM
implementation and functionality.

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

Comments

Casey Schaufler Aug. 7, 2023, 8:39 p.m. UTC | #1
On 7/10/2023 3:23 AM, Dr. Greg wrote:
> TSEM is designed, from a functional perspective, to be contained
> entirely in its own directory.
>
> The tsem.h header file defines the enumeration types, structure
> definitions and externally visiable functions that are referenced
> by all of the compilation units of the TSEM LSM implementation in
> that directory.

Extensive documentation notwithstanding, it's impossible to review
the data structures and constants without the code that goes along
with them.

>
> The structure and enumeration types are extensively documented
> and are the recommended starting point for understanding TSEM
> implementation and functionality.
>
> Signed-off-by: Greg Wettstein <greg@enjellic.com>
> ---
>  security/tsem/tsem.h | 1516 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 1516 insertions(+)
>  create mode 100644 security/tsem/tsem.h
>
> diff --git a/security/tsem/tsem.h b/security/tsem/tsem.h
> new file mode 100644
> index 000000000000..03915f47529b
> --- /dev/null
> +++ b/security/tsem/tsem.h
> @@ -0,0 +1,1516 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +
> +/*
> + * Copyright (C) 2023 Enjellic Systems Development, LLC
> + * Author: Dr. Greg Wettstein <greg@enjellic.com>
> + *
> + * This is the single include file that documents all of the externally
> + * visible types and functions that are used by TSEM.  This file is
> + * currently organized into four major sections in the following order;
> + *
> + * includes used by all compilation units
> + * CPP definitions
> + * enumeration types
> + * structure definitions
> + * function declarations
> + * inline encapsulation functions.
> + *
> + * Include files that are referenced by more than a single compilation
> + * should be included in this file.  Includes that are needed to
> + * satisfy compilation requirements for only a single file should be
> + * included in the file needing that include.
> + *
> + * Understanding the overall implementation and architecture of TSEM
> + * will be facilitated by reviewing the documentation in this file.
> + */
> +
> +#include <uapi/linux/in.h>
> +#include <uapi/linux/in6.h>
> +#include <linux/wait.h>
> +#include <linux/kref.h>
> +#include <linux/lsm_hooks.h>
> +#include <linux/capability.h>
> +#include <crypto/hash.h>
> +#include <crypto/hash_info.h>
> +#include <net/af_unix.h>
> +
> +/* The capability needed to manage TSEM. */
> +#define TSEM_CONTROL_CAPABILITY CAP_ML

Why would you do this? You gave the capability a name that even you
don't want to use.

> +
> +/*
> + * The number of 'slots' in the structure magazines that are used to
> + * satisfy modeling of security events that are called in atomic context.
> + */
> +#define TSEM_ROOT_MAGAZINE_SIZE	96
> +#define TSEM_MAGAZINE_SIZE_INTERNAL 16
> +#define TSEM_MAGAZINE_SIZE_EXTERNAL 96
> +
> +/**
> + * enum tsem_event_type - Ordinal value for a security event.
> + * @TSEM_BPRM_SET_CREDS: Ordinal value for bprm_creds_for_exec.
> + * @TSEM_GENERIC_EVENT: Ordinal value for a generically modeled event.
> + * @TSEM_TASK_KILL: Ordinal value for task kill.
> + * @....: Remainder follows with a similar naming format that has
> + *        TSEM_ prep ended to the raw LSM security hook name.
> + * @TSEM_EVENT_CNT: The final ordinal value is used to define the
> + *		    length of the following arrays that are indexed
> + *		    by the ordinal value of the hook:
> + *
> + * This enumeration is used to designate an ordinal value for each
> + * security event, ie. LSM hook, that TSEM is implementing modeling
> + * for.  This value is used to identify the hook that is either having
> + * its event description being exported to an external Trusted Modeling
> + * Agent (TMA) or modeled by the internal TMA implementation.
> + *
> + * The primary use of this enumeration is to conditionalize code paths
> + * based on the security hook being processed and to index the
> + * tsem_names array and the array that defines the action that is to
> + * be taken in response to an event that generates a permissions
> + * violation.
> + */
> +enum tsem_event_type {
> +	TSEM_BPRM_SET_CREDS = 1,
> +	TSEM_GENERIC_EVENT,
> +	TSEM_TASK_KILL,
> +	TSEM_TASK_SETPGID,
> +	TSEM_TASK_GETPGID,
> +	TSEM_TASK_GETSID,
> +	TSEM_TASK_SETNICE,
> +	TSEM_TASK_SETIOPRIO,
> +	TSEM_TASK_GETIOPRIO,
> +	TSEM_TASK_PRLIMIT,
> +	TSEM_TASK_SETRLIMIT,
> +	TSEM_TASK_SETSCHEDULER,
> +	TSEM_TASK_GETSCHEDULER,
> +	TSEM_TASK_PRCTL,
> +	TSEM_FILE_OPEN,
> +	TSEM_MMAP_FILE,
> +	TSEM_FILE_IOCTL,
> +	TSEM_FILE_LOCK,
> +	TSEM_FILE_FCNTL,
> +	TSEM_FILE_RECEIVE,
> +	TSEM_UNIX_STREAM_CONNECT,
> +	TSEM_UNIX_MAY_SEND,
> +	TSEM_SOCKET_CREATE,
> +	TSEM_SOCKET_CONNECT,
> +	TSEM_SOCKET_BIND,
> +	TSEM_SOCKET_ACCEPT,
> +	TSEM_SOCKET_LISTEN,
> +	TSEM_SOCKET_SOCKETPAIR,
> +	TSEM_SOCKET_SENDMSG,
> +	TSEM_SOCKET_RECVMSG,
> +	TSEM_SOCKET_GETSOCKNAME,
> +	TSEM_SOCKET_GETPEERNAME,
> +	TSEM_SOCKET_SETSOCKOPT,
> +	TSEM_SOCKET_SHUTDOWN,
> +	TSEM_PTRACE_TRACEME,
> +	TSEM_KERNEL_MODULE_REQUEST,
> +	TSEM_KERNEL_LOAD_DATA,
> +	TSEM_KERNEL_READ_FILE,
> +	TSEM_SB_MOUNT,
> +	TSEM_SB_UMOUNT,
> +	TSEM_SB_REMOUNT,
> +	TSEM_SB_PIVOTROOT,
> +	TSEM_SB_STATFS,
> +	TSEM_MOVE_MOUNT,
> +	TSEM_SHM_ASSOCIATE,
> +	TSEM_SHM_SHMCTL,
> +	TSEM_SHM_SHMAT,
> +	TSEM_SEM_ASSOCIATE,
> +	TSEM_SEM_SEMCTL,
> +	TSEM_SEM_SEMOP,
> +	TSEM_SYSLOG,
> +	TSEM_SETTIME,
> +	TSEM_QUOTACTL,
> +	TSEM_QUOTA_ON,
> +	TSEM_MSG_QUEUE_ASSOCIATE,
> +	TSEM_MSG_QUEUE_MSGCTL,
> +	TSEM_MSG_QUEUE_MSGSND,
> +	TSEM_MSG_QUEUE_MSGRCV,
> +	TSEM_IPC_PERMISSION,
> +	TSEM_KEY_ALLOC,
> +	TSEM_KEY_PERMISSION,
> +	TSEM_NETLINK_SEND,
> +	TSEM_INODE_CREATE,
> +	TSEM_INODE_LINK,
> +	TSEM_INODE_UNLINK,
> +	TSEM_INODE_SYMLINK,
> +	TSEM_INODE_MKDIR,
> +	TSEM_INODE_RMDIR,
> +	TSEM_INODE_MKNOD,
> +	TSEM_INODE_RENAME,
> +	TSEM_INODE_SETATTR,
> +	TSEM_INODE_GETATTR,
> +	TSEM_INODE_SETXATTR,
> +	TSEM_INODE_GETXATTR,
> +	TSEM_INODE_LISTXATTR,
> +	TSEM_INODE_REMOVEXATTR,
> +	TSEM_INODE_KILLPRIV,
> +	TSEM_TUN_DEV_CREATE,
> +	TSEM_TUN_DEV_ATTACH_QUEUE,
> +	TSEM_TUN_DEV_ATTACH,
> +	TSEM_TUN_DEV_OPEN,
> +	TSEM_BPF,
> +	TSEM_BPF_MAP,
> +	TSEM_BPF_PROG,
> +	TSEM_EVENT_CNT
> +};
> +
> +/**
> + * enum tsem_action_type - Ordinal value for security responses.
> + * @TSEM_ACTION_LOG: Ordinal value to indicate that a security event
> + *		     that results in a model permissions violation
> + *		     should be logged.
> + * @TSEM_ACTION_EPERM: Ordinal value to indicate that a security event
> + *		       generating a model permissions violation should
> + *		       return -EPERM to the caller.
> + *
> + * This enumeration type is used to designate what type of action is
> + * to be taken when the processing of a security event hook results in
> + * a model violation.  The TSEM_ACTION_LOG and TSEM_ACTION_EPERM
> + * translate into the classical concepts of logging or enforcing
> + * actions used by other mandatory access control architectures.
> + */
> +enum tsem_action_type {
> +	TSEM_ACTION_LOG = 0,
> +	TSEM_ACTION_EPERM,
> +	TSEM_ACTION_CNT
> +};
> +
> +/**
> + * enum tsem_control_type - Ordinal values for TSEM control actions.
> + * @TSEM_CONTROL_INTERNAL: This ordinal value is set when the first
> + *			   word of an argument string written to the
> + *			   control file is the word 'internal'.  This
> + *			   designates that the security namespace will
> + *			   be modeled by the internal TMA.
> + * @TSEM_CONTROL_EXTERNAL: This ordinal value is set when the first
> + *			   word of an argument string written to the
> + *			   control file is the word 'external'.  This
> + *			   designates that the security namespace will
> + *			   be model by an external TMA.
> + * @TSEM_CONTROL_ENFORCE: This ordinal value is set when the word
> + *			  'enforce' is written to the control file.
> + *			  This indicates that model is to be placed
> + *			  in 'enforcing' mode and security events that
> + *			  result in model violations will return EPERM.
> + * @TSEM_CONTROL_SEAL: This ordinal value is set when the word 'seal'
> + *		       is written to the control file.  This indicates
> + *		       that the model for security domain will treat
> + *		       all security events that do not conform to the
> + *		       model as 'forensics' events.
> + * @TSEM_CONTROL_TRUSTED: This ordinal value is used when the first
> + *			  word of an argument string written to the
> + *			  control file is the word 'trusted'.  This
> + *			  is interpreted as a directive to set the
> + *			  trust status of the task that executed the
> + *			  security event to be trusted.
> + * @TSEM_CONTROL_UNTRUSTED: This ordinal value is used when the first
> + *			    word of an argument string written to the
> + *			    control file is the word 'untrusted'.
> + *			    This is interpreted as a directive to set
> + *			    the trust status of the task that executed
> + *			    the security event to be untrusted.
> + * @TSEM_CONTROL_MAP_STATE: This ordinal value is used when the first
> + *			    word of an argument string written to the
> + *			    control file is the word 'state'.  The
> + *			    argument to this directive will be an
> + *			    ASCII hexadecimally encoded string of the
> + *			    current model's digest size that will be
> + *			    treated as a security state point for
> + *			    inclusion in the security model for the
> + *			    security domain/namespace.
> + * @TSEM_CONTROL_MAP_PSEUDONYM: This ordinal value is used when the
> + *				first word of an argument string
> + *				written to the control file is the
> + *				word 'pseudonym'.  The argument to
> + *				this directive will be an ASCII
> + *				hexadecimally encoded string of the
> + *				current model's digest size that will
> + *				be treated as a pseudonym directive
> + *				for the security domain/namespace.
> + * TSEM_CONTROL_MAP_BASE: This ordinal value is used when the first
> + *			  word of an argument string written to the
> + *			  control file is the word 'base'.  The
> + *			  argument to this directive will be an ASCII
> + *			  hexadecimally encoded string of the current
> + *			  model's digest size that will be treated as
> + *			  the base value for the computation of the
> + *			  functional values (measurement and state) of
> + *			  the security domain/namespace.
> +
> + * This enumeration type is used to designate what type of control
> + * action is to be implemented when arguments are written to the TSEM
> + * control file (/sys/kernel/security/tsem/control).  The ordinal
> + * values govern the processing of the command and the interpretation
> + * of the rest of the command argument string.
> + */
> +enum tsem_control_type {
> +	TSEM_CONTROL_INTERNAL = 0,
> +	TSEM_CONTROL_EXTERNAL,
> +	TSEM_CONTROL_ENFORCE,
> +	TSEM_CONTROL_SEAL,
> +	TSEM_CONTROL_TRUSTED,
> +	TSEM_CONTROL_UNTRUSTED,
> +	TSEM_CONTROL_MAP_STATE,
> +	TSEM_CONTROL_MAP_PSEUDONYM,
> +	TSEM_CONTROL_MAP_BASE
> +};
> +
> +/**
> + * enum tsem_ns_reference - Ordinal value for DAC namespace reference.
> + * @TSEM_NS_INITIAL: This ordinal value indicates that the uid/gid
> + *		     values should be interpreted against the initial
> + *		     user namespace.
> + * @TSEM_NS_CURRENT: This ordinal value indicates that the uid/gid
> + *		     values should be interpreted against the user
> + *		     namespace that is in effect for the process being
> + *		     modeled.
> + *
> + * This enumeration type is used to indicate what user namespace
> + * should be referenced when the uid/gid values are interpreted for
> + * the creation of either the COE or CELL identities.  The enumeration
> + * ordinal passed to the tsem_ns_create() function, to configure the
> + * security domain/namespace, is set by the nsref argument to either
> + * the 'internal' or 'external' control commands.
> + */
> +enum tsem_ns_reference {
> +	TSEM_NS_INITIAL = 1,
> +	TSEM_NS_CURRENT
> +};
> +
> +/**
> + * enum tsem_task_trust - Ordinal value describing task trust status.
> + * @TSEM_TASK_TRUSTED: This ordinal value indicates that the task has
> + *		       not executed a security event that has resulted
> + *		       in a security behavior not described by the
> + *		       security model the task is being governed by.
> + * @TSEM_TASK_UNTRUSTED: This ordinal value indicates that the task
> + *		          has requested the execution of a security event
> + *		          that resulted in a security behavior not
> + *		          permitted by the security model the task is
> + *		          being governed by.
> + * @TSEM_TASK_TRUST_PENDING: This ordinal value indicates that the setting
> + *			     of the task trust status is pending a response
> + *		             from an external TMA.
> + *
> + * This enumeration type is used to specify the three different trust
> + * states that a task can be in.  The trust status of a task is
> + * regulated by the trust_status member of struct tsem_task.  A task
> + * carrying the status of TSEM_TASK_TRUSTED means that it has
> + * not requested the execution of any security events that are
> + * inconsistent with the security model that the task is running in.
> + *
> + * If a task requests execution of a security event that is
> + * inconsistent with the security model it is operating in, and the
> + * domain is running in 'sealed' mode, the task trust status is set to
> + * TSEM_TASK_UNTRUSTED.  This value is 'sticky' in that it will be
> + * propagated to any child tasks that are spawned from an untrusted
> + * task.
> + *
> + * In the case of an externally modeled security domain/namespace, the
> + * task trust status cannot be determined until the modeling of the
> + * security event has been completed.  The tsem_export_event()
> + * function sets the trust status TSEM_TASK_TRUST_PENDING and then
> + * places the task into an interruptible sleep state.
> + *
> + * Only two events will cause the task to be removed from sleep state.
> + * Either the task is killed or a control message is written to the
> + * TSEM control file that specifies the trust status of the task.  See
> + * the description of the TSEM_CONTROL_TRUSTED and
> + * TSEM_CONTROL_UNTRUSTED enumeration types.
> + */
> +enum tsem_task_trust {
> +	TSEM_TASK_TRUSTED = 1,
> +	TSEM_TASK_UNTRUSTED = 2,
> +	TSEM_TASK_TRUST_PENDING = 4

What happened to 3?

> +};
> +
> +/**
> + * enum tsem_inode_state - Ordinal value for inode reference state.
> + * @TSEM_INODE_COLLECTING: This ordinal value indicates that the uid/gid
> + *			   values should be interpreted against the initial
> + *			   user namespace.
> + * @TSEM_INODE_COLLECTED: This ordinal value indicates that the uid/gid
> + *			  values should be interpreted against the user
> + *			  namespace that is in effect for the process being
> + *		          modeled.
> + *
> + * This enumeration type is used to specify the status of the inode
> + * that is having a digest value computed on the file that it is
> + * referencing.  The purpose of this enumeration is so that the
> + * recursive call to the TSEM_FILE_OPEN hook, caused by the kernel
> + * opening the file to compute the checksum, can be bypassed.
> + *
> + * The state value of the inode is carried in struct tsem_inode and is
> + * set and interrogated by the add_file_digest() function.  If the
> + * status of the inode is TSEM_INODE_COLLECTED and the iversion of the
> + * inode is the same as the collection time, the cached value for
> + * currently active model digest is returned.
> +
> + * If the test for the relevancy of the cached digest value fails the
> + * status of the inode is set to TSEM_INODE_COLLECTING.  The
> + * tsem_file_open() function will check the inode status when it is
> + * invoked by the integrity_kernel_read() function and if it is
> + * set to 'collecting', a successful permissions check is returned so
> + * that the kernel can open the file and compute its digest.
> + */
> +enum tsem_inode_state {
> +	TSEM_INODE_COLLECTING = 1,
> +	TSEM_INODE_COLLECTED
> +};
> +
> +/**
> + * struct tsem_task - TSEM task control structure.
> + * @tma_for_ns: The context identity number of the namespace that
> + *		the task has control over if any.
> + * @trust_status: The enumeration type that specifies the trust state of
> + *		  the process.
> + * @task_id: The hash specific digest that identifies the process.
> + * @task_key: A hash specific digest value that is used to
> + *	      authenticate a task that is running as a trust
> + *	      orchestrator to a task that is under the control of the
> + *	      orchestrator.
> + * @context: A pointer to the tsem_context structure that defines the
> + *	     modeling context that the task is running under.
> + *
> + * This structure is one of the two primary control structures that
> + * are implemented through the LSM blob functionality.  It is
> + * automatically created when the task control structure is allocated
> + * for a new task that is being created.  It's role is to control the
> + * status of the task with respect to its security model.
> + *
> + * The trust_status member of structure determines whether or not the
> + * task is in a condition to be trusted.  It represents whether or not
> + * the task has requested execution of a security event that is
> + * inconsistent with the model that the task is running under.
> + * Reference the tsem_trust_status enumeration type for more
> + * information on this member.  The trust status value is propagated
> + * to any child tasks that are spawned from a task.
> + *
> + * The digest value that the task_id member contains is generated by
> + * the tsem_tsem_bprm_creds_for_exec() function that computes the
> + * task identity based on the COE identity and the CELL identity of
> + * the executable that is being started.  This task_id value is used
> + * in the computation of the security state point values in
> + * combination with the COE and CELL identities for this event.  The
> + * task_id digest creates security state points that are specific to
> + * the executable file that was used to start the task.
> + *
> + * The task_key member holds the authentication key that will be used
> + * to authenticate a process that is requesting the ability to set the
> + * trust status of a process.  This value is generated for the task
> + * structure of the trust orchestrator when a security modeling
> + * namespace is created by the orchestrator.
> + *
> + * As an additional protection, the creation of a namespace causes the
> + * context id of the created namespace to be placed in the task that
> + * will serve as the trust orchestrator for the namespace.  This
> + * context id must match the context id of a process that a trust
> + * control request is being sent to.  Like the authentication key
> + * this value is not propagated on task allocation so only the task
> + * that has nominated the security modeling namespace will have
> + * possession of the necessary credentials to control it.
> + *
> + * The context member of the structure contains a pointer to the
> + * tsem_context structure allocated when a security modeling namespace
> + * is created by the tsem_ns_create() function.  This structure will
> + * contain all of the information needed to define how the task is to
> + * have its security behavior modeled.
> + */
> +struct tsem_task {
> +	u64 tma_for_ns;
> +	enum tsem_task_trust trust_status;
> +	u8 task_id[HASH_MAX_DIGESTSIZE];
> +	u8 task_key[HASH_MAX_DIGESTSIZE];
> +	struct tsem_context *context;
> +};
> +
> +/**
> + * struct tsem_context - TSEM modeling context description.
> + * @kref: Reference count for the context.
> + * @work: Work structure for delayed release of the context.
> + * @id: The index number of the context.
> + * @sealed: Status variable indicating whether or not the
> + *	    modeling context can be modified.
> + * @use_current_ns: Status variable indicating which user namespace
> + *		    should be used for resolution of uid/gid values.
> + * @actions: An array of enum tsem_action_type variables indicating
> + *	     the type of response that should be returned in
> + *	     response to the modeling of a security event that
> + *	     is inconsistent with the model being used for the
> + *	     security context.
> + * @digestname: A pointer to a null-terminated buffer containing the
> + *		name of the digest function that is to be used for
> + *		this security context.
> + * @zero_digest: The digest value for a 'zero-length' digest value.
> + * @tfm: A pointer to the digest transformation structure that is to
> + *	 be used for this context.
> + * @magazine_size: The number of struct tsem_event structures that
> + *		   are held in reserve for security event hooks that
> + *		   are called in atomic context.
> + * @magazine_lock: The spinlock that protects access to the event
> + *		   magazine for the security context.
> + * @magazine_index: The bitmap that is used to track the magazine slots
> + *		    that have been allocated.
> + * @ws: An array of work structures that are used to refill the magazine
> + *	slots.
> + * @magazine: An array of pointers to struct tsem_event structures that
> + *	      are pre-allocated for security hooks called in atomic
> + *	      context.
> + * @model: If the modeling context is implemented with a kernel based
> + *	   trusted model agent this pointer will point to the struct
> + *	   tsem_model structure that maintains the state of the
> + *	   security model.
> + * @external: If the modeling context is implemented with an external
> + *	      modeling agent this pointer will point to the struct
> + *	      tsem_external structure that implements the interface to
> + *	      the external trusted modeling agent.
> +
> + * This structure is used to represent the state of a TSEM security
> + * modeling namespace.  A pointer to this structure is stored in the
> + * struct tsem_task structure.
> + *
> + * This structure is allocated by the tsem_ns_create() function in
> + * response to a TSEM control request.  This structure maintains all
> + * of the information that describes the security modeling namespace
> + * that is not specific to the type of namespace, ie. external or
> + * internal that is being implemented.
> +
> + * The id member is a 64-bit counter that cannot feasibly be
> + * overflowed and that is incremented for each namespace creation that
> + * is created.  The root modeling namespace has a value of zero so the
> + * TSEM code uses a pattern of testing this value for non-zero status
> + * as an indication of whether or not the task is running in a
> + * subordinate modeling namespace.
> +
> + * Each security modeling namespace can have an independent
> + * cryptographic digest function that is used as the compression
> + * function for generating the digest values that are used to model
> + * the security events that occur in a namespace.  A single struct tfm
> + * is allocated for this digest function at the time that the
> + * tsem_context structure is created and is maintained in this
> + * structure for subsequent use during event processing.
> +
> + * Each cryptographic digest function has a 'zero message' value that
> + * is the result of the initialization and closure of a hash function
> + * that has no other input.  This zero digest value is computed at the
> + * time of the creation of the array.  This digest value is returned
> + * for files with zero sizes or that have pseudonyms declared for
> + * them.
> + *
> + * The actions array contains a specification of how each security
> + * event should be handled in the event that the model detects a
> + * security event consistent with the model designated for the
> + * namespace.  This array allows the specification of whether the
> + * model should be enforcing or logging.  Currently the specification
> + * is all or nothing for all of the events, with plans to make the
> + * actions individually configurable.
> +
> + * Each security event that is processed requires a struct tsem_event
> + * structure that drives either the internal modeling of an event or
> + * its export to an external modeling agent.  Some security event
> + * hooks are called while a task is running in atomic context. Since
> + * memory cannot be allocated while a process is in atomic context, a
> + * magazine of these structures is maintained by this structure for
> + * security events that run in atomic context.  The size of this
> + * magazine is dynamic and is configurable for each security modeling
> + * namespace that is created.
> + *
> + * When a tsem_event structure is allocated for an atomic event a
> + * request for the refill of the slot that is vacated is dispatched to
> + * an asynchronous workqueue.  The ws member of this structure points
> + * to an array of work structures for this refill capability, one for
> + * each slot in the magazine.
> + *
> + * All of this infrastructure is generic for each security modeling
> + * namespace.  How the security modeling is done is governed by the
> + * model and external members of this structure.  These members point
> + * to data structures that either maintain the security model state
> + * for an in kernel trusted modeling agent or handle the export of the
> + * event to an external trusted modeling agent.
> + *
> + * Each task that is created in a non-root security modeling namespace
> + * increments the reference count maintained in the kref member of
> + * this structure in the tsem_task_alloc() function.  The
> + * tsem_task_free() function decrements this reference count.  When
> + * the reference count expires, ie. when the last task using the
> + * modeling namespace exits, an asynchronous workqueue request is
> + * dispatched to dispose of the context.  The work member of this
> + * structure is used to reference that workqueue request.
> + */
> +struct tsem_context {
> +	struct kref kref;
> +	struct work_struct work;
> +
> +	u64 id;
> +	bool sealed;
> +	bool use_current_ns;
> +
> +	enum tsem_action_type actions[TSEM_EVENT_CNT];
> +
> +	char *digestname;
> +	u8 zero_digest[HASH_MAX_DIGESTSIZE];
> +	struct crypto_shash *tfm;
> +
> +	unsigned int magazine_size;
> +	spinlock_t magazine_lock;
> +	unsigned long *magazine_index;
> +	struct tsem_work *ws;
> +	struct tsem_event **magazine;
> +
> +	struct tsem_model *model;
> +	struct tsem_external *external;
> +};

Odd use of whitespace in the structure definition.

> +
> +/**
> + * struct tsem_model - TSEM internal TMA description.
> + * @have_aggregate: Flag variable to indicate whether or not the
> + *		    hardware aggregate value has been injected into
> + *		    the mode.
> + * @base: The base value that is to be used in computing the
> + *	  measurement and state values of the model.
> + * @measurement: The time dependent linear extension state of the
> + *		 model.
> + * @state: The time independent linear extension state of the model.
> + * @point_lock: The spinlock that protects access to the list of
> + *		security state coefficients in the model.
> + * @point_list: A pointer to the list of security state coefficients
> + *		in the model.
> + * @point_end_mutex: The mutex that is used to protect the end of the
> + *		     list of security state coefficients for the
> + *		     model.
> + * @point_end: A pointer to the end of the list of security state
> + *	       coefficients that will be traversed by a call to the
> + *	       control plane.
> + * @trajectory_lock: The spinlock used to protect the list of security
> + *		     event descriptions in the model.
> + * @trajectory_list: A pointer to the list of descriptions of the
> + *		     security events that have been recorded in this
> + *		     model.
> + * @trajectory_end_mutex: The mutex that protects the end of the list
> + *			  of security event descriptions.
> + * @trajectory_end: A pointer to the end of the list of security event
> + *		    descriptions that will be traversed by a call to
> + *		    the control plane.
> + * @forensics_lock: The spinlock used to protect the list of security
> + *		    event descriptions that are considered invalid by
> + *		    the model being enforced.
> + * @forensics_list: A pointer to the list of descriptions of security
> + *		    events that are considered invalid by the security
> + *		    model being enforced.
> + * @forensics_end_mutex: The mutex that protects the end of the list
> + *			 of security event descriptions that are
> + *			 considered invalid by the current model.
> + * @forensics_end: A pointer to the end of the list of security event
> + *		   descriptions, that are considered invalid, that are
> + *		   to be traversed by a call to the control plane.
> + * @pseudonym_mutex: The mutex lock that protects the list of file
> + *		     digest pseudonyms for the current model.
> + * @pseudonum_list: A pointer to the list of file digest pseudonyms
> + *		    that have been declared for the current model.
> + * @magazine_size: The number of struct tsem_event_point structures that
> + *		   are held in reserve for security event hooks that
> + *		   are called in atomic context.
> + * @magazine_lock: The spinlock that protects access to the event
> + *		   magazine for the security context.
> + * @magazine_index: The bitmap that is used to track the magazine slots
> + *		    that have been allocated.
> + * @ws: An array of work structures that are used to refill the magazine
> + *	slots.
> + * @magazine: An array of pointers to struct tsem_event_point structures that
> + *	      are pre-allocated for security hooks called in atomic
> + *	      context.
> + *
> + * If a call to the tsem_ns_create() function specifies that a kernel
> + * based trusted modeling agent is to be used to implement the
> + * security namespace model, a pointer to this structure is placed in
> + * the struct tsem_context structure.  This structure is used to
> + * maintain the state of the kernel based model.
> + *
> + * There are two primary functional values that are maintained by the
> + * model.  The measurement member of this structure represents the
> + * time dependent linear extension sum of the security state
> + * coefficients that have been assigned to security events that have
> + * occurred in the context of the model.
> + *
> + * This classic integrity measurement is subject to scheduling
> + * dependencies and may be invariant from run to run of the model.  It
> + * is of primary use in verifying the order of security events that
> + * have occurred in the model.
> + *
> + * The state member of this structure represents a time independent
> + * linear extension sum of the security state coefficients that have
> + * been generated in the model.  It represents the linear extension
> + * sum of the security state coefficients that have been sorted in
> + * natural (big-endian) form.
> + *
> + * Both of these measurements are dependent on the platform hardware
> + * aggregate value and the base point that has been defined for the
> + * define.
> + *
> + * A non-zero hardware aggregate value is only available if the
> + * platform has a TPM.  The have_aggregate member of this structure is
> + * a flag variable that indicates whether or not the aggregate value
> + * has been injected into the model.
> + *
> + * The base member of this structure contains a model specific
> + * coefficient that is used to perturb each security state coefficient
> + * generated in the model.  This value is designed to serve as a
> + * 'freshness' value for a verifying party to the model.
> + *
> + * There are three primary model lists maintain by this structure:
> + *
> + * * security state points
> + * * security trajectory events
> + * * security forensics events
> + *
> + * Similar members are maintained in this structure to support each of
> + * these lists.
> + *
> + * All three lists are extension only and are protected by a spinlock
> + * that can be held in atomic context.  This spinlock is only held for
> + * the period of time required to extend the list.
> + *
> + * Calls by the control plane to interrogate the lists require the
> + * traversal of the list that is ill-suited for a spinlock.  As a
> + * result each list type has a mutex associated with it that protects
> + * a pointer to the end of the list, an endpoint that is determined at
> + * the start of a call to the control plane.
> + *
> + * The list spinlock is used at the start of the control plane call to
> + * capture the end of the list that is then protected by the mutex.
> + * In essence this is used to transition protection of the list from
> + * the spinlock to the mutex.
> + *
> + * The kernel based modeling agent has support for maintaining a
> + * constant digest value for files, that by function, do not have a
> + * fixed digest value, such as log files.  The pseudonym_list member
> + * of this structure points to the list of these designations.  The
> + * pseudonym_mutex structure protects this list.
> + *
> + * Like the struct tsem_context structure the tsem_model structure
> + * maintains a magazine of structures that are used to service
> + * security events that are called in atomic context.  The magazine
> + * maintained by this structure is a list of struct tsem_event_point
> + * structures that are used to describe the security state
> + * coefficients held by the model.
> + *
> + * The description of struct tsem_context details the implementation
> + * of the magazine which is identical to the implementation for this
> + * structure, with the exception of the type of structures that are
> + * held in reserve.
> + */
> +struct tsem_model {
> +	bool have_aggregate;
> +
> +	u8 base[HASH_MAX_DIGESTSIZE];
> +	u8 measurement[HASH_MAX_DIGESTSIZE];
> +	u8 state[HASH_MAX_DIGESTSIZE];
> +
> +	spinlock_t point_lock;
> +	struct list_head point_list;
> +	struct mutex point_end_mutex;
> +	unsigned int point_count;
> +	struct list_head *point_end;
> +
> +	spinlock_t trajectory_lock;
> +	struct list_head trajectory_list;
> +	struct mutex trajectory_end_mutex;
> +	struct list_head *trajectory_end;
> +
> +	spinlock_t forensics_lock;
> +	struct list_head forensics_list;
> +	struct mutex forensics_end_mutex;
> +	struct list_head *forensics_end;
> +
> +	struct mutex pseudonym_mutex;
> +	struct list_head pseudonym_list;
> +
> +	unsigned int magazine_size;
> +	spinlock_t magazine_lock;
> +	unsigned long *magazine_index;
> +	struct tsem_work *ws;
> +	struct tsem_event_point **magazine;
> +};
> +
> +/**
> + * struct tsem_external - TSEM external TMA description.
> + * @export_lock: The spinlock that protects access to the export_list
> + *		 member of this structure.
> + * @export_list: A pointer to the list of events waiting to be
> + *		 exported to the trust orchestrator for the security
> + *		 modeling namespace.  The structure type that is
> + *		 linked by this list is the struct export_event
> + *		 structure that is private to the export.c compilation
> + *		 unit.
> + * @dentry: A pointer to the dentry describing the pseudo-file in the
> + *	    /sys/kernel/security/tsem/ExternalTMA directory that is
> + *	    being used to export security event descriptions to the
> + *	    external trust orchestrator for the security modeling
> + *	    domain described by this structure.
> + * @have_event: A flag variable to indicate that there is work queued
> + *		on the export pseudo-file for the security modeling
> + *		namespace.
> + * @wq: The work queue used to implement polling for the security
> + *	event export file for the security modeling namespace.
> + * @magazine_size: The number of struct export_event structures that
> + *		   are held in reserve for security event hooks that
> + *		   are called in atomic context.
> + * @magazine_lock: The spinlock that protects access to the event
> + *		   magazine for the security modeling domain.
> + * @magazine_index: The bitmap that is used to track the magazine slots
> + *		    that have been allocated.
> + * @ws: An array of work structures that are used to refill the magazine
> + *	slots.
> + * @magazine: An array of pointers to struct export_event structures that
> + *	      are pre-allocated for security hooks called in atomic
> + *	      context.
> + *
> + * If an externally modeled security modeling namespace is created
> + * a structure of this type is allocated for the namespace and placed
> + * in the struct tsem_context structure.
> + *
> + * The primary purpose of this structure is to manage event
> + * descriptions that are being transmitted to the trust orchestrator
> + * associated with the security modeling namespace.  The pseudo-file
> + * will be as follows:
> + *
> + * /sys/kernel/security/tsem/ExternalTMA/N
> + *
> + * Where N is the context id number of the modeling namespace.
> + *
> + * The dentry member of this structure is used to represent the
> + * pseudo-file that is created when the external modeled namespace is
> + * created.
> + *
> + * This list of events waiting to be received by the trust
> + * orchestrator is maintained in the export_list member of this
> + * structure.  Additions or removals from the list hold the spinlock
> + * described by the export_lock member of this structure.
> + *
> + * The wq member of this structure is used to implement a workqueue
> + * to support polling for events on the export control file.  The
> + * have_event flag is set to indicate to the polling call that
> + * security events are available for export.
> + *
> + * When a security event description is exported the calling task is
> + * scheduled away to allow the trust orchestrator to process the
> + * event.  This obviously creates issues for security events that are
> + * called in atomic context.
> + *
> + * Security events in atomic context are exported as an async_event
> + * rather than a simple event.  The trust orchestrator has the option
> + * of killing the workload that deviated from the security model or
> + * signaling a violation of the model.
> + *
> + * To support the export of asynchronous events a magazine, similar to
> + * the event and model structure magazines, is maintained by this
> + * structure for the external modeling namespace.
> + */
> +struct tsem_external {
> +	spinlock_t export_lock;
> +	struct list_head export_list;
> +	struct dentry *dentry;
> +	bool have_event;
> +	wait_queue_head_t wq;
> +
> +	unsigned int magazine_size;
> +	spinlock_t magazine_lock;
> +	unsigned long *magazine_index;
> +	struct tsem_work *ws;
> +	struct export_event **magazine;
> +};
> +
> +/**
> + * struct tsem_work - TSEM magazine refill work structure.
> + * @index: The index number of the slot in the structure magazine that
> + *	   is being refilled.
> + * @u: A union that holds pointers to the structure whose magazine is
> + *     being refilled.
> + * @work: The work structure that manages the workqueue being used to
> + *	  refill the magazine entry.
> + *
> + * As has been previously documented for the struct tsem_context,
> + * struct tsem_model and struct tsem_external structures, there is a
> + * need to maintain a magazine of these structures in order to allow
> + * the processing of security events that are called in atomic
> + * context.  An array of this structure type is embedded in each of
> + * these structures to manage the asynchronous refill of the slot in
> + * the magazine that was used to handle an atomic security event.
> + *
> + * The index member of this structure points to the slot in the
> + * magazine that this work item is referencing.
> + *
> + * The structure that the refill work is being done for is maintained
> + * in the respective structure pointer in the u member of this
> + * structure.
> + *
> + * The work member of this structure is used to reference the
> + * asynchronous work request that is being submitted for the refill.
> + */
> +struct tsem_work {
> +	unsigned int index;
> +	union {
> +		struct tsem_context *ctx;
> +		struct tsem_model *model;
> +		struct tsem_external *ext;
> +	} u;
> +	struct work_struct work;
> +};
> +
> +/**
> + * struct tsem_COE - TSEM context of execution definition structure.
> + * @uid: The numeric user identity that the COE is running with.
> + * @euid: The effective user identity that the COE is running with.
> + * @suid: The saved user identity possessed by the COE.
> + * @gid: The group identity that the COE is running with.
> + * @egid: The effective group identity that the COE possesses.
> + * @sgid: The saved group identity of the COE.
> + * @fsuid: The filesystem user identity that the COE is running with.
> + * @fsgid: The filesystem group identity that the COE is running with.
> + * @capeff: This union is used to implement access to the effective
> + *	    capability set the COE is running with.  The mask value
> + *	    is used to assign to the structure with the value member
> + *	    used to extract the 64 bit value for export and
> + *	    computation.
> + *
> + * A security state coefficient is computed from two primary entities:
> + * the COE and the CELL identities.  This structure is used to carry
> + * and encapsulate the characteristics of the context of execution
> + * (COE) that will be used to generate the COE identity.
> + *
> + * The numeric values for discretionary access controls, ie. uid, gid,
> + * are determined by which user namespace the security modeling
> + * namespace is configured to reference.  The reference will be either
> + * the initial user namespace or the user namespace that the context
> + * of execution is running in.
> + */
> +struct tsem_COE {
> +	uid_t uid;
> +	uid_t euid;
> +	uid_t suid;
> +
> +	gid_t gid;
> +	gid_t egid;
> +	gid_t sgid;
> +
> +	uid_t fsuid;
> +	gid_t fsgid;
> +
> +	union {
> +		kernel_cap_t mask;
> +		u64 value;
> +	} capeff;
> +};
> +
> +/**
> + * struct tsem_COE - TSEM file description.
> + * @uid: The numeric user identity of the file.
> + * @gid: The numeric group identity of the file.
> + * @mode: The discretionary access mode for the file.
> + * @flags: The file control flags.
> + * @name_length: The length of the pathname of the file.
> + * @name: The digest value of the pathname of the file using the
> + *	  hash function defined for the security modeling namespace.
> + * @s_magic: The magic number of the filesystem that the file resides
> + *	     in.
> + * @s_id: The name of the block device supporting the filesystem.
> + * @s_uuid: The uuid of the filesystem that the file resides in.
> + * @digest: The digest value of the contents of the file using the
> + *	    hash function defined for the security modeling namespace.
> + *
> + * This structure and the structures that follow up to the struct
> + * tsem_event structure are used to identify the various entities that
> + * are involved in the definition of the CELL identity for a security
> + * event.
> + *
> + * The tsem_file structure is used to encapsulate the characteristics
> + * of a file that is used as an entity in the CELL definition of an
> + * event.
> + *
> + * Since a pathname can be up to PATH_MAX (4096 bytes) in length the
> + * cryptographic digest value is used rather than the pathname of the
> + * file itself.
> + */
> +struct tsem_file {
> +	uid_t uid;
> +	gid_t gid;
> +	umode_t mode;
> +	u32 flags;
> +
> +	u32 name_length;
> +	u8 name[HASH_MAX_DIGESTSIZE];
> +
> +	u32 s_magic;
> +	u8 s_id[32];
> +	u8 s_uuid[16];
> +
> +	u8 digest[HASH_MAX_DIGESTSIZE];
> +};
> +
> +/**
> + * struct tsem_COE - TSEM memory mapped file characteristics.
> + * @file: The struct file definition for the file that is being
> + *	  mapped.  This pointer will be null in the case of an
> + *	  anonymous mapping.
> + * @anonymous: A flag variable to indicate whether or not the mapping
> + *	       is file backed or anonymous.
> + * @reqprot: The memory protection flags that are requested by the
> + *	     memory mapping system call.
> + * @prot: The protections that will be applied to the mapping.
> + * @flags: The control flags of the memory mapping call.
> + *
> + * This structure is used to encapsulate the arguments provided to the
> + * tsem_mmap_file security event handler.
> + */
> +struct tsem_mmap_file_args {
> +	struct file *file;
> +	u32 anonymous;
> +	u32 reqprot;
> +	u32 prot;
> +	u32 flags;
> +};
> +
> +/**
> + * struct tsem_socket_create_args - TSEM socket creation arguments.
> + * @family: The family name of the socket whose creation is being
> + *	    requested.
> + * @type: The type of the socket being created.
> + * @protocol: The protocol family of the socket being created.
> + * @kern: A flag variable to indicate whether or not the socket being
> + *	  created is kernel or userspace based.
> + *
> + * This structure is used to encapsulate the arguments provided to the
> + * tsem_socket_create security event handler.
> + */
> +struct tsem_socket_create_args {
> +	int family;
> +	int type;
> +	int protocol;
> +	int kern;
> +};
> +
> +/**
> + * struct tsem_socket_connection_args - TSEM socket connection arguments.
> + * @tsip: A pointer to the struct tsem_inode structure that describes
> + *	  the TSEM inode characteristics of the inode representing
> + *	  the socket.
> + * @addr: A pointer to the structure describing the socket address
> + *	  that is being connected.
> + * @addr_len: The length of the socket address description structure.
> + * @family: The family number of the socket.
> + *
> + * @protocol: The protocol family of the socket being created.
> + * @kern: A flag variable to indicate whether or not the socket being
> + *	  created is kernel or userspace based.
> + * @u: A union that is used to hold the family specific address
> + *     characteristics of the socket connection.
> + * @u.ipv4: If the connection is IPV4 based this structure will be
> + *	    populated with the IPV4 address information.
> + * @u.ipv6: If the connection is IPV6 based this structure will be
> + *	    populated with the IPV6 address information.
> + * @u.path: If the socket connection is an AF_UNIX based socket
> + *	    address this buffer will contain the pathname of the
> + *	    socket address.
> + * @u.mapping: If the socket represents an address protocol other
> + *	       than IPV4, IPV6 or UNIX domain this buffer will contain
> + *	       the cryptographic value of the socket address
> + *	       information using the hash function that has been
> + *	       specified for the security modeling namespace.
> + *
> + * This structure is used to encapsulate the arguments provided to the
> + * tsem_socket_create security event handler.
> + */
> +struct tsem_socket_connect_args {
> +	struct tsem_inode *tsip;
> +	struct sockaddr *addr;
> +	int addr_len;
> +	u16 family;
> +	union {
> +		struct sockaddr_in ipv4;
> +		struct sockaddr_in6 ipv6;
> +		char path[UNIX_PATH_MAX + 1];
> +		u8 mapping[HASH_MAX_DIGESTSIZE];
> +	} u;
> +};
> +
> +/**
> + * struct tsem_socket_accept_args - TSEM socket accept parameters.
> + * @family: The socket family identifier for the connection being
> + *	    accepted.
> + * @type: The type of socket connection being accepted.
> + * @port: The port number of the connection being accepted.
> + * @ipv4: The IPV4 address of the connection being accepted if the
> + *	  socket is representing an IPV4 connection
> + * @ipv6: The IPV6 address of the connection being accepted if the
> + *	  socket is representing an IPV6 connection.
> + * @af_unix: The UNIX domain socket address if the socket is
> + *	     representing a UNIX domain connection.
> + * @path: The pathname of the UNIX domain socket.
> + * @mapping: A cryptographic hash of description of the socket
> + *	     connection being accepted if the socket is representing
> + *	     a connection other than an IPV4, IPV6 or UNIX domain
> + *	     socket.
> + *
> + * This structure is used to encapsulate the arguments provided to the
> + * tsem_socket_accept security event handler.
> + */
> +struct tsem_socket_accept_args {
> +	u16 family;
> +	u16 type;
> +	__be16 port;
> +	union {
> +		__be32 ipv4;
> +		struct in6_addr ipv6;
> +		struct unix_sock *af_unix;
> +		char path[UNIX_PATH_MAX + 1];
> +		u8 mapping[HASH_MAX_DIGESTSIZE];
> +	} u;
> +};
> +
> +/**
> + * struct tsem_task_kill_args - TSEM task kill arguments.
> + * @cross_model: A flag variable used to indicate whether or not the
> + *		 signal is originating from a security modeling
> + *		 namespace other than the namespace of the target process.
> + * @signal: The number of the signal being sent.
> + * @source: The task identifier of the process sending the signal
> + * @target: The task identifier of the target process.
> + *
> + * This structure is used to encapsulate the arguments provided to the
> + * tsem_task_kill security event handler.
> + */
> +struct tsem_task_kill_args {
> +	u32 cross_model;
> +	u32 signal;
> +	u8 source[HASH_MAX_DIGESTSIZE];
> +	u8 target[HASH_MAX_DIGESTSIZE];
> +};
> +
> +/**
> + * struct tsem_event - TSEM security event description.
> + * @index: The index number of the slot in the structure magazine that
> + *	   is being refilled.
> + * @u: A union that holds pointers to the structure whose magazine is
> + *     being refilled.
> + * @work: The work structure that manages the workqueue being used to
> + *	  refill the magazine entry.
> + * @event: The enumeration type describing the security event that the
> + *	   structure is defining.
> + * @locked: A boolean flag used to indicate whether or not the
> + *	    security event is running in atomic context.
> + * @pid: The process id number, in the global pid namespace, of the
> + *	 task that is requesting approval for a security event.
> + * @pathname: If the event is referencing a file this pointer will
> + *	      point to a null-terminated buffer containing the
> + *	      pathname to the file in the mount namespace that the
> + *	      process is running in.
> + * @comm: A pointer to a null terminated buffer containing the name of
> + *	  the process that is requesting the security event.
> + * @digestsize: The size in bytes of the cryptographic hash function
> + *		that is being used in the namespace in which the event
> + *		is being recorded.
> + * @task_id: The TSEM task identifier of the process that generated the
> + *	     security event described by an instance of this
> + *	     structure.
> + * @mapping: The security state coefficient that the event described
> + *	     by this structure generates.
> + * @COE: The struct tsem_COE structure that describes the Context Of
> + *	 Execution that generated the event described by this
> + *	 structure.
> + * @file: If the security event references a file this structure will
> + *	  contain the struct tsem_file structure that describes the
> + *	  characteristics of the file.
> + * @CELL: The CELL union is used to hold the data structures that
> + *	  characterize the CELL identity of the event.
> + * @CELL.event_type: In the case of a generically modeled event this
> + *		     member will contain the enumeration value
> + *		     identifying the event.
> + * @CELL.mmap_file: The structure describing the characteristics of
> + *		    a mmap_file security event.
> + * @CELL.socket_create: The structure describing the characteristics
> + *			of a socket_create security event.
> + * @CELL.socket_connect: The structure describing the characteristics
> + *			 of a socket_connect security event.
> + * @CELL.socket_accept: The structure describing the characteristics
> + *			of a socket accept security event.
> + * @CELL.task_kill: The structure describing the characteristics of a
> + *		    task_kill security event.
> + *
> + * This structure is the primary data structure for describing
> + * security events that are registered in a security modeling
> + * namespace.  Each unique security coefficient in the namespace will
> + * have one of these structures attached to it.
> + *
> + * This structure encapsulates the following three major sources of
> + * information about the event:
> + *
> + * * A description of the process initiating the event.
> + * * The characteristics that form the COE identity of the event.
> + * * The characteristics that form the CELL identity of the event.
> + *
> + * Since one event description has to ultimately characterize any
> + * security event that can occur the strategy is to use a union that
> + * contains security event specific structures that describe the
> + * characteristics of the event.
> + *
> + * The kref member of this structure is used to signal when the
> + * structure is to be deleted.  For example, in the case of an
> + * externally modeled event, when the export of the event description
> + * is complete.  In the case of an internally modeled namespace the
> + * structure will be released if it represents a security state
> + * coefficient that is already present in the model.
> + *
> + * The work member of this structure is used to support asynchronous
> + * updates to a TPM for the root modeling domain.  Asynchronous
> + * updates are used to improve the performance of modeling and to
> + * handle security events that are running in atomic context and
> + * cannot be scheduled away while the TPM transaction completes.
> + *
> + * The tsem_event_allocate() function is called by a TSEM security
> + * event handler to allocate and populate this structure.  The struct
> + * tsem_event_parameters structure is used to encapsulate all of the
> + * different structure types that are needed to characterize all of
> + * the different security events that occur.
> + *
> + * The tsem_event_allocate() function is called by either the
> + * tsem_map_event() or tsem_map_event_locked() functions.  After
> + * allocating and populating an event description structure the
> + * mapping functions generate a security state coefficient from the
> + * information in this structure.
> + *
> + * The two separate function call points for mapping are to allow the
> + * security event handlers to indicate the context in which the
> + * security event is occurring, ie. sleeping or atomic context.  After
> + * this point the context of the security event is represented by the
> + * locked member of this structure.
> + *
> + * After the event is mapped this structure is either passed to the
> + * internal trusted modeling agent or the contents of this structure
> + * is exported to the trust orchestrator attached to the namespace for
> + * modeling by an external trust modeling agent.
> + */
> +struct tsem_event {
> +	struct kref kref;
> +	struct list_head list;
> +	struct work_struct work;
> +
> +	enum tsem_event_type event;
> +	bool locked;
> +	pid_t pid;
> +	char *pathname;
> +	char comm[TASK_COMM_LEN];
> +
> +	unsigned int digestsize;
> +	u8 task_id[HASH_MAX_DIGESTSIZE];
> +	u8 mapping[HASH_MAX_DIGESTSIZE];
> +
> +	struct tsem_COE COE;
> +	struct tsem_file file;
> +
> +	union {
> +		u32 event_type;
> +		struct tsem_mmap_file_args mmap_file;
> +		struct tsem_socket_create_args socket_create;
> +		struct tsem_socket_connect_args socket_connect;
> +		struct tsem_socket_accept_args socket_accept;
> +		struct tsem_task_kill_args task_kill;
> +	} CELL;
> +};
> +
> +/**
> + * struct tsem_event_parameters - Security event argument descriptions
> + * @u: A union that encapsulates all of the different structures that
> + *     are used to characterize the argument so the TSEM security
> + *     event handlers.
> + * @u.event_type: This structure member holds the enum tsem_event_type
> + *		  enumeration value of the event whose characteristics
> + *		  are encapsulated in the function.
> + * @u.file: If the security event references a VFS file this member
> + *	    hold a pointer to the description of the file.
> + _file event.
> + * @u.socket_create: This member will point to a structure that
> + *		     describes the characteristics of a socket_create
> + *		     event.
> + * @u.socket_connect: This member will point to a structure that
> + *		      describes the characteristics of a socket_connect
> + *		      event.
> + * @u.socket_accept: This member will point to a structure that
> + *		     describes the characteristics of a socket_accept
> + *		     event.
> + * @u.task_kill: This member will point to a structure that describes
> + *		     the characteristics of a task_kill function.
> + *
> + * The purpose of this structure is to provide a common encapsulation
> + * method for passing the CELL characteristics of a security event
> + * into the tsem_event_init() function.  The characteristics passed in
> + * this event will be used to create and populate the struct
> + * tsem_event structure that will go on to be used to characterize
> + * the event either an internal or external modeling agent.
> + *
> + * The strategy followed is to allocate one of these structures on the
> + * stack for a security event call along with a call specific
> + * characteristics description structure, both of which will no longer
> + * be needed after completion of the call since the requisite
> + * information has been transferred to a struct tsem_event structure.
> + */
> +struct tsem_event_parameters {
> +	union {
> +		u32 event_type;
> +		struct file *file;
> +		struct tsem_mmap_file_args *mmap_file;
> +		struct tsem_socket_create_args *socket_create;
> +		struct tsem_socket_connect_args *socket_connect;
> +		struct tsem_socket_accept_args *socket_accept;
> +		struct tsem_task_kill_args *task_kill;
> +	} u;
> +};
> +
> +/**
> + * struct tsem_event_point - TSEM security coefficient characteristics.
> + * @list: The list structure used to link together all of the security
> + *	  state coefficients for a modeling namespace.
> + * @valid: A boolean value use to indicate whether or not the security
> + *	   state point is a valid coefficient in the model.
> + * @count: The number of times this coefficient has been expressed by
> + *	   security model for the namespace.
> + * @point: The security state coefficient for the point created by
> + *	   the cryptographic hash function being used for the modeling
> + *	   namespace.
> + *
> + * This structure is used by internal trusted modeling agents to
> + * represent each unique state point in a security model.  Security
> + * state coefficients are unique within a model so only one struct
> + * tsem_event_point structure will be generated regardless of how many
> + * times the security event that generates the point occurs.  The
> + * count member of this structure represents the total number of
> + * security events that have occurred that have generated the point.
> + *
> + * The valid member of this structure is used to flag whether this
> + * is consistent with the model for the namespace or was generated by
> + * a 'forensic', ie. out of model, event.
> + *
> + * Within each security namespace these structures are linked together
> + * in a list that describes the functional value of the security model
> + * assigned to the namespace.  Entries are only added to this list and
> + * never removed.
> + *
> + * The desired state of a security model is created by using the TSEM
> + * control plane to inject a list of acceptable security state
> + * coefficients into the model.  Sealing a model causes any security
> + * events that produce a coefficient different from those already in
> + * the model to be rejected as an invalid security event and logged as
> + * a forensic event for the model.
> + */
> +struct tsem_event_point {
> +	struct list_head list;
> +	bool valid;
> +	u64 count;
> +	u8 point[HASH_MAX_DIGESTSIZE];
> +};
> +
> +/**
> + * struct tsem_inode - TSEM inode status structure.
> + * @mutex: The mutex that will protect the list of struct
> + *	   tsem_inode_digest structures that have been created for the
> + *	   inode containing a struct tsem_inode structure.
> + * @list: The list structure that points to the list of struct
> + *	  tsem_inode_structures.
> + * @status: The digest collection state of the inode.  See the
> + *	    discussion of enum tsem_inode_state for what information
> + *	    is conveyed by the value of this structure member.
> +
> + * This structure is the second of the two primary control structures
> + * that are implemented through the LSM blob functionality.  It is
> + * automatically created when the inode structure is created for
> + * system resources that are referenced by a struct inode structure.
> + *
> + * This structure has two primary purposes.  The status member is used
> + * to signal that the tsem_file_open() function should return that
> + * permission to access the file is returned when the security hook is
> + * invoked by the integrity_kernel_read() function.  See the
> + * discussion on enum tsem_inode_state to more details.
> + *
> + * The second purpose of this structure is to maintain a list of
> + * digest values that have been computed by the inode that this
> + * structure references.  Maintenance of multiple digest values is
> + * required since there is no concept of a fixed digest function for
> + * TSEM as each modeling namespace can have its own digest function.
> + *
> + * Each digest value in use has a struct tsem_inode_digest structure
> + * allocated for it.  The digest_list member of this structure points
> + * to a list of these structures.
> + *
> + * The mutex implemented in this structure should be held by any
> + * process that is accessing the list.
> + */
> +struct tsem_inode {
> +	struct mutex mutex;
> +	struct list_head digest_list;
> +	enum tsem_inode_state status;
> +};
> +
> +/**
> + * struct tsem_inode_digest - Digest specific file checksum.
> + * @list:	The list structure used to link multiple digest values
> + *		for an inode.
> + * @version:	The version number of the inode that generated the digest
> + *		value that is currently represented.
> + * @name:	A pointer to a null-terminated character buffer containing
> + *		the name of the hash function that generated the current
> + *		digest value.
> + * @value:	The digest value of the file.
> + *
> + * A linked list of these structures is maintained for each inode that
> + * is modeled by TSEM and is used to support multiple hash specific
> + * digest values for a file represented by the inode.  The tsem_inode
> + * structure that represents the TSEM security status of the inode
> + * contains the pointer to this list of structures.
> + *
> + * The version member of the structure contains the inode version number
> + * that was in effect when the last digest value of this type was computed.
> + * This version number value is used to detect changes and to trigger an
> + * update of the digest value.
> + *
> + * The name member of structure contains the name of the hash function
> + * that generated the checksum value.  This name is used to locate the
> + * correct structure by comparing its value against the hash function
> + * that is being used for the modeling domain that is accessing the
> + * inode.
> + */
> +struct tsem_inode_digest {
> +	struct list_head list;
> +	char *name;
> +	u64 version;
> +	u8 value[HASH_MAX_DIGESTSIZE];
> +};
> +
> +/*
> + * The following three variables are the only globally visible
> + * variables used in the TSEM implementation.
> + *
> + * The tsem_blob_sizes variable is used by the LSM infrastructure to
> + * describe the amount of space that will be needed by the struct
> + * tsem_task and struct tsem_inode structures.
> + *
> + * The tsem_names array is defined in the tsem.c file and contains an
> + * array of pointers to the strings that define the names for each of
> + * the TSEM security event handles.  The enum tsem_event_type
> + * enumeration indexes this array.
> + *
> + * The tsem_root_actions array is also indexed by the enum
> + * tsem_event_type enumeration and is used to determine the type of
> + * response that a TSEM security event handler is to return to the
> + * caller, ie. either logging or enforcing.  The contents of this
> + * array is inherited by copying the array into the struct
> + * tsem_context structure for modeling namespaces that are subordinate
> + * to the root model.
> + */
> +extern struct lsm_blob_sizes tsem_blob_sizes;
> +extern const char * const tsem_names[TSEM_EVENT_CNT];
> +extern enum tsem_action_type tsem_root_actions[TSEM_EVENT_CNT];
> +
> +/*
> + * The following section of the file contains the definitions for the
> + * externally visible functions in each of the TSEM compilation units.
> + */
> +extern struct dentry *tsem_fs_create_external(const char *name);
> +extern void tsem_fs_show_trajectory(struct seq_file *c, struct tsem_event *ep);
> +extern void tsem_fs_show_field(struct seq_file *c, const char *field);
> +extern void tsem_fs_show_key(struct seq_file *c, char *term, char *key,
> +			     char *fmt, ...);
> +extern int tsem_fs_init(void);
> +
> +extern struct tsem_model *tsem_model_allocate(size_t size);
> +extern void tsem_model_free(struct tsem_context *ctx);
> +extern int tsem_model_event(struct tsem_event *ep);
> +extern int tsem_model_load_point(u8 *point);
> +extern int tsem_model_load_pseudonym(u8 *mapping);
> +extern int tsem_model_has_pseudonym(struct tsem_inode *tsip,
> +				    struct tsem_file *ep);
> +extern void tsem_model_load_base(u8 *mapping);
> +extern int tsem_model_add_aggregate(void);
> +extern void tsem_model_compute_state(void);
> +extern void tsem_model_magazine_free(struct tsem_model *model);
> +extern int tsem_model_cache_init(struct tsem_model *model, size_t size);
> +
> +extern void tsem_ns_put(struct tsem_context *ctx);
> +extern int tsem_ns_event_key(u8 *task_key, const char *keystr, u8 *key);
> +extern int tsem_ns_create(const enum tsem_control_type type,
> +			  const char *digest, const enum tsem_ns_reference ns,
> +			  const char *key, const unsigned int cache_size);
> +
> +extern int tsem_export_show(struct seq_file *m, void *v);
> +extern int tsem_export_event(struct tsem_event *ep);
> +extern int tsem_export_action(enum tsem_event_type event, bool locked);
> +extern int tsem_export_aggregate(void);
> +extern int tsem_export_magazine_allocate(struct tsem_external *ext,
> +					 size_t size);
> +extern void tsem_export_magazine_free(struct tsem_external *ext);
> +extern int tsem_export_cache_init(void);
> +
> +extern int tsem_map_task(struct file *file, u8 *mapping);
> +struct tsem_event *tsem_map_event(enum tsem_event_type event,
> +				  struct tsem_event_parameters *param);
> +struct tsem_event *tsem_map_event_locked(enum tsem_event_type event,
> +					 struct tsem_event_parameters *param);
> +
> +extern struct tsem_event *tsem_event_allocate(bool locked);
> +extern struct tsem_event *tsem_event_init(enum tsem_event_type event,
> +					  struct tsem_event_parameters *params,
> +					  bool locked);
> +extern void tsem_event_put(struct tsem_event *ep);
> +extern void tsem_event_get(struct tsem_event *ep);
> +extern int tsem_event_magazine_allocate(struct tsem_context *ctx, size_t size);
> +extern void tsem_event_magazine_free(struct tsem_context *ctx);
> +extern int tsem_event_cache_init(void);
> +
> +extern u8 *tsem_trust_aggregate(void);
> +extern int tsem_trust_add_event(struct tsem_event *ep);
> +
> +/*
> + * The remaining inline function declarations follow the design
> + * pattern of the other LSM's and implement functions that return
> + * various TSEM characteristics of tasks, modeling contexts and
> + * inodes.
> + */
> +static inline struct tsem_task *tsem_task(struct task_struct *task)
> +{
> +	return task->security + tsem_blob_sizes.lbs_task;
> +}
> +
> +static inline bool tsem_task_trusted(struct task_struct *task)
> +{
> +	return tsem_task(task)->trust_status & TSEM_TASK_TRUSTED;
> +}
> +
> +static inline bool tsem_task_untrusted(struct task_struct *task)
> +{
> +	return tsem_task(task)->trust_status & ~TSEM_TASK_TRUSTED;
> +}
> +
> +static inline struct tsem_context *tsem_context(struct task_struct *task)
> +{
> +	return tsem_task(task)->context;
> +}
> +
> +static inline struct tsem_model *tsem_model(struct task_struct *task)
> +{
> +	return tsem_task(task)->context->model;
> +}
> +
> +static inline struct tsem_inode *tsem_inode(struct inode *inode)
> +{
> +	return inode->i_security + tsem_blob_sizes.lbs_inode;
> +}
> +
> +static inline struct crypto_shash *tsem_digest(void)
> +{
> +	return tsem_context(current)->tfm;
> +}
> +
> +static inline unsigned int tsem_digestsize(void)
> +{
> +	return crypto_shash_digestsize(tsem_digest());
> +}
Dr. Greg Aug. 10, 2023, 2:57 a.m. UTC | #2
On Mon, Aug 07, 2023 at 01:39:22PM -0700, Casey Schaufler wrote:

Hi Casey, thank you for the review comments.

> On 7/10/2023 3:23 AM, Dr. Greg wrote:
> > TSEM is designed, from a functional perspective, to be contained
> > entirely in its own directory.
> >
> > The tsem.h header file defines the enumeration types, structure
> > definitions and externally visiable functions that are referenced
> > by all of the compilation units of the TSEM LSM implementation in
> > that directory.

> Extensive documentation notwithstanding, it's impossible to review
> the data structures and constants without the code that goes along
> with them.

Big picture, I couldn't resist passing along an actual quote from my
mentor in Computer Science and modeling theory.  An algebraic
topologist by training who had Robert Ellis once briefly convinced
that it could be proven that it was possible to comb the hair on a
coconut, who also did significant work in data structures:

	"If one carefully studies and understands the data structures
	acted upon, including a description of their character, role
	and importance; the code itself, upon simple examination,
	will speak clearly, eloquently and stridently with respect to
	its intent and purpose for existence."

:-)

We approached the patch series from the perspective of tsem.h being a
reference document for the compilation units.

The rules are pretty simple.  Any structure, variable or function with
a tsem_ prefix, in some form of appropriate capitalization, can be
found quickly in tsem.h, along with what we hope is a complete
description on how and why the entity is implemented.

We were somewhat influenced by SMACK that uses a single include file
for its globally visible state.

Other LSM's seem to use multiple include files, is that a preferred
approach?

The tsem_event structure is the poster child of the challenges
associated with the latter model.  It gets used by all eight compilation
units so its declaration is going to be isolated from its use in most
cases.

This model seems to inevitably come down to something like 'common.h'
which puts you sort of back to where things started.

We may have missed it but I don't see anything in the kernel
developers guide with respect best practices for introducing blocks of
entire sub-system code.

Recommendations welcome.

> > The structure and enumeration types are extensively documented
> > and are the recommended starting point for understanding TSEM
> > implementation and functionality.
> >
> > Signed-off-by: Greg Wettstein <greg@enjellic.com>
> > ---
> >  security/tsem/tsem.h | 1516 ++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 1516 insertions(+)
> >  create mode 100644 security/tsem/tsem.h
> >
> > diff --git a/security/tsem/tsem.h b/security/tsem/tsem.h
> > new file mode 100644
> > index 000000000000..03915f47529b
> > --- /dev/null
> > +++ b/security/tsem/tsem.h
> > @@ -0,0 +1,1516 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +
> > +/*
> > + * Copyright (C) 2023 Enjellic Systems Development, LLC
> > + * Author: Dr. Greg Wettstein <greg@enjellic.com>
> > + *
> > + * This is the single include file that documents all of the externally
> > + * visible types and functions that are used by TSEM.  This file is
> > + * currently organized into four major sections in the following order;
> > + *
> > + * includes used by all compilation units
> > + * CPP definitions
> > + * enumeration types
> > + * structure definitions
> > + * function declarations
> > + * inline encapsulation functions.
> > + *
> > + * Include files that are referenced by more than a single compilation
> > + * should be included in this file.  Includes that are needed to
> > + * satisfy compilation requirements for only a single file should be
> > + * included in the file needing that include.
> > + *
> > + * Understanding the overall implementation and architecture of TSEM
> > + * will be facilitated by reviewing the documentation in this file.
> > + */
> > +
> > +#include <uapi/linux/in.h>
> > +#include <uapi/linux/in6.h>
> > +#include <linux/wait.h>
> > +#include <linux/kref.h>
> > +#include <linux/lsm_hooks.h>
> > +#include <linux/capability.h>
> > +#include <crypto/hash.h>
> > +#include <crypto/hash_info.h>
> > +#include <net/af_unix.h>
> > +
> > +/* The capability needed to manage TSEM. */
> > +#define TSEM_CONTROL_CAPABILITY CAP_ML

> Why would you do this? You gave the capability a name that even you
> don't want to use.

A simple placeholder that allows the capability used to control
security modeling to be set in one place, and one place only, until
the debate over the capability issue is settled.

We never envisioned this define lasting beyond the initial reviews.

> > +
> > +/*
> > + * The number of 'slots' in the structure magazines that are used to
> > + * satisfy modeling of security events that are called in atomic context.
> > + */
> > +#define TSEM_ROOT_MAGAZINE_SIZE	96
> > +#define TSEM_MAGAZINE_SIZE_INTERNAL 16
> > +#define TSEM_MAGAZINE_SIZE_EXTERNAL 96
> > +
> > +/**
> > + * enum tsem_event_type - Ordinal value for a security event.
> > + * @TSEM_BPRM_SET_CREDS: Ordinal value for bprm_creds_for_exec.
> > + * @TSEM_GENERIC_EVENT: Ordinal value for a generically modeled event.
> > + * @TSEM_TASK_KILL: Ordinal value for task kill.
> > + * @....: Remainder follows with a similar naming format that has
> > + *        TSEM_ prep ended to the raw LSM security hook name.
> > + * @TSEM_EVENT_CNT: The final ordinal value is used to define the
> > + *		    length of the following arrays that are indexed
> > + *		    by the ordinal value of the hook:
> > + *
> > + * This enumeration is used to designate an ordinal value for each
> > + * security event, ie. LSM hook, that TSEM is implementing modeling
> > + * for.  This value is used to identify the hook that is either having
> > + * its event description being exported to an external Trusted Modeling
> > + * Agent (TMA) or modeled by the internal TMA implementation.
> > + *
> > + * The primary use of this enumeration is to conditionalize code paths
> > + * based on the security hook being processed and to index the
> > + * tsem_names array and the array that defines the action that is to
> > + * be taken in response to an event that generates a permissions
> > + * violation.
> > + */
> > +enum tsem_event_type {
> > +	TSEM_BPRM_SET_CREDS = 1,
> > +	TSEM_GENERIC_EVENT,
> > +	TSEM_TASK_KILL,
> > +	TSEM_TASK_SETPGID,
> > +	TSEM_TASK_GETPGID,
> > +	TSEM_TASK_GETSID,
> > +	TSEM_TASK_SETNICE,
> > +	TSEM_TASK_SETIOPRIO,
> > +	TSEM_TASK_GETIOPRIO,
> > +	TSEM_TASK_PRLIMIT,
> > +	TSEM_TASK_SETRLIMIT,
> > +	TSEM_TASK_SETSCHEDULER,
> > +	TSEM_TASK_GETSCHEDULER,
> > +	TSEM_TASK_PRCTL,
> > +	TSEM_FILE_OPEN,
> > +	TSEM_MMAP_FILE,
> > +	TSEM_FILE_IOCTL,
> > +	TSEM_FILE_LOCK,
> > +	TSEM_FILE_FCNTL,
> > +	TSEM_FILE_RECEIVE,
> > +	TSEM_UNIX_STREAM_CONNECT,
> > +	TSEM_UNIX_MAY_SEND,
> > +	TSEM_SOCKET_CREATE,
> > +	TSEM_SOCKET_CONNECT,
> > +	TSEM_SOCKET_BIND,
> > +	TSEM_SOCKET_ACCEPT,
> > +	TSEM_SOCKET_LISTEN,
> > +	TSEM_SOCKET_SOCKETPAIR,
> > +	TSEM_SOCKET_SENDMSG,
> > +	TSEM_SOCKET_RECVMSG,
> > +	TSEM_SOCKET_GETSOCKNAME,
> > +	TSEM_SOCKET_GETPEERNAME,
> > +	TSEM_SOCKET_SETSOCKOPT,
> > +	TSEM_SOCKET_SHUTDOWN,
> > +	TSEM_PTRACE_TRACEME,
> > +	TSEM_KERNEL_MODULE_REQUEST,
> > +	TSEM_KERNEL_LOAD_DATA,
> > +	TSEM_KERNEL_READ_FILE,
> > +	TSEM_SB_MOUNT,
> > +	TSEM_SB_UMOUNT,
> > +	TSEM_SB_REMOUNT,
> > +	TSEM_SB_PIVOTROOT,
> > +	TSEM_SB_STATFS,
> > +	TSEM_MOVE_MOUNT,
> > +	TSEM_SHM_ASSOCIATE,
> > +	TSEM_SHM_SHMCTL,
> > +	TSEM_SHM_SHMAT,
> > +	TSEM_SEM_ASSOCIATE,
> > +	TSEM_SEM_SEMCTL,
> > +	TSEM_SEM_SEMOP,
> > +	TSEM_SYSLOG,
> > +	TSEM_SETTIME,
> > +	TSEM_QUOTACTL,
> > +	TSEM_QUOTA_ON,
> > +	TSEM_MSG_QUEUE_ASSOCIATE,
> > +	TSEM_MSG_QUEUE_MSGCTL,
> > +	TSEM_MSG_QUEUE_MSGSND,
> > +	TSEM_MSG_QUEUE_MSGRCV,
> > +	TSEM_IPC_PERMISSION,
> > +	TSEM_KEY_ALLOC,
> > +	TSEM_KEY_PERMISSION,
> > +	TSEM_NETLINK_SEND,
> > +	TSEM_INODE_CREATE,
> > +	TSEM_INODE_LINK,
> > +	TSEM_INODE_UNLINK,
> > +	TSEM_INODE_SYMLINK,
> > +	TSEM_INODE_MKDIR,
> > +	TSEM_INODE_RMDIR,
> > +	TSEM_INODE_MKNOD,
> > +	TSEM_INODE_RENAME,
> > +	TSEM_INODE_SETATTR,
> > +	TSEM_INODE_GETATTR,
> > +	TSEM_INODE_SETXATTR,
> > +	TSEM_INODE_GETXATTR,
> > +	TSEM_INODE_LISTXATTR,
> > +	TSEM_INODE_REMOVEXATTR,
> > +	TSEM_INODE_KILLPRIV,
> > +	TSEM_TUN_DEV_CREATE,
> > +	TSEM_TUN_DEV_ATTACH_QUEUE,
> > +	TSEM_TUN_DEV_ATTACH,
> > +	TSEM_TUN_DEV_OPEN,
> > +	TSEM_BPF,
> > +	TSEM_BPF_MAP,
> > +	TSEM_BPF_PROG,
> > +	TSEM_EVENT_CNT
> > +};
> > +
> > +/**
> > + * enum tsem_action_type - Ordinal value for security responses.
> > + * @TSEM_ACTION_LOG: Ordinal value to indicate that a security event
> > + *		     that results in a model permissions violation
> > + *		     should be logged.
> > + * @TSEM_ACTION_EPERM: Ordinal value to indicate that a security event
> > + *		       generating a model permissions violation should
> > + *		       return -EPERM to the caller.
> > + *
> > + * This enumeration type is used to designate what type of action is
> > + * to be taken when the processing of a security event hook results in
> > + * a model violation.  The TSEM_ACTION_LOG and TSEM_ACTION_EPERM
> > + * translate into the classical concepts of logging or enforcing
> > + * actions used by other mandatory access control architectures.
> > + */
> > +enum tsem_action_type {
> > +	TSEM_ACTION_LOG = 0,
> > +	TSEM_ACTION_EPERM,
> > +	TSEM_ACTION_CNT
> > +};
> > +
> > +/**
> > + * enum tsem_control_type - Ordinal values for TSEM control actions.
> > + * @TSEM_CONTROL_INTERNAL: This ordinal value is set when the first
> > + *			   word of an argument string written to the
> > + *			   control file is the word 'internal'.  This
> > + *			   designates that the security namespace will
> > + *			   be modeled by the internal TMA.
> > + * @TSEM_CONTROL_EXTERNAL: This ordinal value is set when the first
> > + *			   word of an argument string written to the
> > + *			   control file is the word 'external'.  This
> > + *			   designates that the security namespace will
> > + *			   be model by an external TMA.
> > + * @TSEM_CONTROL_ENFORCE: This ordinal value is set when the word
> > + *			  'enforce' is written to the control file.
> > + *			  This indicates that model is to be placed
> > + *			  in 'enforcing' mode and security events that
> > + *			  result in model violations will return EPERM.
> > + * @TSEM_CONTROL_SEAL: This ordinal value is set when the word 'seal'
> > + *		       is written to the control file.  This indicates
> > + *		       that the model for security domain will treat
> > + *		       all security events that do not conform to the
> > + *		       model as 'forensics' events.
> > + * @TSEM_CONTROL_TRUSTED: This ordinal value is used when the first
> > + *			  word of an argument string written to the
> > + *			  control file is the word 'trusted'.  This
> > + *			  is interpreted as a directive to set the
> > + *			  trust status of the task that executed the
> > + *			  security event to be trusted.
> > + * @TSEM_CONTROL_UNTRUSTED: This ordinal value is used when the first
> > + *			    word of an argument string written to the
> > + *			    control file is the word 'untrusted'.
> > + *			    This is interpreted as a directive to set
> > + *			    the trust status of the task that executed
> > + *			    the security event to be untrusted.
> > + * @TSEM_CONTROL_MAP_STATE: This ordinal value is used when the first
> > + *			    word of an argument string written to the
> > + *			    control file is the word 'state'.  The
> > + *			    argument to this directive will be an
> > + *			    ASCII hexadecimally encoded string of the
> > + *			    current model's digest size that will be
> > + *			    treated as a security state point for
> > + *			    inclusion in the security model for the
> > + *			    security domain/namespace.
> > + * @TSEM_CONTROL_MAP_PSEUDONYM: This ordinal value is used when the
> > + *				first word of an argument string
> > + *				written to the control file is the
> > + *				word 'pseudonym'.  The argument to
> > + *				this directive will be an ASCII
> > + *				hexadecimally encoded string of the
> > + *				current model's digest size that will
> > + *				be treated as a pseudonym directive
> > + *				for the security domain/namespace.
> > + * TSEM_CONTROL_MAP_BASE: This ordinal value is used when the first
> > + *			  word of an argument string written to the
> > + *			  control file is the word 'base'.  The
> > + *			  argument to this directive will be an ASCII
> > + *			  hexadecimally encoded string of the current
> > + *			  model's digest size that will be treated as
> > + *			  the base value for the computation of the
> > + *			  functional values (measurement and state) of
> > + *			  the security domain/namespace.
> > +
> > + * This enumeration type is used to designate what type of control
> > + * action is to be implemented when arguments are written to the TSEM
> > + * control file (/sys/kernel/security/tsem/control).  The ordinal
> > + * values govern the processing of the command and the interpretation
> > + * of the rest of the command argument string.
> > + */
> > +enum tsem_control_type {
> > +	TSEM_CONTROL_INTERNAL = 0,
> > +	TSEM_CONTROL_EXTERNAL,
> > +	TSEM_CONTROL_ENFORCE,
> > +	TSEM_CONTROL_SEAL,
> > +	TSEM_CONTROL_TRUSTED,
> > +	TSEM_CONTROL_UNTRUSTED,
> > +	TSEM_CONTROL_MAP_STATE,
> > +	TSEM_CONTROL_MAP_PSEUDONYM,
> > +	TSEM_CONTROL_MAP_BASE
> > +};
> > +
> > +/**
> > + * enum tsem_ns_reference - Ordinal value for DAC namespace reference.
> > + * @TSEM_NS_INITIAL: This ordinal value indicates that the uid/gid
> > + *		     values should be interpreted against the initial
> > + *		     user namespace.
> > + * @TSEM_NS_CURRENT: This ordinal value indicates that the uid/gid
> > + *		     values should be interpreted against the user
> > + *		     namespace that is in effect for the process being
> > + *		     modeled.
> > + *
> > + * This enumeration type is used to indicate what user namespace
> > + * should be referenced when the uid/gid values are interpreted for
> > + * the creation of either the COE or CELL identities.  The enumeration
> > + * ordinal passed to the tsem_ns_create() function, to configure the
> > + * security domain/namespace, is set by the nsref argument to either
> > + * the 'internal' or 'external' control commands.
> > + */
> > +enum tsem_ns_reference {
> > +	TSEM_NS_INITIAL = 1,
> > +	TSEM_NS_CURRENT
> > +};
> > +
> > +/**
> > + * enum tsem_task_trust - Ordinal value describing task trust status.
> > + * @TSEM_TASK_TRUSTED: This ordinal value indicates that the task has
> > + *		       not executed a security event that has resulted
> > + *		       in a security behavior not described by the
> > + *		       security model the task is being governed by.
> > + * @TSEM_TASK_UNTRUSTED: This ordinal value indicates that the task
> > + *		          has requested the execution of a security event
> > + *		          that resulted in a security behavior not
> > + *		          permitted by the security model the task is
> > + *		          being governed by.
> > + * @TSEM_TASK_TRUST_PENDING: This ordinal value indicates that the setting
> > + *			     of the task trust status is pending a response
> > + *		             from an external TMA.
> > + *
> > + * This enumeration type is used to specify the three different trust
> > + * states that a task can be in.  The trust status of a task is
> > + * regulated by the trust_status member of struct tsem_task.  A task
> > + * carrying the status of TSEM_TASK_TRUSTED means that it has
> > + * not requested the execution of any security events that are
> > + * inconsistent with the security model that the task is running in.
> > + *
> > + * If a task requests execution of a security event that is
> > + * inconsistent with the security model it is operating in, and the
> > + * domain is running in 'sealed' mode, the task trust status is set to
> > + * TSEM_TASK_UNTRUSTED.  This value is 'sticky' in that it will be
> > + * propagated to any child tasks that are spawned from an untrusted
> > + * task.
> > + *
> > + * In the case of an externally modeled security domain/namespace, the
> > + * task trust status cannot be determined until the modeling of the
> > + * security event has been completed.  The tsem_export_event()
> > + * function sets the trust status TSEM_TASK_TRUST_PENDING and then
> > + * places the task into an interruptible sleep state.
> > + *
> > + * Only two events will cause the task to be removed from sleep state.
> > + * Either the task is killed or a control message is written to the
> > + * TSEM control file that specifies the trust status of the task.  See
> > + * the description of the TSEM_CONTROL_TRUSTED and
> > + * TSEM_CONTROL_UNTRUSTED enumeration types.
> > + */
> > +enum tsem_task_trust {
> > +	TSEM_TASK_TRUSTED = 1,
> > +	TSEM_TASK_UNTRUSTED = 2,
> > +	TSEM_TASK_TRUST_PENDING = 4

> What happened to 3?

The enumerations represent bit values used in the 'trust_status'
member of the tsem_task structure.

If a task thinks that it has a trust status value of three it would
indicate the task needs massive doses of chlorpromazine.

> > +};
> > +
> > +/**
> > + * enum tsem_inode_state - Ordinal value for inode reference state.
> > + * @TSEM_INODE_COLLECTING: This ordinal value indicates that the uid/gid
> > + *			   values should be interpreted against the initial
> > + *			   user namespace.
> > + * @TSEM_INODE_COLLECTED: This ordinal value indicates that the uid/gid
> > + *			  values should be interpreted against the user
> > + *			  namespace that is in effect for the process being
> > + *		          modeled.
> > + *
> > + * This enumeration type is used to specify the status of the inode
> > + * that is having a digest value computed on the file that it is
> > + * referencing.  The purpose of this enumeration is so that the
> > + * recursive call to the TSEM_FILE_OPEN hook, caused by the kernel
> > + * opening the file to compute the checksum, can be bypassed.
> > + *
> > + * The state value of the inode is carried in struct tsem_inode and is
> > + * set and interrogated by the add_file_digest() function.  If the
> > + * status of the inode is TSEM_INODE_COLLECTED and the iversion of the
> > + * inode is the same as the collection time, the cached value for
> > + * currently active model digest is returned.
> > +
> > + * If the test for the relevancy of the cached digest value fails the
> > + * status of the inode is set to TSEM_INODE_COLLECTING.  The
> > + * tsem_file_open() function will check the inode status when it is
> > + * invoked by the integrity_kernel_read() function and if it is
> > + * set to 'collecting', a successful permissions check is returned so
> > + * that the kernel can open the file and compute its digest.
> > + */
> > +enum tsem_inode_state {
> > +	TSEM_INODE_COLLECTING = 1,
> > +	TSEM_INODE_COLLECTED
> > +};
> > +
> > +/**
> > + * struct tsem_task - TSEM task control structure.
> > + * @tma_for_ns: The context identity number of the namespace that
> > + *		the task has control over if any.
> > + * @trust_status: The enumeration type that specifies the trust state of
> > + *		  the process.
> > + * @task_id: The hash specific digest that identifies the process.
> > + * @task_key: A hash specific digest value that is used to
> > + *	      authenticate a task that is running as a trust
> > + *	      orchestrator to a task that is under the control of the
> > + *	      orchestrator.
> > + * @context: A pointer to the tsem_context structure that defines the
> > + *	     modeling context that the task is running under.
> > + *
> > + * This structure is one of the two primary control structures that
> > + * are implemented through the LSM blob functionality.  It is
> > + * automatically created when the task control structure is allocated
> > + * for a new task that is being created.  It's role is to control the
> > + * status of the task with respect to its security model.
> > + *
> > + * The trust_status member of structure determines whether or not the
> > + * task is in a condition to be trusted.  It represents whether or not
> > + * the task has requested execution of a security event that is
> > + * inconsistent with the model that the task is running under.
> > + * Reference the tsem_trust_status enumeration type for more
> > + * information on this member.  The trust status value is propagated
> > + * to any child tasks that are spawned from a task.
> > + *
> > + * The digest value that the task_id member contains is generated by
> > + * the tsem_tsem_bprm_creds_for_exec() function that computes the
> > + * task identity based on the COE identity and the CELL identity of
> > + * the executable that is being started.  This task_id value is used
> > + * in the computation of the security state point values in
> > + * combination with the COE and CELL identities for this event.  The
> > + * task_id digest creates security state points that are specific to
> > + * the executable file that was used to start the task.
> > + *
> > + * The task_key member holds the authentication key that will be used
> > + * to authenticate a process that is requesting the ability to set the
> > + * trust status of a process.  This value is generated for the task
> > + * structure of the trust orchestrator when a security modeling
> > + * namespace is created by the orchestrator.
> > + *
> > + * As an additional protection, the creation of a namespace causes the
> > + * context id of the created namespace to be placed in the task that
> > + * will serve as the trust orchestrator for the namespace.  This
> > + * context id must match the context id of a process that a trust
> > + * control request is being sent to.  Like the authentication key
> > + * this value is not propagated on task allocation so only the task
> > + * that has nominated the security modeling namespace will have
> > + * possession of the necessary credentials to control it.
> > + *
> > + * The context member of the structure contains a pointer to the
> > + * tsem_context structure allocated when a security modeling namespace
> > + * is created by the tsem_ns_create() function.  This structure will
> > + * contain all of the information needed to define how the task is to
> > + * have its security behavior modeled.
> > + */
> > +struct tsem_task {
> > +	u64 tma_for_ns;
> > +	enum tsem_task_trust trust_status;
> > +	u8 task_id[HASH_MAX_DIGESTSIZE];
> > +	u8 task_key[HASH_MAX_DIGESTSIZE];
> > +	struct tsem_context *context;
> > +};
> > +
> > +/**
> > + * struct tsem_context - TSEM modeling context description.
> > + * @kref: Reference count for the context.
> > + * @work: Work structure for delayed release of the context.
> > + * @id: The index number of the context.
> > + * @sealed: Status variable indicating whether or not the
> > + *	    modeling context can be modified.
> > + * @use_current_ns: Status variable indicating which user namespace
> > + *		    should be used for resolution of uid/gid values.
> > + * @actions: An array of enum tsem_action_type variables indicating
> > + *	     the type of response that should be returned in
> > + *	     response to the modeling of a security event that
> > + *	     is inconsistent with the model being used for the
> > + *	     security context.
> > + * @digestname: A pointer to a null-terminated buffer containing the
> > + *		name of the digest function that is to be used for
> > + *		this security context.
> > + * @zero_digest: The digest value for a 'zero-length' digest value.
> > + * @tfm: A pointer to the digest transformation structure that is to
> > + *	 be used for this context.
> > + * @magazine_size: The number of struct tsem_event structures that
> > + *		   are held in reserve for security event hooks that
> > + *		   are called in atomic context.
> > + * @magazine_lock: The spinlock that protects access to the event
> > + *		   magazine for the security context.
> > + * @magazine_index: The bitmap that is used to track the magazine slots
> > + *		    that have been allocated.
> > + * @ws: An array of work structures that are used to refill the magazine
> > + *	slots.
> > + * @magazine: An array of pointers to struct tsem_event structures that
> > + *	      are pre-allocated for security hooks called in atomic
> > + *	      context.
> > + * @model: If the modeling context is implemented with a kernel based
> > + *	   trusted model agent this pointer will point to the struct
> > + *	   tsem_model structure that maintains the state of the
> > + *	   security model.
> > + * @external: If the modeling context is implemented with an external
> > + *	      modeling agent this pointer will point to the struct
> > + *	      tsem_external structure that implements the interface to
> > + *	      the external trusted modeling agent.
> > +
> > + * This structure is used to represent the state of a TSEM security
> > + * modeling namespace.  A pointer to this structure is stored in the
> > + * struct tsem_task structure.
> > + *
> > + * This structure is allocated by the tsem_ns_create() function in
> > + * response to a TSEM control request.  This structure maintains all
> > + * of the information that describes the security modeling namespace
> > + * that is not specific to the type of namespace, ie. external or
> > + * internal that is being implemented.
> > +
> > + * The id member is a 64-bit counter that cannot feasibly be
> > + * overflowed and that is incremented for each namespace creation that
> > + * is created.  The root modeling namespace has a value of zero so the
> > + * TSEM code uses a pattern of testing this value for non-zero status
> > + * as an indication of whether or not the task is running in a
> > + * subordinate modeling namespace.
> > +
> > + * Each security modeling namespace can have an independent
> > + * cryptographic digest function that is used as the compression
> > + * function for generating the digest values that are used to model
> > + * the security events that occur in a namespace.  A single struct tfm
> > + * is allocated for this digest function at the time that the
> > + * tsem_context structure is created and is maintained in this
> > + * structure for subsequent use during event processing.
> > +
> > + * Each cryptographic digest function has a 'zero message' value that
> > + * is the result of the initialization and closure of a hash function
> > + * that has no other input.  This zero digest value is computed at the
> > + * time of the creation of the array.  This digest value is returned
> > + * for files with zero sizes or that have pseudonyms declared for
> > + * them.
> > + *
> > + * The actions array contains a specification of how each security
> > + * event should be handled in the event that the model detects a
> > + * security event consistent with the model designated for the
> > + * namespace.  This array allows the specification of whether the
> > + * model should be enforcing or logging.  Currently the specification
> > + * is all or nothing for all of the events, with plans to make the
> > + * actions individually configurable.
> > +
> > + * Each security event that is processed requires a struct tsem_event
> > + * structure that drives either the internal modeling of an event or
> > + * its export to an external modeling agent.  Some security event
> > + * hooks are called while a task is running in atomic context. Since
> > + * memory cannot be allocated while a process is in atomic context, a
> > + * magazine of these structures is maintained by this structure for
> > + * security events that run in atomic context.  The size of this
> > + * magazine is dynamic and is configurable for each security modeling
> > + * namespace that is created.
> > + *
> > + * When a tsem_event structure is allocated for an atomic event a
> > + * request for the refill of the slot that is vacated is dispatched to
> > + * an asynchronous workqueue.  The ws member of this structure points
> > + * to an array of work structures for this refill capability, one for
> > + * each slot in the magazine.
> > + *
> > + * All of this infrastructure is generic for each security modeling
> > + * namespace.  How the security modeling is done is governed by the
> > + * model and external members of this structure.  These members point
> > + * to data structures that either maintain the security model state
> > + * for an in kernel trusted modeling agent or handle the export of the
> > + * event to an external trusted modeling agent.
> > + *
> > + * Each task that is created in a non-root security modeling namespace
> > + * increments the reference count maintained in the kref member of
> > + * this structure in the tsem_task_alloc() function.  The
> > + * tsem_task_free() function decrements this reference count.  When
> > + * the reference count expires, ie. when the last task using the
> > + * modeling namespace exits, an asynchronous workqueue request is
> > + * dispatched to dispose of the context.  The work member of this
> > + * structure is used to reference that workqueue request.
> > + */
> > +struct tsem_context {
> > +	struct kref kref;
> > +	struct work_struct work;
> > +
> > +	u64 id;
> > +	bool sealed;
> > +	bool use_current_ns;
> > +
> > +	enum tsem_action_type actions[TSEM_EVENT_CNT];
> > +
> > +	char *digestname;
> > +	u8 zero_digest[HASH_MAX_DIGESTSIZE];
> > +	struct crypto_shash *tfm;
> > +
> > +	unsigned int magazine_size;
> > +	spinlock_t magazine_lock;
> > +	unsigned long *magazine_index;
> > +	struct tsem_work *ws;
> > +	struct tsem_event **magazine;
> > +
> > +	struct tsem_model *model;
> > +	struct tsem_external *external;
> > +};

> Odd use of whitespace in the structure definition.

It is a carry over from our userspace coding style.  As a team we have
found it helpful to visually segregate members of a structure that
have a common and distinct purpose.

FWIW, it would seem that include/linux/sched.h seems to embrace
a similar concept for 'struct task_struct'.

[ ... rest of tsem.h trimmed ... ]

As always,
Dr. Greg

The Quixote Project - Flailing at the Travails of Cybersecurity
Casey Schaufler Aug. 10, 2023, 3:03 p.m. UTC | #3
On 8/9/2023 7:57 PM, Dr. Greg wrote:
> On Mon, Aug 07, 2023 at 01:39:22PM -0700, Casey Schaufler wrote:
>
> Hi Casey, thank you for the review comments.
>
>> On 7/10/2023 3:23 AM, Dr. Greg wrote:
>>> TSEM is designed, from a functional perspective, to be contained
>>> entirely in its own directory.
>>>
>>> The tsem.h header file defines the enumeration types, structure
>>> definitions and externally visiable functions that are referenced
>>> by all of the compilation units of the TSEM LSM implementation in
>>> that directory.
>> Extensive documentation notwithstanding, it's impossible to review
>> the data structures and constants without the code that goes along
>> with them.
> ...
>
> We may have missed it but I don't see anything in the kernel
> developers guide with respect best practices for introducing blocks of
> entire sub-system code.
>
> Recommendations welcome.

You've broken the code into progressive units. Include the data structure
definitions as required in those progressive units. Include the .h's as
they are needed by the .c's.

>
>>> The structure and enumeration types are extensively documented
>>> and are the recommended starting point for understanding TSEM
>>> implementation and functionality.
>>>
>>> Signed-off-by: Greg Wettstein <greg@enjellic.com>
>>> ---
>>>  security/tsem/tsem.h | 1516 ++++++++++++++++++++++++++++++++++++++++++
>>>  1 file changed, 1516 insertions(+)
>>>  create mode 100644 security/tsem/tsem.h
>>>
>>> diff --git a/security/tsem/tsem.h b/security/tsem/tsem.h
>>> new file mode 100644
>>> index 000000000000..03915f47529b
>>> --- /dev/null
>>> +++ b/security/tsem/tsem.h
>>> @@ -0,0 +1,1516 @@
>>> +/* SPDX-License-Identifier: GPL-2.0-only */
>>> +
>>> +/*
>>> + * Copyright (C) 2023 Enjellic Systems Development, LLC
>>> + * Author: Dr. Greg Wettstein <greg@enjellic.com>
>>> + *
>>> + * This is the single include file that documents all of the externally
>>> + * visible types and functions that are used by TSEM.  This file is
>>> + * currently organized into four major sections in the following order;
>>> + *
>>> + * includes used by all compilation units
>>> + * CPP definitions
>>> + * enumeration types
>>> + * structure definitions
>>> + * function declarations
>>> + * inline encapsulation functions.
>>> + *
>>> + * Include files that are referenced by more than a single compilation
>>> + * should be included in this file.  Includes that are needed to
>>> + * satisfy compilation requirements for only a single file should be
>>> + * included in the file needing that include.
>>> + *
>>> + * Understanding the overall implementation and architecture of TSEM
>>> + * will be facilitated by reviewing the documentation in this file.
>>> + */
>>> +
>>> +#include <uapi/linux/in.h>
>>> +#include <uapi/linux/in6.h>
>>> +#include <linux/wait.h>
>>> +#include <linux/kref.h>
>>> +#include <linux/lsm_hooks.h>
>>> +#include <linux/capability.h>
>>> +#include <crypto/hash.h>
>>> +#include <crypto/hash_info.h>
>>> +#include <net/af_unix.h>
>>> +
>>> +/* The capability needed to manage TSEM. */
>>> +#define TSEM_CONTROL_CAPABILITY CAP_ML
>> Why would you do this? You gave the capability a name that even you
>> don't want to use.
> A simple placeholder that allows the capability used to control
> security modeling to be set in one place, and one place only, until
> the debate over the capability issue is settled.
>
> We never envisioned this define lasting beyond the initial reviews.

Intentional obfuscation is never going to make the review process
easier. I have enough trouble following clear and obvious code. I'm
going to search for CAP_ during a review. You just made that harder. 

> ...
>
> +
> +/**
> + * enum tsem_task_trust - Ordinal value describing task trust status.
> + * @TSEM_TASK_TRUSTED: This ordinal value indicates that the task has
> + *		       not executed a security event that has resulted
> + *		       in a security behavior not described by the
> + *		       security model the task is being governed by.
> + * @TSEM_TASK_UNTRUSTED: This ordinal value indicates that the task
> + *		          has requested the execution of a security event
> + *		          that resulted in a security behavior not
> + *		          permitted by the security model the task is
> + *		          being governed by.
> + * @TSEM_TASK_TRUST_PENDING: This ordinal value indicates that the setting
> + *			     of the task trust status is pending a response
> + *		             from an external TMA.
> + *
> + * This enumeration type is used to specify the three different trust
> + * states that a task can be in.  The trust status of a task is
> + * regulated by the trust_status member of struct tsem_task.  A task
> + * carrying the status of TSEM_TASK_TRUSTED means that it has
> + * not requested the execution of any security events that are
> + * inconsistent with the security model that the task is running in.
> + *
> + * If a task requests execution of a security event that is
> + * inconsistent with the security model it is operating in, and the
> + * domain is running in 'sealed' mode, the task trust status is set to
> + * TSEM_TASK_UNTRUSTED.  This value is 'sticky' in that it will be
> + * propagated to any child tasks that are spawned from an untrusted
> + * task.
> + *
> + * In the case of an externally modeled security domain/namespace, the
> + * task trust status cannot be determined until the modeling of the
> + * security event has been completed.  The tsem_export_event()
> + * function sets the trust status TSEM_TASK_TRUST_PENDING and then
> + * places the task into an interruptible sleep state.
> + *
> + * Only two events will cause the task to be removed from sleep state.
> + * Either the task is killed or a control message is written to the
> + * TSEM control file that specifies the trust status of the task.  See
> + * the description of the TSEM_CONTROL_TRUSTED and
> + * TSEM_CONTROL_UNTRUSTED enumeration types.
> + */
> +enum tsem_task_trust {
> +	TSEM_TASK_TRUSTED = 1,
> +	TSEM_TASK_UNTRUSTED = 2,
> +	TSEM_TASK_TRUST_PENDING = 4
>> What happened to 3?
> The enumerations represent bit values used in the 'trust_status'
> member of the tsem_task structure.

Someone can correct me if I'm wrong, but I think that's a misuse
of enum. 

>
> If a task thinks that it has a trust status value of three it would
> indicate the task needs massive doses of chlorpromazine.

If you're not using logical operations (&, |) why do you care if
they're "bit values"?

> ...
>
> + *
> + * Each task that is created in a non-root security modeling namespace
> + * increments the reference count maintained in the kref member of
> + * this structure in the tsem_task_alloc() function.  The
> + * tsem_task_free() function decrements this reference count.  When
> + * the reference count expires, ie. when the last task using the
> + * modeling namespace exits, an asynchronous workqueue request is
> + * dispatched to dispose of the context.  The work member of this
> + * structure is used to reference that workqueue request.
> + */
> +struct tsem_context {
> +	struct kref kref;
> +	struct work_struct work;
> +
> +	u64 id;
> +	bool sealed;
> +	bool use_current_ns;
> +
> +	enum tsem_action_type actions[TSEM_EVENT_CNT];
> +
> +	char *digestname;
> +	u8 zero_digest[HASH_MAX_DIGESTSIZE];
> +	struct crypto_shash *tfm;
> +
> +	unsigned int magazine_size;
> +	spinlock_t magazine_lock;
> +	unsigned long *magazine_index;
> +	struct tsem_work *ws;
> +	struct tsem_event **magazine;
> +
> +	struct tsem_model *model;
> +	struct tsem_external *external;
> +};
>> Odd use of whitespace in the structure definition.
> It is a carry over from our userspace coding style.  As a team we have
> found it helpful to visually segregate members of a structure that
> have a common and distinct purpose.
>
> FWIW, it would seem that include/linux/sched.h seems to embrace
> a similar concept for 'struct task_struct'.

I'm not formally objecting to it, but there's no obvious reason for it.

>
> [ ... rest of tsem.h trimmed ... ]
>
> As always,
> Dr. Greg
>
> The Quixote Project - Flailing at the Travails of Cybersecurity
diff mbox series

Patch

diff --git a/security/tsem/tsem.h b/security/tsem/tsem.h
new file mode 100644
index 000000000000..03915f47529b
--- /dev/null
+++ b/security/tsem/tsem.h
@@ -0,0 +1,1516 @@ 
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * Copyright (C) 2023 Enjellic Systems Development, LLC
+ * Author: Dr. Greg Wettstein <greg@enjellic.com>
+ *
+ * This is the single include file that documents all of the externally
+ * visible types and functions that are used by TSEM.  This file is
+ * currently organized into four major sections in the following order;
+ *
+ * includes used by all compilation units
+ * CPP definitions
+ * enumeration types
+ * structure definitions
+ * function declarations
+ * inline encapsulation functions.
+ *
+ * Include files that are referenced by more than a single compilation
+ * should be included in this file.  Includes that are needed to
+ * satisfy compilation requirements for only a single file should be
+ * included in the file needing that include.
+ *
+ * Understanding the overall implementation and architecture of TSEM
+ * will be facilitated by reviewing the documentation in this file.
+ */
+
+#include <uapi/linux/in.h>
+#include <uapi/linux/in6.h>
+#include <linux/wait.h>
+#include <linux/kref.h>
+#include <linux/lsm_hooks.h>
+#include <linux/capability.h>
+#include <crypto/hash.h>
+#include <crypto/hash_info.h>
+#include <net/af_unix.h>
+
+/* The capability needed to manage TSEM. */
+#define TSEM_CONTROL_CAPABILITY CAP_ML
+
+/*
+ * The number of 'slots' in the structure magazines that are used to
+ * satisfy modeling of security events that are called in atomic context.
+ */
+#define TSEM_ROOT_MAGAZINE_SIZE	96
+#define TSEM_MAGAZINE_SIZE_INTERNAL 16
+#define TSEM_MAGAZINE_SIZE_EXTERNAL 96
+
+/**
+ * enum tsem_event_type - Ordinal value for a security event.
+ * @TSEM_BPRM_SET_CREDS: Ordinal value for bprm_creds_for_exec.
+ * @TSEM_GENERIC_EVENT: Ordinal value for a generically modeled event.
+ * @TSEM_TASK_KILL: Ordinal value for task kill.
+ * @....: Remainder follows with a similar naming format that has
+ *        TSEM_ prep ended to the raw LSM security hook name.
+ * @TSEM_EVENT_CNT: The final ordinal value is used to define the
+ *		    length of the following arrays that are indexed
+ *		    by the ordinal value of the hook:
+ *
+ * This enumeration is used to designate an ordinal value for each
+ * security event, ie. LSM hook, that TSEM is implementing modeling
+ * for.  This value is used to identify the hook that is either having
+ * its event description being exported to an external Trusted Modeling
+ * Agent (TMA) or modeled by the internal TMA implementation.
+ *
+ * The primary use of this enumeration is to conditionalize code paths
+ * based on the security hook being processed and to index the
+ * tsem_names array and the array that defines the action that is to
+ * be taken in response to an event that generates a permissions
+ * violation.
+ */
+enum tsem_event_type {
+	TSEM_BPRM_SET_CREDS = 1,
+	TSEM_GENERIC_EVENT,
+	TSEM_TASK_KILL,
+	TSEM_TASK_SETPGID,
+	TSEM_TASK_GETPGID,
+	TSEM_TASK_GETSID,
+	TSEM_TASK_SETNICE,
+	TSEM_TASK_SETIOPRIO,
+	TSEM_TASK_GETIOPRIO,
+	TSEM_TASK_PRLIMIT,
+	TSEM_TASK_SETRLIMIT,
+	TSEM_TASK_SETSCHEDULER,
+	TSEM_TASK_GETSCHEDULER,
+	TSEM_TASK_PRCTL,
+	TSEM_FILE_OPEN,
+	TSEM_MMAP_FILE,
+	TSEM_FILE_IOCTL,
+	TSEM_FILE_LOCK,
+	TSEM_FILE_FCNTL,
+	TSEM_FILE_RECEIVE,
+	TSEM_UNIX_STREAM_CONNECT,
+	TSEM_UNIX_MAY_SEND,
+	TSEM_SOCKET_CREATE,
+	TSEM_SOCKET_CONNECT,
+	TSEM_SOCKET_BIND,
+	TSEM_SOCKET_ACCEPT,
+	TSEM_SOCKET_LISTEN,
+	TSEM_SOCKET_SOCKETPAIR,
+	TSEM_SOCKET_SENDMSG,
+	TSEM_SOCKET_RECVMSG,
+	TSEM_SOCKET_GETSOCKNAME,
+	TSEM_SOCKET_GETPEERNAME,
+	TSEM_SOCKET_SETSOCKOPT,
+	TSEM_SOCKET_SHUTDOWN,
+	TSEM_PTRACE_TRACEME,
+	TSEM_KERNEL_MODULE_REQUEST,
+	TSEM_KERNEL_LOAD_DATA,
+	TSEM_KERNEL_READ_FILE,
+	TSEM_SB_MOUNT,
+	TSEM_SB_UMOUNT,
+	TSEM_SB_REMOUNT,
+	TSEM_SB_PIVOTROOT,
+	TSEM_SB_STATFS,
+	TSEM_MOVE_MOUNT,
+	TSEM_SHM_ASSOCIATE,
+	TSEM_SHM_SHMCTL,
+	TSEM_SHM_SHMAT,
+	TSEM_SEM_ASSOCIATE,
+	TSEM_SEM_SEMCTL,
+	TSEM_SEM_SEMOP,
+	TSEM_SYSLOG,
+	TSEM_SETTIME,
+	TSEM_QUOTACTL,
+	TSEM_QUOTA_ON,
+	TSEM_MSG_QUEUE_ASSOCIATE,
+	TSEM_MSG_QUEUE_MSGCTL,
+	TSEM_MSG_QUEUE_MSGSND,
+	TSEM_MSG_QUEUE_MSGRCV,
+	TSEM_IPC_PERMISSION,
+	TSEM_KEY_ALLOC,
+	TSEM_KEY_PERMISSION,
+	TSEM_NETLINK_SEND,
+	TSEM_INODE_CREATE,
+	TSEM_INODE_LINK,
+	TSEM_INODE_UNLINK,
+	TSEM_INODE_SYMLINK,
+	TSEM_INODE_MKDIR,
+	TSEM_INODE_RMDIR,
+	TSEM_INODE_MKNOD,
+	TSEM_INODE_RENAME,
+	TSEM_INODE_SETATTR,
+	TSEM_INODE_GETATTR,
+	TSEM_INODE_SETXATTR,
+	TSEM_INODE_GETXATTR,
+	TSEM_INODE_LISTXATTR,
+	TSEM_INODE_REMOVEXATTR,
+	TSEM_INODE_KILLPRIV,
+	TSEM_TUN_DEV_CREATE,
+	TSEM_TUN_DEV_ATTACH_QUEUE,
+	TSEM_TUN_DEV_ATTACH,
+	TSEM_TUN_DEV_OPEN,
+	TSEM_BPF,
+	TSEM_BPF_MAP,
+	TSEM_BPF_PROG,
+	TSEM_EVENT_CNT
+};
+
+/**
+ * enum tsem_action_type - Ordinal value for security responses.
+ * @TSEM_ACTION_LOG: Ordinal value to indicate that a security event
+ *		     that results in a model permissions violation
+ *		     should be logged.
+ * @TSEM_ACTION_EPERM: Ordinal value to indicate that a security event
+ *		       generating a model permissions violation should
+ *		       return -EPERM to the caller.
+ *
+ * This enumeration type is used to designate what type of action is
+ * to be taken when the processing of a security event hook results in
+ * a model violation.  The TSEM_ACTION_LOG and TSEM_ACTION_EPERM
+ * translate into the classical concepts of logging or enforcing
+ * actions used by other mandatory access control architectures.
+ */
+enum tsem_action_type {
+	TSEM_ACTION_LOG = 0,
+	TSEM_ACTION_EPERM,
+	TSEM_ACTION_CNT
+};
+
+/**
+ * enum tsem_control_type - Ordinal values for TSEM control actions.
+ * @TSEM_CONTROL_INTERNAL: This ordinal value is set when the first
+ *			   word of an argument string written to the
+ *			   control file is the word 'internal'.  This
+ *			   designates that the security namespace will
+ *			   be modeled by the internal TMA.
+ * @TSEM_CONTROL_EXTERNAL: This ordinal value is set when the first
+ *			   word of an argument string written to the
+ *			   control file is the word 'external'.  This
+ *			   designates that the security namespace will
+ *			   be model by an external TMA.
+ * @TSEM_CONTROL_ENFORCE: This ordinal value is set when the word
+ *			  'enforce' is written to the control file.
+ *			  This indicates that model is to be placed
+ *			  in 'enforcing' mode and security events that
+ *			  result in model violations will return EPERM.
+ * @TSEM_CONTROL_SEAL: This ordinal value is set when the word 'seal'
+ *		       is written to the control file.  This indicates
+ *		       that the model for security domain will treat
+ *		       all security events that do not conform to the
+ *		       model as 'forensics' events.
+ * @TSEM_CONTROL_TRUSTED: This ordinal value is used when the first
+ *			  word of an argument string written to the
+ *			  control file is the word 'trusted'.  This
+ *			  is interpreted as a directive to set the
+ *			  trust status of the task that executed the
+ *			  security event to be trusted.
+ * @TSEM_CONTROL_UNTRUSTED: This ordinal value is used when the first
+ *			    word of an argument string written to the
+ *			    control file is the word 'untrusted'.
+ *			    This is interpreted as a directive to set
+ *			    the trust status of the task that executed
+ *			    the security event to be untrusted.
+ * @TSEM_CONTROL_MAP_STATE: This ordinal value is used when the first
+ *			    word of an argument string written to the
+ *			    control file is the word 'state'.  The
+ *			    argument to this directive will be an
+ *			    ASCII hexadecimally encoded string of the
+ *			    current model's digest size that will be
+ *			    treated as a security state point for
+ *			    inclusion in the security model for the
+ *			    security domain/namespace.
+ * @TSEM_CONTROL_MAP_PSEUDONYM: This ordinal value is used when the
+ *				first word of an argument string
+ *				written to the control file is the
+ *				word 'pseudonym'.  The argument to
+ *				this directive will be an ASCII
+ *				hexadecimally encoded string of the
+ *				current model's digest size that will
+ *				be treated as a pseudonym directive
+ *				for the security domain/namespace.
+ * TSEM_CONTROL_MAP_BASE: This ordinal value is used when the first
+ *			  word of an argument string written to the
+ *			  control file is the word 'base'.  The
+ *			  argument to this directive will be an ASCII
+ *			  hexadecimally encoded string of the current
+ *			  model's digest size that will be treated as
+ *			  the base value for the computation of the
+ *			  functional values (measurement and state) of
+ *			  the security domain/namespace.
+
+ * This enumeration type is used to designate what type of control
+ * action is to be implemented when arguments are written to the TSEM
+ * control file (/sys/kernel/security/tsem/control).  The ordinal
+ * values govern the processing of the command and the interpretation
+ * of the rest of the command argument string.
+ */
+enum tsem_control_type {
+	TSEM_CONTROL_INTERNAL = 0,
+	TSEM_CONTROL_EXTERNAL,
+	TSEM_CONTROL_ENFORCE,
+	TSEM_CONTROL_SEAL,
+	TSEM_CONTROL_TRUSTED,
+	TSEM_CONTROL_UNTRUSTED,
+	TSEM_CONTROL_MAP_STATE,
+	TSEM_CONTROL_MAP_PSEUDONYM,
+	TSEM_CONTROL_MAP_BASE
+};
+
+/**
+ * enum tsem_ns_reference - Ordinal value for DAC namespace reference.
+ * @TSEM_NS_INITIAL: This ordinal value indicates that the uid/gid
+ *		     values should be interpreted against the initial
+ *		     user namespace.
+ * @TSEM_NS_CURRENT: This ordinal value indicates that the uid/gid
+ *		     values should be interpreted against the user
+ *		     namespace that is in effect for the process being
+ *		     modeled.
+ *
+ * This enumeration type is used to indicate what user namespace
+ * should be referenced when the uid/gid values are interpreted for
+ * the creation of either the COE or CELL identities.  The enumeration
+ * ordinal passed to the tsem_ns_create() function, to configure the
+ * security domain/namespace, is set by the nsref argument to either
+ * the 'internal' or 'external' control commands.
+ */
+enum tsem_ns_reference {
+	TSEM_NS_INITIAL = 1,
+	TSEM_NS_CURRENT
+};
+
+/**
+ * enum tsem_task_trust - Ordinal value describing task trust status.
+ * @TSEM_TASK_TRUSTED: This ordinal value indicates that the task has
+ *		       not executed a security event that has resulted
+ *		       in a security behavior not described by the
+ *		       security model the task is being governed by.
+ * @TSEM_TASK_UNTRUSTED: This ordinal value indicates that the task
+ *		          has requested the execution of a security event
+ *		          that resulted in a security behavior not
+ *		          permitted by the security model the task is
+ *		          being governed by.
+ * @TSEM_TASK_TRUST_PENDING: This ordinal value indicates that the setting
+ *			     of the task trust status is pending a response
+ *		             from an external TMA.
+ *
+ * This enumeration type is used to specify the three different trust
+ * states that a task can be in.  The trust status of a task is
+ * regulated by the trust_status member of struct tsem_task.  A task
+ * carrying the status of TSEM_TASK_TRUSTED means that it has
+ * not requested the execution of any security events that are
+ * inconsistent with the security model that the task is running in.
+ *
+ * If a task requests execution of a security event that is
+ * inconsistent with the security model it is operating in, and the
+ * domain is running in 'sealed' mode, the task trust status is set to
+ * TSEM_TASK_UNTRUSTED.  This value is 'sticky' in that it will be
+ * propagated to any child tasks that are spawned from an untrusted
+ * task.
+ *
+ * In the case of an externally modeled security domain/namespace, the
+ * task trust status cannot be determined until the modeling of the
+ * security event has been completed.  The tsem_export_event()
+ * function sets the trust status TSEM_TASK_TRUST_PENDING and then
+ * places the task into an interruptible sleep state.
+ *
+ * Only two events will cause the task to be removed from sleep state.
+ * Either the task is killed or a control message is written to the
+ * TSEM control file that specifies the trust status of the task.  See
+ * the description of the TSEM_CONTROL_TRUSTED and
+ * TSEM_CONTROL_UNTRUSTED enumeration types.
+ */
+enum tsem_task_trust {
+	TSEM_TASK_TRUSTED = 1,
+	TSEM_TASK_UNTRUSTED = 2,
+	TSEM_TASK_TRUST_PENDING = 4
+};
+
+/**
+ * enum tsem_inode_state - Ordinal value for inode reference state.
+ * @TSEM_INODE_COLLECTING: This ordinal value indicates that the uid/gid
+ *			   values should be interpreted against the initial
+ *			   user namespace.
+ * @TSEM_INODE_COLLECTED: This ordinal value indicates that the uid/gid
+ *			  values should be interpreted against the user
+ *			  namespace that is in effect for the process being
+ *		          modeled.
+ *
+ * This enumeration type is used to specify the status of the inode
+ * that is having a digest value computed on the file that it is
+ * referencing.  The purpose of this enumeration is so that the
+ * recursive call to the TSEM_FILE_OPEN hook, caused by the kernel
+ * opening the file to compute the checksum, can be bypassed.
+ *
+ * The state value of the inode is carried in struct tsem_inode and is
+ * set and interrogated by the add_file_digest() function.  If the
+ * status of the inode is TSEM_INODE_COLLECTED and the iversion of the
+ * inode is the same as the collection time, the cached value for
+ * currently active model digest is returned.
+
+ * If the test for the relevancy of the cached digest value fails the
+ * status of the inode is set to TSEM_INODE_COLLECTING.  The
+ * tsem_file_open() function will check the inode status when it is
+ * invoked by the integrity_kernel_read() function and if it is
+ * set to 'collecting', a successful permissions check is returned so
+ * that the kernel can open the file and compute its digest.
+ */
+enum tsem_inode_state {
+	TSEM_INODE_COLLECTING = 1,
+	TSEM_INODE_COLLECTED
+};
+
+/**
+ * struct tsem_task - TSEM task control structure.
+ * @tma_for_ns: The context identity number of the namespace that
+ *		the task has control over if any.
+ * @trust_status: The enumeration type that specifies the trust state of
+ *		  the process.
+ * @task_id: The hash specific digest that identifies the process.
+ * @task_key: A hash specific digest value that is used to
+ *	      authenticate a task that is running as a trust
+ *	      orchestrator to a task that is under the control of the
+ *	      orchestrator.
+ * @context: A pointer to the tsem_context structure that defines the
+ *	     modeling context that the task is running under.
+ *
+ * This structure is one of the two primary control structures that
+ * are implemented through the LSM blob functionality.  It is
+ * automatically created when the task control structure is allocated
+ * for a new task that is being created.  It's role is to control the
+ * status of the task with respect to its security model.
+ *
+ * The trust_status member of structure determines whether or not the
+ * task is in a condition to be trusted.  It represents whether or not
+ * the task has requested execution of a security event that is
+ * inconsistent with the model that the task is running under.
+ * Reference the tsem_trust_status enumeration type for more
+ * information on this member.  The trust status value is propagated
+ * to any child tasks that are spawned from a task.
+ *
+ * The digest value that the task_id member contains is generated by
+ * the tsem_tsem_bprm_creds_for_exec() function that computes the
+ * task identity based on the COE identity and the CELL identity of
+ * the executable that is being started.  This task_id value is used
+ * in the computation of the security state point values in
+ * combination with the COE and CELL identities for this event.  The
+ * task_id digest creates security state points that are specific to
+ * the executable file that was used to start the task.
+ *
+ * The task_key member holds the authentication key that will be used
+ * to authenticate a process that is requesting the ability to set the
+ * trust status of a process.  This value is generated for the task
+ * structure of the trust orchestrator when a security modeling
+ * namespace is created by the orchestrator.
+ *
+ * As an additional protection, the creation of a namespace causes the
+ * context id of the created namespace to be placed in the task that
+ * will serve as the trust orchestrator for the namespace.  This
+ * context id must match the context id of a process that a trust
+ * control request is being sent to.  Like the authentication key
+ * this value is not propagated on task allocation so only the task
+ * that has nominated the security modeling namespace will have
+ * possession of the necessary credentials to control it.
+ *
+ * The context member of the structure contains a pointer to the
+ * tsem_context structure allocated when a security modeling namespace
+ * is created by the tsem_ns_create() function.  This structure will
+ * contain all of the information needed to define how the task is to
+ * have its security behavior modeled.
+ */
+struct tsem_task {
+	u64 tma_for_ns;
+	enum tsem_task_trust trust_status;
+	u8 task_id[HASH_MAX_DIGESTSIZE];
+	u8 task_key[HASH_MAX_DIGESTSIZE];
+	struct tsem_context *context;
+};
+
+/**
+ * struct tsem_context - TSEM modeling context description.
+ * @kref: Reference count for the context.
+ * @work: Work structure for delayed release of the context.
+ * @id: The index number of the context.
+ * @sealed: Status variable indicating whether or not the
+ *	    modeling context can be modified.
+ * @use_current_ns: Status variable indicating which user namespace
+ *		    should be used for resolution of uid/gid values.
+ * @actions: An array of enum tsem_action_type variables indicating
+ *	     the type of response that should be returned in
+ *	     response to the modeling of a security event that
+ *	     is inconsistent with the model being used for the
+ *	     security context.
+ * @digestname: A pointer to a null-terminated buffer containing the
+ *		name of the digest function that is to be used for
+ *		this security context.
+ * @zero_digest: The digest value for a 'zero-length' digest value.
+ * @tfm: A pointer to the digest transformation structure that is to
+ *	 be used for this context.
+ * @magazine_size: The number of struct tsem_event structures that
+ *		   are held in reserve for security event hooks that
+ *		   are called in atomic context.
+ * @magazine_lock: The spinlock that protects access to the event
+ *		   magazine for the security context.
+ * @magazine_index: The bitmap that is used to track the magazine slots
+ *		    that have been allocated.
+ * @ws: An array of work structures that are used to refill the magazine
+ *	slots.
+ * @magazine: An array of pointers to struct tsem_event structures that
+ *	      are pre-allocated for security hooks called in atomic
+ *	      context.
+ * @model: If the modeling context is implemented with a kernel based
+ *	   trusted model agent this pointer will point to the struct
+ *	   tsem_model structure that maintains the state of the
+ *	   security model.
+ * @external: If the modeling context is implemented with an external
+ *	      modeling agent this pointer will point to the struct
+ *	      tsem_external structure that implements the interface to
+ *	      the external trusted modeling agent.
+
+ * This structure is used to represent the state of a TSEM security
+ * modeling namespace.  A pointer to this structure is stored in the
+ * struct tsem_task structure.
+ *
+ * This structure is allocated by the tsem_ns_create() function in
+ * response to a TSEM control request.  This structure maintains all
+ * of the information that describes the security modeling namespace
+ * that is not specific to the type of namespace, ie. external or
+ * internal that is being implemented.
+
+ * The id member is a 64-bit counter that cannot feasibly be
+ * overflowed and that is incremented for each namespace creation that
+ * is created.  The root modeling namespace has a value of zero so the
+ * TSEM code uses a pattern of testing this value for non-zero status
+ * as an indication of whether or not the task is running in a
+ * subordinate modeling namespace.
+
+ * Each security modeling namespace can have an independent
+ * cryptographic digest function that is used as the compression
+ * function for generating the digest values that are used to model
+ * the security events that occur in a namespace.  A single struct tfm
+ * is allocated for this digest function at the time that the
+ * tsem_context structure is created and is maintained in this
+ * structure for subsequent use during event processing.
+
+ * Each cryptographic digest function has a 'zero message' value that
+ * is the result of the initialization and closure of a hash function
+ * that has no other input.  This zero digest value is computed at the
+ * time of the creation of the array.  This digest value is returned
+ * for files with zero sizes or that have pseudonyms declared for
+ * them.
+ *
+ * The actions array contains a specification of how each security
+ * event should be handled in the event that the model detects a
+ * security event consistent with the model designated for the
+ * namespace.  This array allows the specification of whether the
+ * model should be enforcing or logging.  Currently the specification
+ * is all or nothing for all of the events, with plans to make the
+ * actions individually configurable.
+
+ * Each security event that is processed requires a struct tsem_event
+ * structure that drives either the internal modeling of an event or
+ * its export to an external modeling agent.  Some security event
+ * hooks are called while a task is running in atomic context. Since
+ * memory cannot be allocated while a process is in atomic context, a
+ * magazine of these structures is maintained by this structure for
+ * security events that run in atomic context.  The size of this
+ * magazine is dynamic and is configurable for each security modeling
+ * namespace that is created.
+ *
+ * When a tsem_event structure is allocated for an atomic event a
+ * request for the refill of the slot that is vacated is dispatched to
+ * an asynchronous workqueue.  The ws member of this structure points
+ * to an array of work structures for this refill capability, one for
+ * each slot in the magazine.
+ *
+ * All of this infrastructure is generic for each security modeling
+ * namespace.  How the security modeling is done is governed by the
+ * model and external members of this structure.  These members point
+ * to data structures that either maintain the security model state
+ * for an in kernel trusted modeling agent or handle the export of the
+ * event to an external trusted modeling agent.
+ *
+ * Each task that is created in a non-root security modeling namespace
+ * increments the reference count maintained in the kref member of
+ * this structure in the tsem_task_alloc() function.  The
+ * tsem_task_free() function decrements this reference count.  When
+ * the reference count expires, ie. when the last task using the
+ * modeling namespace exits, an asynchronous workqueue request is
+ * dispatched to dispose of the context.  The work member of this
+ * structure is used to reference that workqueue request.
+ */
+struct tsem_context {
+	struct kref kref;
+	struct work_struct work;
+
+	u64 id;
+	bool sealed;
+	bool use_current_ns;
+
+	enum tsem_action_type actions[TSEM_EVENT_CNT];
+
+	char *digestname;
+	u8 zero_digest[HASH_MAX_DIGESTSIZE];
+	struct crypto_shash *tfm;
+
+	unsigned int magazine_size;
+	spinlock_t magazine_lock;
+	unsigned long *magazine_index;
+	struct tsem_work *ws;
+	struct tsem_event **magazine;
+
+	struct tsem_model *model;
+	struct tsem_external *external;
+};
+
+/**
+ * struct tsem_model - TSEM internal TMA description.
+ * @have_aggregate: Flag variable to indicate whether or not the
+ *		    hardware aggregate value has been injected into
+ *		    the mode.
+ * @base: The base value that is to be used in computing the
+ *	  measurement and state values of the model.
+ * @measurement: The time dependent linear extension state of the
+ *		 model.
+ * @state: The time independent linear extension state of the model.
+ * @point_lock: The spinlock that protects access to the list of
+ *		security state coefficients in the model.
+ * @point_list: A pointer to the list of security state coefficients
+ *		in the model.
+ * @point_end_mutex: The mutex that is used to protect the end of the
+ *		     list of security state coefficients for the
+ *		     model.
+ * @point_end: A pointer to the end of the list of security state
+ *	       coefficients that will be traversed by a call to the
+ *	       control plane.
+ * @trajectory_lock: The spinlock used to protect the list of security
+ *		     event descriptions in the model.
+ * @trajectory_list: A pointer to the list of descriptions of the
+ *		     security events that have been recorded in this
+ *		     model.
+ * @trajectory_end_mutex: The mutex that protects the end of the list
+ *			  of security event descriptions.
+ * @trajectory_end: A pointer to the end of the list of security event
+ *		    descriptions that will be traversed by a call to
+ *		    the control plane.
+ * @forensics_lock: The spinlock used to protect the list of security
+ *		    event descriptions that are considered invalid by
+ *		    the model being enforced.
+ * @forensics_list: A pointer to the list of descriptions of security
+ *		    events that are considered invalid by the security
+ *		    model being enforced.
+ * @forensics_end_mutex: The mutex that protects the end of the list
+ *			 of security event descriptions that are
+ *			 considered invalid by the current model.
+ * @forensics_end: A pointer to the end of the list of security event
+ *		   descriptions, that are considered invalid, that are
+ *		   to be traversed by a call to the control plane.
+ * @pseudonym_mutex: The mutex lock that protects the list of file
+ *		     digest pseudonyms for the current model.
+ * @pseudonum_list: A pointer to the list of file digest pseudonyms
+ *		    that have been declared for the current model.
+ * @magazine_size: The number of struct tsem_event_point structures that
+ *		   are held in reserve for security event hooks that
+ *		   are called in atomic context.
+ * @magazine_lock: The spinlock that protects access to the event
+ *		   magazine for the security context.
+ * @magazine_index: The bitmap that is used to track the magazine slots
+ *		    that have been allocated.
+ * @ws: An array of work structures that are used to refill the magazine
+ *	slots.
+ * @magazine: An array of pointers to struct tsem_event_point structures that
+ *	      are pre-allocated for security hooks called in atomic
+ *	      context.
+ *
+ * If a call to the tsem_ns_create() function specifies that a kernel
+ * based trusted modeling agent is to be used to implement the
+ * security namespace model, a pointer to this structure is placed in
+ * the struct tsem_context structure.  This structure is used to
+ * maintain the state of the kernel based model.
+ *
+ * There are two primary functional values that are maintained by the
+ * model.  The measurement member of this structure represents the
+ * time dependent linear extension sum of the security state
+ * coefficients that have been assigned to security events that have
+ * occurred in the context of the model.
+ *
+ * This classic integrity measurement is subject to scheduling
+ * dependencies and may be invariant from run to run of the model.  It
+ * is of primary use in verifying the order of security events that
+ * have occurred in the model.
+ *
+ * The state member of this structure represents a time independent
+ * linear extension sum of the security state coefficients that have
+ * been generated in the model.  It represents the linear extension
+ * sum of the security state coefficients that have been sorted in
+ * natural (big-endian) form.
+ *
+ * Both of these measurements are dependent on the platform hardware
+ * aggregate value and the base point that has been defined for the
+ * define.
+ *
+ * A non-zero hardware aggregate value is only available if the
+ * platform has a TPM.  The have_aggregate member of this structure is
+ * a flag variable that indicates whether or not the aggregate value
+ * has been injected into the model.
+ *
+ * The base member of this structure contains a model specific
+ * coefficient that is used to perturb each security state coefficient
+ * generated in the model.  This value is designed to serve as a
+ * 'freshness' value for a verifying party to the model.
+ *
+ * There are three primary model lists maintain by this structure:
+ *
+ * * security state points
+ * * security trajectory events
+ * * security forensics events
+ *
+ * Similar members are maintained in this structure to support each of
+ * these lists.
+ *
+ * All three lists are extension only and are protected by a spinlock
+ * that can be held in atomic context.  This spinlock is only held for
+ * the period of time required to extend the list.
+ *
+ * Calls by the control plane to interrogate the lists require the
+ * traversal of the list that is ill-suited for a spinlock.  As a
+ * result each list type has a mutex associated with it that protects
+ * a pointer to the end of the list, an endpoint that is determined at
+ * the start of a call to the control plane.
+ *
+ * The list spinlock is used at the start of the control plane call to
+ * capture the end of the list that is then protected by the mutex.
+ * In essence this is used to transition protection of the list from
+ * the spinlock to the mutex.
+ *
+ * The kernel based modeling agent has support for maintaining a
+ * constant digest value for files, that by function, do not have a
+ * fixed digest value, such as log files.  The pseudonym_list member
+ * of this structure points to the list of these designations.  The
+ * pseudonym_mutex structure protects this list.
+ *
+ * Like the struct tsem_context structure the tsem_model structure
+ * maintains a magazine of structures that are used to service
+ * security events that are called in atomic context.  The magazine
+ * maintained by this structure is a list of struct tsem_event_point
+ * structures that are used to describe the security state
+ * coefficients held by the model.
+ *
+ * The description of struct tsem_context details the implementation
+ * of the magazine which is identical to the implementation for this
+ * structure, with the exception of the type of structures that are
+ * held in reserve.
+ */
+struct tsem_model {
+	bool have_aggregate;
+
+	u8 base[HASH_MAX_DIGESTSIZE];
+	u8 measurement[HASH_MAX_DIGESTSIZE];
+	u8 state[HASH_MAX_DIGESTSIZE];
+
+	spinlock_t point_lock;
+	struct list_head point_list;
+	struct mutex point_end_mutex;
+	unsigned int point_count;
+	struct list_head *point_end;
+
+	spinlock_t trajectory_lock;
+	struct list_head trajectory_list;
+	struct mutex trajectory_end_mutex;
+	struct list_head *trajectory_end;
+
+	spinlock_t forensics_lock;
+	struct list_head forensics_list;
+	struct mutex forensics_end_mutex;
+	struct list_head *forensics_end;
+
+	struct mutex pseudonym_mutex;
+	struct list_head pseudonym_list;
+
+	unsigned int magazine_size;
+	spinlock_t magazine_lock;
+	unsigned long *magazine_index;
+	struct tsem_work *ws;
+	struct tsem_event_point **magazine;
+};
+
+/**
+ * struct tsem_external - TSEM external TMA description.
+ * @export_lock: The spinlock that protects access to the export_list
+ *		 member of this structure.
+ * @export_list: A pointer to the list of events waiting to be
+ *		 exported to the trust orchestrator for the security
+ *		 modeling namespace.  The structure type that is
+ *		 linked by this list is the struct export_event
+ *		 structure that is private to the export.c compilation
+ *		 unit.
+ * @dentry: A pointer to the dentry describing the pseudo-file in the
+ *	    /sys/kernel/security/tsem/ExternalTMA directory that is
+ *	    being used to export security event descriptions to the
+ *	    external trust orchestrator for the security modeling
+ *	    domain described by this structure.
+ * @have_event: A flag variable to indicate that there is work queued
+ *		on the export pseudo-file for the security modeling
+ *		namespace.
+ * @wq: The work queue used to implement polling for the security
+ *	event export file for the security modeling namespace.
+ * @magazine_size: The number of struct export_event structures that
+ *		   are held in reserve for security event hooks that
+ *		   are called in atomic context.
+ * @magazine_lock: The spinlock that protects access to the event
+ *		   magazine for the security modeling domain.
+ * @magazine_index: The bitmap that is used to track the magazine slots
+ *		    that have been allocated.
+ * @ws: An array of work structures that are used to refill the magazine
+ *	slots.
+ * @magazine: An array of pointers to struct export_event structures that
+ *	      are pre-allocated for security hooks called in atomic
+ *	      context.
+ *
+ * If an externally modeled security modeling namespace is created
+ * a structure of this type is allocated for the namespace and placed
+ * in the struct tsem_context structure.
+ *
+ * The primary purpose of this structure is to manage event
+ * descriptions that are being transmitted to the trust orchestrator
+ * associated with the security modeling namespace.  The pseudo-file
+ * will be as follows:
+ *
+ * /sys/kernel/security/tsem/ExternalTMA/N
+ *
+ * Where N is the context id number of the modeling namespace.
+ *
+ * The dentry member of this structure is used to represent the
+ * pseudo-file that is created when the external modeled namespace is
+ * created.
+ *
+ * This list of events waiting to be received by the trust
+ * orchestrator is maintained in the export_list member of this
+ * structure.  Additions or removals from the list hold the spinlock
+ * described by the export_lock member of this structure.
+ *
+ * The wq member of this structure is used to implement a workqueue
+ * to support polling for events on the export control file.  The
+ * have_event flag is set to indicate to the polling call that
+ * security events are available for export.
+ *
+ * When a security event description is exported the calling task is
+ * scheduled away to allow the trust orchestrator to process the
+ * event.  This obviously creates issues for security events that are
+ * called in atomic context.
+ *
+ * Security events in atomic context are exported as an async_event
+ * rather than a simple event.  The trust orchestrator has the option
+ * of killing the workload that deviated from the security model or
+ * signaling a violation of the model.
+ *
+ * To support the export of asynchronous events a magazine, similar to
+ * the event and model structure magazines, is maintained by this
+ * structure for the external modeling namespace.
+ */
+struct tsem_external {
+	spinlock_t export_lock;
+	struct list_head export_list;
+	struct dentry *dentry;
+	bool have_event;
+	wait_queue_head_t wq;
+
+	unsigned int magazine_size;
+	spinlock_t magazine_lock;
+	unsigned long *magazine_index;
+	struct tsem_work *ws;
+	struct export_event **magazine;
+};
+
+/**
+ * struct tsem_work - TSEM magazine refill work structure.
+ * @index: The index number of the slot in the structure magazine that
+ *	   is being refilled.
+ * @u: A union that holds pointers to the structure whose magazine is
+ *     being refilled.
+ * @work: The work structure that manages the workqueue being used to
+ *	  refill the magazine entry.
+ *
+ * As has been previously documented for the struct tsem_context,
+ * struct tsem_model and struct tsem_external structures, there is a
+ * need to maintain a magazine of these structures in order to allow
+ * the processing of security events that are called in atomic
+ * context.  An array of this structure type is embedded in each of
+ * these structures to manage the asynchronous refill of the slot in
+ * the magazine that was used to handle an atomic security event.
+ *
+ * The index member of this structure points to the slot in the
+ * magazine that this work item is referencing.
+ *
+ * The structure that the refill work is being done for is maintained
+ * in the respective structure pointer in the u member of this
+ * structure.
+ *
+ * The work member of this structure is used to reference the
+ * asynchronous work request that is being submitted for the refill.
+ */
+struct tsem_work {
+	unsigned int index;
+	union {
+		struct tsem_context *ctx;
+		struct tsem_model *model;
+		struct tsem_external *ext;
+	} u;
+	struct work_struct work;
+};
+
+/**
+ * struct tsem_COE - TSEM context of execution definition structure.
+ * @uid: The numeric user identity that the COE is running with.
+ * @euid: The effective user identity that the COE is running with.
+ * @suid: The saved user identity possessed by the COE.
+ * @gid: The group identity that the COE is running with.
+ * @egid: The effective group identity that the COE possesses.
+ * @sgid: The saved group identity of the COE.
+ * @fsuid: The filesystem user identity that the COE is running with.
+ * @fsgid: The filesystem group identity that the COE is running with.
+ * @capeff: This union is used to implement access to the effective
+ *	    capability set the COE is running with.  The mask value
+ *	    is used to assign to the structure with the value member
+ *	    used to extract the 64 bit value for export and
+ *	    computation.
+ *
+ * A security state coefficient is computed from two primary entities:
+ * the COE and the CELL identities.  This structure is used to carry
+ * and encapsulate the characteristics of the context of execution
+ * (COE) that will be used to generate the COE identity.
+ *
+ * The numeric values for discretionary access controls, ie. uid, gid,
+ * are determined by which user namespace the security modeling
+ * namespace is configured to reference.  The reference will be either
+ * the initial user namespace or the user namespace that the context
+ * of execution is running in.
+ */
+struct tsem_COE {
+	uid_t uid;
+	uid_t euid;
+	uid_t suid;
+
+	gid_t gid;
+	gid_t egid;
+	gid_t sgid;
+
+	uid_t fsuid;
+	gid_t fsgid;
+
+	union {
+		kernel_cap_t mask;
+		u64 value;
+	} capeff;
+};
+
+/**
+ * struct tsem_COE - TSEM file description.
+ * @uid: The numeric user identity of the file.
+ * @gid: The numeric group identity of the file.
+ * @mode: The discretionary access mode for the file.
+ * @flags: The file control flags.
+ * @name_length: The length of the pathname of the file.
+ * @name: The digest value of the pathname of the file using the
+ *	  hash function defined for the security modeling namespace.
+ * @s_magic: The magic number of the filesystem that the file resides
+ *	     in.
+ * @s_id: The name of the block device supporting the filesystem.
+ * @s_uuid: The uuid of the filesystem that the file resides in.
+ * @digest: The digest value of the contents of the file using the
+ *	    hash function defined for the security modeling namespace.
+ *
+ * This structure and the structures that follow up to the struct
+ * tsem_event structure are used to identify the various entities that
+ * are involved in the definition of the CELL identity for a security
+ * event.
+ *
+ * The tsem_file structure is used to encapsulate the characteristics
+ * of a file that is used as an entity in the CELL definition of an
+ * event.
+ *
+ * Since a pathname can be up to PATH_MAX (4096 bytes) in length the
+ * cryptographic digest value is used rather than the pathname of the
+ * file itself.
+ */
+struct tsem_file {
+	uid_t uid;
+	gid_t gid;
+	umode_t mode;
+	u32 flags;
+
+	u32 name_length;
+	u8 name[HASH_MAX_DIGESTSIZE];
+
+	u32 s_magic;
+	u8 s_id[32];
+	u8 s_uuid[16];
+
+	u8 digest[HASH_MAX_DIGESTSIZE];
+};
+
+/**
+ * struct tsem_COE - TSEM memory mapped file characteristics.
+ * @file: The struct file definition for the file that is being
+ *	  mapped.  This pointer will be null in the case of an
+ *	  anonymous mapping.
+ * @anonymous: A flag variable to indicate whether or not the mapping
+ *	       is file backed or anonymous.
+ * @reqprot: The memory protection flags that are requested by the
+ *	     memory mapping system call.
+ * @prot: The protections that will be applied to the mapping.
+ * @flags: The control flags of the memory mapping call.
+ *
+ * This structure is used to encapsulate the arguments provided to the
+ * tsem_mmap_file security event handler.
+ */
+struct tsem_mmap_file_args {
+	struct file *file;
+	u32 anonymous;
+	u32 reqprot;
+	u32 prot;
+	u32 flags;
+};
+
+/**
+ * struct tsem_socket_create_args - TSEM socket creation arguments.
+ * @family: The family name of the socket whose creation is being
+ *	    requested.
+ * @type: The type of the socket being created.
+ * @protocol: The protocol family of the socket being created.
+ * @kern: A flag variable to indicate whether or not the socket being
+ *	  created is kernel or userspace based.
+ *
+ * This structure is used to encapsulate the arguments provided to the
+ * tsem_socket_create security event handler.
+ */
+struct tsem_socket_create_args {
+	int family;
+	int type;
+	int protocol;
+	int kern;
+};
+
+/**
+ * struct tsem_socket_connection_args - TSEM socket connection arguments.
+ * @tsip: A pointer to the struct tsem_inode structure that describes
+ *	  the TSEM inode characteristics of the inode representing
+ *	  the socket.
+ * @addr: A pointer to the structure describing the socket address
+ *	  that is being connected.
+ * @addr_len: The length of the socket address description structure.
+ * @family: The family number of the socket.
+ *
+ * @protocol: The protocol family of the socket being created.
+ * @kern: A flag variable to indicate whether or not the socket being
+ *	  created is kernel or userspace based.
+ * @u: A union that is used to hold the family specific address
+ *     characteristics of the socket connection.
+ * @u.ipv4: If the connection is IPV4 based this structure will be
+ *	    populated with the IPV4 address information.
+ * @u.ipv6: If the connection is IPV6 based this structure will be
+ *	    populated with the IPV6 address information.
+ * @u.path: If the socket connection is an AF_UNIX based socket
+ *	    address this buffer will contain the pathname of the
+ *	    socket address.
+ * @u.mapping: If the socket represents an address protocol other
+ *	       than IPV4, IPV6 or UNIX domain this buffer will contain
+ *	       the cryptographic value of the socket address
+ *	       information using the hash function that has been
+ *	       specified for the security modeling namespace.
+ *
+ * This structure is used to encapsulate the arguments provided to the
+ * tsem_socket_create security event handler.
+ */
+struct tsem_socket_connect_args {
+	struct tsem_inode *tsip;
+	struct sockaddr *addr;
+	int addr_len;
+	u16 family;
+	union {
+		struct sockaddr_in ipv4;
+		struct sockaddr_in6 ipv6;
+		char path[UNIX_PATH_MAX + 1];
+		u8 mapping[HASH_MAX_DIGESTSIZE];
+	} u;
+};
+
+/**
+ * struct tsem_socket_accept_args - TSEM socket accept parameters.
+ * @family: The socket family identifier for the connection being
+ *	    accepted.
+ * @type: The type of socket connection being accepted.
+ * @port: The port number of the connection being accepted.
+ * @ipv4: The IPV4 address of the connection being accepted if the
+ *	  socket is representing an IPV4 connection
+ * @ipv6: The IPV6 address of the connection being accepted if the
+ *	  socket is representing an IPV6 connection.
+ * @af_unix: The UNIX domain socket address if the socket is
+ *	     representing a UNIX domain connection.
+ * @path: The pathname of the UNIX domain socket.
+ * @mapping: A cryptographic hash of description of the socket
+ *	     connection being accepted if the socket is representing
+ *	     a connection other than an IPV4, IPV6 or UNIX domain
+ *	     socket.
+ *
+ * This structure is used to encapsulate the arguments provided to the
+ * tsem_socket_accept security event handler.
+ */
+struct tsem_socket_accept_args {
+	u16 family;
+	u16 type;
+	__be16 port;
+	union {
+		__be32 ipv4;
+		struct in6_addr ipv6;
+		struct unix_sock *af_unix;
+		char path[UNIX_PATH_MAX + 1];
+		u8 mapping[HASH_MAX_DIGESTSIZE];
+	} u;
+};
+
+/**
+ * struct tsem_task_kill_args - TSEM task kill arguments.
+ * @cross_model: A flag variable used to indicate whether or not the
+ *		 signal is originating from a security modeling
+ *		 namespace other than the namespace of the target process.
+ * @signal: The number of the signal being sent.
+ * @source: The task identifier of the process sending the signal
+ * @target: The task identifier of the target process.
+ *
+ * This structure is used to encapsulate the arguments provided to the
+ * tsem_task_kill security event handler.
+ */
+struct tsem_task_kill_args {
+	u32 cross_model;
+	u32 signal;
+	u8 source[HASH_MAX_DIGESTSIZE];
+	u8 target[HASH_MAX_DIGESTSIZE];
+};
+
+/**
+ * struct tsem_event - TSEM security event description.
+ * @index: The index number of the slot in the structure magazine that
+ *	   is being refilled.
+ * @u: A union that holds pointers to the structure whose magazine is
+ *     being refilled.
+ * @work: The work structure that manages the workqueue being used to
+ *	  refill the magazine entry.
+ * @event: The enumeration type describing the security event that the
+ *	   structure is defining.
+ * @locked: A boolean flag used to indicate whether or not the
+ *	    security event is running in atomic context.
+ * @pid: The process id number, in the global pid namespace, of the
+ *	 task that is requesting approval for a security event.
+ * @pathname: If the event is referencing a file this pointer will
+ *	      point to a null-terminated buffer containing the
+ *	      pathname to the file in the mount namespace that the
+ *	      process is running in.
+ * @comm: A pointer to a null terminated buffer containing the name of
+ *	  the process that is requesting the security event.
+ * @digestsize: The size in bytes of the cryptographic hash function
+ *		that is being used in the namespace in which the event
+ *		is being recorded.
+ * @task_id: The TSEM task identifier of the process that generated the
+ *	     security event described by an instance of this
+ *	     structure.
+ * @mapping: The security state coefficient that the event described
+ *	     by this structure generates.
+ * @COE: The struct tsem_COE structure that describes the Context Of
+ *	 Execution that generated the event described by this
+ *	 structure.
+ * @file: If the security event references a file this structure will
+ *	  contain the struct tsem_file structure that describes the
+ *	  characteristics of the file.
+ * @CELL: The CELL union is used to hold the data structures that
+ *	  characterize the CELL identity of the event.
+ * @CELL.event_type: In the case of a generically modeled event this
+ *		     member will contain the enumeration value
+ *		     identifying the event.
+ * @CELL.mmap_file: The structure describing the characteristics of
+ *		    a mmap_file security event.
+ * @CELL.socket_create: The structure describing the characteristics
+ *			of a socket_create security event.
+ * @CELL.socket_connect: The structure describing the characteristics
+ *			 of a socket_connect security event.
+ * @CELL.socket_accept: The structure describing the characteristics
+ *			of a socket accept security event.
+ * @CELL.task_kill: The structure describing the characteristics of a
+ *		    task_kill security event.
+ *
+ * This structure is the primary data structure for describing
+ * security events that are registered in a security modeling
+ * namespace.  Each unique security coefficient in the namespace will
+ * have one of these structures attached to it.
+ *
+ * This structure encapsulates the following three major sources of
+ * information about the event:
+ *
+ * * A description of the process initiating the event.
+ * * The characteristics that form the COE identity of the event.
+ * * The characteristics that form the CELL identity of the event.
+ *
+ * Since one event description has to ultimately characterize any
+ * security event that can occur the strategy is to use a union that
+ * contains security event specific structures that describe the
+ * characteristics of the event.
+ *
+ * The kref member of this structure is used to signal when the
+ * structure is to be deleted.  For example, in the case of an
+ * externally modeled event, when the export of the event description
+ * is complete.  In the case of an internally modeled namespace the
+ * structure will be released if it represents a security state
+ * coefficient that is already present in the model.
+ *
+ * The work member of this structure is used to support asynchronous
+ * updates to a TPM for the root modeling domain.  Asynchronous
+ * updates are used to improve the performance of modeling and to
+ * handle security events that are running in atomic context and
+ * cannot be scheduled away while the TPM transaction completes.
+ *
+ * The tsem_event_allocate() function is called by a TSEM security
+ * event handler to allocate and populate this structure.  The struct
+ * tsem_event_parameters structure is used to encapsulate all of the
+ * different structure types that are needed to characterize all of
+ * the different security events that occur.
+ *
+ * The tsem_event_allocate() function is called by either the
+ * tsem_map_event() or tsem_map_event_locked() functions.  After
+ * allocating and populating an event description structure the
+ * mapping functions generate a security state coefficient from the
+ * information in this structure.
+ *
+ * The two separate function call points for mapping are to allow the
+ * security event handlers to indicate the context in which the
+ * security event is occurring, ie. sleeping or atomic context.  After
+ * this point the context of the security event is represented by the
+ * locked member of this structure.
+ *
+ * After the event is mapped this structure is either passed to the
+ * internal trusted modeling agent or the contents of this structure
+ * is exported to the trust orchestrator attached to the namespace for
+ * modeling by an external trust modeling agent.
+ */
+struct tsem_event {
+	struct kref kref;
+	struct list_head list;
+	struct work_struct work;
+
+	enum tsem_event_type event;
+	bool locked;
+	pid_t pid;
+	char *pathname;
+	char comm[TASK_COMM_LEN];
+
+	unsigned int digestsize;
+	u8 task_id[HASH_MAX_DIGESTSIZE];
+	u8 mapping[HASH_MAX_DIGESTSIZE];
+
+	struct tsem_COE COE;
+	struct tsem_file file;
+
+	union {
+		u32 event_type;
+		struct tsem_mmap_file_args mmap_file;
+		struct tsem_socket_create_args socket_create;
+		struct tsem_socket_connect_args socket_connect;
+		struct tsem_socket_accept_args socket_accept;
+		struct tsem_task_kill_args task_kill;
+	} CELL;
+};
+
+/**
+ * struct tsem_event_parameters - Security event argument descriptions
+ * @u: A union that encapsulates all of the different structures that
+ *     are used to characterize the argument so the TSEM security
+ *     event handlers.
+ * @u.event_type: This structure member holds the enum tsem_event_type
+ *		  enumeration value of the event whose characteristics
+ *		  are encapsulated in the function.
+ * @u.file: If the security event references a VFS file this member
+ *	    hold a pointer to the description of the file.
+ _file event.
+ * @u.socket_create: This member will point to a structure that
+ *		     describes the characteristics of a socket_create
+ *		     event.
+ * @u.socket_connect: This member will point to a structure that
+ *		      describes the characteristics of a socket_connect
+ *		      event.
+ * @u.socket_accept: This member will point to a structure that
+ *		     describes the characteristics of a socket_accept
+ *		     event.
+ * @u.task_kill: This member will point to a structure that describes
+ *		     the characteristics of a task_kill function.
+ *
+ * The purpose of this structure is to provide a common encapsulation
+ * method for passing the CELL characteristics of a security event
+ * into the tsem_event_init() function.  The characteristics passed in
+ * this event will be used to create and populate the struct
+ * tsem_event structure that will go on to be used to characterize
+ * the event either an internal or external modeling agent.
+ *
+ * The strategy followed is to allocate one of these structures on the
+ * stack for a security event call along with a call specific
+ * characteristics description structure, both of which will no longer
+ * be needed after completion of the call since the requisite
+ * information has been transferred to a struct tsem_event structure.
+ */
+struct tsem_event_parameters {
+	union {
+		u32 event_type;
+		struct file *file;
+		struct tsem_mmap_file_args *mmap_file;
+		struct tsem_socket_create_args *socket_create;
+		struct tsem_socket_connect_args *socket_connect;
+		struct tsem_socket_accept_args *socket_accept;
+		struct tsem_task_kill_args *task_kill;
+	} u;
+};
+
+/**
+ * struct tsem_event_point - TSEM security coefficient characteristics.
+ * @list: The list structure used to link together all of the security
+ *	  state coefficients for a modeling namespace.
+ * @valid: A boolean value use to indicate whether or not the security
+ *	   state point is a valid coefficient in the model.
+ * @count: The number of times this coefficient has been expressed by
+ *	   security model for the namespace.
+ * @point: The security state coefficient for the point created by
+ *	   the cryptographic hash function being used for the modeling
+ *	   namespace.
+ *
+ * This structure is used by internal trusted modeling agents to
+ * represent each unique state point in a security model.  Security
+ * state coefficients are unique within a model so only one struct
+ * tsem_event_point structure will be generated regardless of how many
+ * times the security event that generates the point occurs.  The
+ * count member of this structure represents the total number of
+ * security events that have occurred that have generated the point.
+ *
+ * The valid member of this structure is used to flag whether this
+ * is consistent with the model for the namespace or was generated by
+ * a 'forensic', ie. out of model, event.
+ *
+ * Within each security namespace these structures are linked together
+ * in a list that describes the functional value of the security model
+ * assigned to the namespace.  Entries are only added to this list and
+ * never removed.
+ *
+ * The desired state of a security model is created by using the TSEM
+ * control plane to inject a list of acceptable security state
+ * coefficients into the model.  Sealing a model causes any security
+ * events that produce a coefficient different from those already in
+ * the model to be rejected as an invalid security event and logged as
+ * a forensic event for the model.
+ */
+struct tsem_event_point {
+	struct list_head list;
+	bool valid;
+	u64 count;
+	u8 point[HASH_MAX_DIGESTSIZE];
+};
+
+/**
+ * struct tsem_inode - TSEM inode status structure.
+ * @mutex: The mutex that will protect the list of struct
+ *	   tsem_inode_digest structures that have been created for the
+ *	   inode containing a struct tsem_inode structure.
+ * @list: The list structure that points to the list of struct
+ *	  tsem_inode_structures.
+ * @status: The digest collection state of the inode.  See the
+ *	    discussion of enum tsem_inode_state for what information
+ *	    is conveyed by the value of this structure member.
+
+ * This structure is the second of the two primary control structures
+ * that are implemented through the LSM blob functionality.  It is
+ * automatically created when the inode structure is created for
+ * system resources that are referenced by a struct inode structure.
+ *
+ * This structure has two primary purposes.  The status member is used
+ * to signal that the tsem_file_open() function should return that
+ * permission to access the file is returned when the security hook is
+ * invoked by the integrity_kernel_read() function.  See the
+ * discussion on enum tsem_inode_state to more details.
+ *
+ * The second purpose of this structure is to maintain a list of
+ * digest values that have been computed by the inode that this
+ * structure references.  Maintenance of multiple digest values is
+ * required since there is no concept of a fixed digest function for
+ * TSEM as each modeling namespace can have its own digest function.
+ *
+ * Each digest value in use has a struct tsem_inode_digest structure
+ * allocated for it.  The digest_list member of this structure points
+ * to a list of these structures.
+ *
+ * The mutex implemented in this structure should be held by any
+ * process that is accessing the list.
+ */
+struct tsem_inode {
+	struct mutex mutex;
+	struct list_head digest_list;
+	enum tsem_inode_state status;
+};
+
+/**
+ * struct tsem_inode_digest - Digest specific file checksum.
+ * @list:	The list structure used to link multiple digest values
+ *		for an inode.
+ * @version:	The version number of the inode that generated the digest
+ *		value that is currently represented.
+ * @name:	A pointer to a null-terminated character buffer containing
+ *		the name of the hash function that generated the current
+ *		digest value.
+ * @value:	The digest value of the file.
+ *
+ * A linked list of these structures is maintained for each inode that
+ * is modeled by TSEM and is used to support multiple hash specific
+ * digest values for a file represented by the inode.  The tsem_inode
+ * structure that represents the TSEM security status of the inode
+ * contains the pointer to this list of structures.
+ *
+ * The version member of the structure contains the inode version number
+ * that was in effect when the last digest value of this type was computed.
+ * This version number value is used to detect changes and to trigger an
+ * update of the digest value.
+ *
+ * The name member of structure contains the name of the hash function
+ * that generated the checksum value.  This name is used to locate the
+ * correct structure by comparing its value against the hash function
+ * that is being used for the modeling domain that is accessing the
+ * inode.
+ */
+struct tsem_inode_digest {
+	struct list_head list;
+	char *name;
+	u64 version;
+	u8 value[HASH_MAX_DIGESTSIZE];
+};
+
+/*
+ * The following three variables are the only globally visible
+ * variables used in the TSEM implementation.
+ *
+ * The tsem_blob_sizes variable is used by the LSM infrastructure to
+ * describe the amount of space that will be needed by the struct
+ * tsem_task and struct tsem_inode structures.
+ *
+ * The tsem_names array is defined in the tsem.c file and contains an
+ * array of pointers to the strings that define the names for each of
+ * the TSEM security event handles.  The enum tsem_event_type
+ * enumeration indexes this array.
+ *
+ * The tsem_root_actions array is also indexed by the enum
+ * tsem_event_type enumeration and is used to determine the type of
+ * response that a TSEM security event handler is to return to the
+ * caller, ie. either logging or enforcing.  The contents of this
+ * array is inherited by copying the array into the struct
+ * tsem_context structure for modeling namespaces that are subordinate
+ * to the root model.
+ */
+extern struct lsm_blob_sizes tsem_blob_sizes;
+extern const char * const tsem_names[TSEM_EVENT_CNT];
+extern enum tsem_action_type tsem_root_actions[TSEM_EVENT_CNT];
+
+/*
+ * The following section of the file contains the definitions for the
+ * externally visible functions in each of the TSEM compilation units.
+ */
+extern struct dentry *tsem_fs_create_external(const char *name);
+extern void tsem_fs_show_trajectory(struct seq_file *c, struct tsem_event *ep);
+extern void tsem_fs_show_field(struct seq_file *c, const char *field);
+extern void tsem_fs_show_key(struct seq_file *c, char *term, char *key,
+			     char *fmt, ...);
+extern int tsem_fs_init(void);
+
+extern struct tsem_model *tsem_model_allocate(size_t size);
+extern void tsem_model_free(struct tsem_context *ctx);
+extern int tsem_model_event(struct tsem_event *ep);
+extern int tsem_model_load_point(u8 *point);
+extern int tsem_model_load_pseudonym(u8 *mapping);
+extern int tsem_model_has_pseudonym(struct tsem_inode *tsip,
+				    struct tsem_file *ep);
+extern void tsem_model_load_base(u8 *mapping);
+extern int tsem_model_add_aggregate(void);
+extern void tsem_model_compute_state(void);
+extern void tsem_model_magazine_free(struct tsem_model *model);
+extern int tsem_model_cache_init(struct tsem_model *model, size_t size);
+
+extern void tsem_ns_put(struct tsem_context *ctx);
+extern int tsem_ns_event_key(u8 *task_key, const char *keystr, u8 *key);
+extern int tsem_ns_create(const enum tsem_control_type type,
+			  const char *digest, const enum tsem_ns_reference ns,
+			  const char *key, const unsigned int cache_size);
+
+extern int tsem_export_show(struct seq_file *m, void *v);
+extern int tsem_export_event(struct tsem_event *ep);
+extern int tsem_export_action(enum tsem_event_type event, bool locked);
+extern int tsem_export_aggregate(void);
+extern int tsem_export_magazine_allocate(struct tsem_external *ext,
+					 size_t size);
+extern void tsem_export_magazine_free(struct tsem_external *ext);
+extern int tsem_export_cache_init(void);
+
+extern int tsem_map_task(struct file *file, u8 *mapping);
+struct tsem_event *tsem_map_event(enum tsem_event_type event,
+				  struct tsem_event_parameters *param);
+struct tsem_event *tsem_map_event_locked(enum tsem_event_type event,
+					 struct tsem_event_parameters *param);
+
+extern struct tsem_event *tsem_event_allocate(bool locked);
+extern struct tsem_event *tsem_event_init(enum tsem_event_type event,
+					  struct tsem_event_parameters *params,
+					  bool locked);
+extern void tsem_event_put(struct tsem_event *ep);
+extern void tsem_event_get(struct tsem_event *ep);
+extern int tsem_event_magazine_allocate(struct tsem_context *ctx, size_t size);
+extern void tsem_event_magazine_free(struct tsem_context *ctx);
+extern int tsem_event_cache_init(void);
+
+extern u8 *tsem_trust_aggregate(void);
+extern int tsem_trust_add_event(struct tsem_event *ep);
+
+/*
+ * The remaining inline function declarations follow the design
+ * pattern of the other LSM's and implement functions that return
+ * various TSEM characteristics of tasks, modeling contexts and
+ * inodes.
+ */
+static inline struct tsem_task *tsem_task(struct task_struct *task)
+{
+	return task->security + tsem_blob_sizes.lbs_task;
+}
+
+static inline bool tsem_task_trusted(struct task_struct *task)
+{
+	return tsem_task(task)->trust_status & TSEM_TASK_TRUSTED;
+}
+
+static inline bool tsem_task_untrusted(struct task_struct *task)
+{
+	return tsem_task(task)->trust_status & ~TSEM_TASK_TRUSTED;
+}
+
+static inline struct tsem_context *tsem_context(struct task_struct *task)
+{
+	return tsem_task(task)->context;
+}
+
+static inline struct tsem_model *tsem_model(struct task_struct *task)
+{
+	return tsem_task(task)->context->model;
+}
+
+static inline struct tsem_inode *tsem_inode(struct inode *inode)
+{
+	return inode->i_security + tsem_blob_sizes.lbs_inode;
+}
+
+static inline struct crypto_shash *tsem_digest(void)
+{
+	return tsem_context(current)->tfm;
+}
+
+static inline unsigned int tsem_digestsize(void)
+{
+	return crypto_shash_digestsize(tsem_digest());
+}