All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/14] Implement Trusted Security Event Modeling.
@ 2023-02-04  5:09 Dr. Greg
  2023-02-04  5:09 ` [PATCH 01/14] Update MAINTAINERS file Dr. Greg
                   ` (14 more replies)
  0 siblings, 15 replies; 42+ messages in thread
From: Dr. Greg @ 2023-02-04  5:09 UTC (permalink / raw)
  To: linux-security-module

This patch series implements Trusted Security Event Modeling (TSEM) as
a new Linux Security Module (LSM) architecture.

At a conceptual level, TSEM can be thought of as an integration of
integrity measurement and mandatory access controls.  TSEM brings to
Linux security, a new model for implementing security controls that is
unique among current operating system platforms.

TSEM is designed to support the concept of a Trust Orchestration
System (TOS).  Trust orchestration involves the process of modeling
the security behavior of a workload, or a platform at large, and
defining whether or not a process is to be trusted, based on whether
or not the security events that it produces are consistent with a
security model that has been designed for a workload or platform.

TSEM operates under the premise, that security, like all other
physical phenomena in science and engineering, can be mathematically
modeled.  TSEM notionally treats the LSM security event hooks as a
basis set that is capable of generating a functional value for a
security model.

To support this notion, TSEM implements, entirely within the context
of the LSM architecture, the notion of security modeling domains which
are akin to resource namespaces.  A modeling domain is designed to be
paired with a Trusted Modeling Agent (TMA) that implements the root of
trust for a security domain/namespace.

A TMA implementation uses the descriptive parameters of a security
event hook to compute task specific coefficients for each security
event that occurs in a modeling domain.  The sum of these
coefficients, represents the security 'state' of the model.  These
coefficients, nee state points, for a security model are designed to
be developed by unit testing of an application stack.

TSEM thus represents a security architecture designed to support
modern software development strategies that are embracing
resource containerization and continuous integration and
development practices.  The objective of TSEM, along with
Quixote, it's userspace TOS implementation, is to bring to Linux
integrity and mandatory what Docker brought to Linux resource
namespaces.

The Quixote TOS has implementations of trust orchestrator's for the
following TMA trust roots:

Kernel.

Userspace process.

SGX enclave.

Xen Hypervisor domain.

Hardware based security coprocessors.

One of the objectives for Quixote/TSEM is to provide a framework for
developing next generation security co-processor technology that
extends beyond what is currently represented in the form of Trusted
Platform Modules.

Included with the Quixote TOS is an implementation of a security
co-processor based on the Nordic NRF52840-DONGLE micro-controller.
This is a USB form factor device that is currently being used for
projects such as GOOGLE's OpenSK security key initiative and 3mdeb's
Fobnail attestation server project.

Included in the patch series is an extensive documentation file that
can be found in the following location after the series is applied:

Documentation/admin-guide/LSM/tsem.rst

Reviewers, and other who are interested, are referred to this
document for a more extensive discussion into the rationale,
design and implementation of the TSEM architecture.

Control of TSEM is surfaced entirely through the tsemfs filesystem
that has the following mountpoint:

/sys/fs/tsem

TSEM is designed to be largely self-contained and independent of the
kernel at large and other LSM's.  It operates without the need for
filesystem labeling or cryptographic integrity protection of
filesystem metadata.

Source code for the userspace trust orchestration system and
pre-compiled binariesare available at the following location:

ftp://ftp.enjellic.com/pub/Quixote

The Quixote/TSEM TMA currently implements a very simple deterministic
security model.  The architecture is designed to provide a flexible
framework to support the potential implementation of more advanced
models that use stochastics, inference or other machine learning
methodologies.

Dr. Greg (14):
  Update MAINTAINERS file.
  Add TSEM specific documentation.
  Add magic number for tsemfs.
  Implement CAP_TRUST capability.
  Add TSEM master header file.
  Add primary TSEM implementation file.
  Add root domain trust implementation.
  Implement TSEM control plane.
  Add namespace implementation.
  Add security event description export facility.
  Add event description implementation.
  Implement security event mapping.
  Implement an internal Trusted Modeling Agent.
  Activate the configuration and build of the TSEM LSM.

 Documentation/ABI/testing/tsemfs              |  576 ++++++
 Documentation/admin-guide/LSM/index.rst       |    1 +
 Documentation/admin-guide/LSM/tsem.rst        | 1240 ++++++++++++
 .../admin-guide/kernel-parameters.txt         |    5 +
 MAINTAINERS                                   |    8 +
 include/uapi/linux/capability.h               |    6 +-
 include/uapi/linux/magic.h                    |    1 +
 security/Kconfig                              |   11 +-
 security/Makefile                             |    1 +
 security/selinux/include/classmap.h           |    2 +-
 security/tsem/Kconfig                         |   22 +
 security/tsem/Makefile                        |    2 +
 security/tsem/event.c                         |  474 +++++
 security/tsem/export.c                        |  388 ++++
 security/tsem/fs.c                            |  894 ++++++++
 security/tsem/map.c                           |  497 +++++
 security/tsem/model.c                         |  598 ++++++
 security/tsem/namespace.c                     |  226 +++
 security/tsem/trust.c                         |  134 ++
 security/tsem/tsem.c                          | 1801 +++++++++++++++++
 security/tsem/tsem.h                          |  388 ++++
 21 files changed, 7268 insertions(+), 7 deletions(-)
 create mode 100644 Documentation/ABI/testing/tsemfs
 create mode 100644 Documentation/admin-guide/LSM/tsem.rst
 create mode 100644 security/tsem/Kconfig
 create mode 100644 security/tsem/Makefile
 create mode 100644 security/tsem/event.c
 create mode 100644 security/tsem/export.c
 create mode 100644 security/tsem/fs.c
 create mode 100644 security/tsem/map.c
 create mode 100644 security/tsem/model.c
 create mode 100644 security/tsem/namespace.c
 create mode 100644 security/tsem/trust.c
 create mode 100644 security/tsem/tsem.c
 create mode 100644 security/tsem/tsem.h

-- 
2.39.1

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 01/14] Update MAINTAINERS file.
  2023-02-04  5:09 [PATCH 00/14] Implement Trusted Security Event Modeling Dr. Greg
@ 2023-02-04  5:09 ` Dr. Greg
  2023-02-04  5:09 ` [PATCH 02/14] Add TSEM specific documentation Dr. Greg
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 42+ messages in thread
From: Dr. Greg @ 2023-02-04  5:09 UTC (permalink / raw)
  To: linux-security-module

Add an entry to the MAINTAINERS file to document the maintainer's
address and files relevant to the Trusted Security Event Modeling
system (TSEM).

Signed-off-by: Greg Wettstein <greg@enjellic.com>
---
 MAINTAINERS | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8a5c25c20d00..b939dc482145 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -18836,6 +18836,14 @@ F:	include/uapi/linux/selinux_netlink.h
 F:	scripts/selinux/
 F:	security/selinux/
 
+TSEM SECURITY MODULE
+M:	Greg Wettstein <greg@enjellic.com>
+S:	Supported
+L:	linux-security-module@vger.kernel.org
+F:	Documentation/admin-guide/LSM/tsem.rst
+F:	Documentation/ABI/testing/tsemfs
+F:	security/tsem/
+
 SENSABLE PHANTOM
 M:	Jiri Slaby <jirislaby@kernel.org>
 S:	Maintained
-- 
2.39.1


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 02/14] Add TSEM specific documentation.
  2023-02-04  5:09 [PATCH 00/14] Implement Trusted Security Event Modeling Dr. Greg
  2023-02-04  5:09 ` [PATCH 01/14] Update MAINTAINERS file Dr. Greg
@ 2023-02-04  5:09 ` Dr. Greg
  2023-02-09 11:47   ` Greg KH
  2023-02-13  4:33   ` Paul Moore
  2023-02-04  5:09 ` [PATCH 03/14] Add magic number for tsemfs Dr. Greg
                   ` (12 subsequent siblings)
  14 siblings, 2 replies; 42+ messages in thread
From: Dr. Greg @ 2023-02-04  5:09 UTC (permalink / raw)
  To: linux-security-module

An entry was added to the ABI testing documentation to document
the files in the TSEM management filesystem.

The file documenting the kernel command-line parameters was
updated to document the tsem_mode command-line parameter.

The primary TSEM documentation file was added to the LSM
administration guide and the file was linked to the index of LSM
documentation.

Signed-off-by: Greg Wettstein <greg@enjellic.com>
---
 Documentation/ABI/testing/tsemfs              |  576 ++++++++
 Documentation/admin-guide/LSM/index.rst       |    1 +
 Documentation/admin-guide/LSM/tsem.rst        | 1240 +++++++++++++++++
 .../admin-guide/kernel-parameters.txt         |    5 +
 4 files changed, 1822 insertions(+)
 create mode 100644 Documentation/ABI/testing/tsemfs
 create mode 100644 Documentation/admin-guide/LSM/tsem.rst

diff --git a/Documentation/ABI/testing/tsemfs b/Documentation/ABI/testing/tsemfs
new file mode 100644
index 000000000000..3d326934624c
--- /dev/null
+++ b/Documentation/ABI/testing/tsemfs
@@ -0,0 +1,576 @@
+What:		/sys/fs/tsem
+Date:		November 2022
+Contact:	Greg Wettstein <greg@enjellic.com>
+Description:
+		The /sys/fs/tsem directory contains files and one
+		directory that implement the control plane for the
+		Trusted Security Event Modeling (TSEM) LSM.
+
+		The files in this directory, with the exception of the
+		aggregate file, when read, reflect the values for the
+		modeling domain/namespace that the process reading the
+		files is operating in.
+
+What:		/sys/fs/tsem/aggregate
+Date:		November 2022
+Contact:	Greg Wettstein <greg@enjellic.com>
+Description:
+		The aggregate file contains the ASCII base 16
+		representation of the 256 bit hardware platform
+		aggregate that TSEM is modeling under.  The platform
+		aggregate is the extension measurement of the Trusted
+		Platform Module PCR registers 0 through 8.
+
+What:		/sys/fs/tsem/forensics
+Date:		November 2022
+Contact:	Greg Wettstein <greg@enjellic.com>
+Description:
+		The forensics file contains the descriptions of
+		security events that are inconsistent with the
+		security model that the domain/namespace is running
+		under.  Forensics events are generated after a
+		security model is 'sealed' and the events represent
+		security state points that have not already been
+		defined in the model.
+
+		The format of lines in this file are identical to the
+		output generated by the /sys/fs/tsem/trajectory file
+		that is documented below.
+
+What:		/sys/fs/tsem/id
+Date:		November 2022
+Contact:	Greg Wettstein <greg@enjellic.com>
+Description:
+		The id file contains the ASCII base 10 representation
+		of the model domain/namespace identifier that the
+		reading process is operating in.
+
+		The root domain/namespace has a value of zero, with a
+		non-zero value representing a modeling domain
+		independent from the root model.
+
+		A domain with a non-zero id value, that is externally
+		modeled.  Each externally modeled domain will have a
+		file created in the /sys/fs/tsem/ExternalTMA directory
+		that is documented at the end of this document.
+
+What:		/sys/fs/tsem/measurement
+Date:		November 2022
+Contact:	Greg Wettstein <greg@enjellic.com>
+Description:
+		The measurement file contains the ASCII base 16
+		hexadecimal representation of the 256 bit measurement
+		value of the security model that the process is
+		operating in.
+
+		The measurement value is the classic linear extension
+		measurement of the model.  An updated measurement
+		value is created by extending the current measurement
+		value with the state coefficient computed for a
+		security event.
+
+		This measurement value represents a time dependent
+		measurement of a model and is susceptible to
+		deviations caused by scheduling differences between
+		subsequent invocations of a workload.
+
+What:		/sys/fs/tsem/points
+Date:		November 2022
+Contact:	Greg Wettstein <greg@enjellic.com>
+Description:
+		The points file contains the ASCII base 16
+		representation of the 256 bit security state points of
+		a security domain/model.  The number of entries in
+		this file represent the number of security events that
+		are represented by the model.
+
+What:		/sys/fs/tsem/state
+Date:		November 2022
+Contact:	Greg Wettstein <greg@enjellic.com>
+Description:
+		The state file contains the ASCII base 16
+		representation of the 256 bit value of the functional
+		state of a security domain/model.
+
+		The state value is a time independent representation
+		of the measurement of a model/domain, and unlike the
+		measurement value, is a time independent
+		representation of the security state of a workload.
+
+		This value is designed to be a single value that can
+		be attested to represent whether or not a workload has
+		deviated from a defined security behavior.
+
+What:		/sys/fs/tsem/trajectory
+Date:		November 2022
+Contact:	Greg Wettstein <greg@enjellic.com>
+Description:
+		The trajectory file contains a description of the
+		security events that have occurred in a security
+		domain/model.
+
+		Each entry in this file represents a single security
+		event and consists of brace {} delimited fields that
+		describe the characteristics of a security event.
+		Each field has key=value pairs that define
+		characteristics of the field.
+
+		Each line in a trajectory, or forensics, file will
+		always have the event{} and COE{} fields.  The event
+		field describes the characteristics of a security
+		event while the COE field describes the Context Of
+		Execution that is executing the security event.
+
+		The event{} field consists of the following
+		characteristic definitions:
+
+			process=COMM
+				Where COMM is the ASCII representation
+				of the name of the process executing
+				the event.
+
+			filename=PATH
+				If the CELL definition for an event
+				references a file the filename
+				characteristic contains a definition
+				of the path to the file.
+
+				In the case where an event does not
+				have a file the PATH value is set to a
+				value of none.
+
+			type=EVENT_TYPE
+				The value field for a type key is the
+				name of the security event that is
+				being modeled.  The list of value
+				EVENT_TYPE names is defined in the
+				following source file:
+
+				security/tsem/tsem.c
+
+				If the security event is a generically
+				modeled event the EVENT_TYPE will be
+				generic_event.  In this case the CELL
+				characteristics for the event will be
+				described by a generic_event{} field.
+
+			task_id=TASK_ID
+				The value of the task_id key will the
+				ASCII base 16 representation of the
+				model identity of the task that is
+				executing the security event.
+
+				The following documentation file:
+
+				Documentation/admin-guide/LSM/TSEM.rst
+
+				Describes how the TASK_ID value is
+				generated.
+
+		The COE{} field consists of the following
+		characteristic definitions:
+
+			uid=NN
+				The ASCII base 10 representation of
+				the numeric value of the discretionary
+				user id of the process that is
+				executing the security event.
+
+			euid=NN
+				The ASCII base 10 representation of
+				the numeric value of the effective
+				discretionary user id of the process
+				that is executing the security event.
+
+			euid=NN
+				The ASCII base 10 representation of
+				the numeric value of the effective
+				discretionary user id of the process
+				that is executing the security event.
+
+			suid=NN
+				The ASCII base 10 representation of
+				the numeric value of the saved user id
+				of the process that is executing the
+				security event.
+
+			gid=NN
+				The ASCII base 10 representation of
+				the numeric value of the discretionary
+				group id of the process that is
+				executing the security event.
+
+			egid=NN
+				The ASCII base 10 representation of
+				the numeric value of the discretionary
+				effective group id of the process that
+				is executing the security event.
+
+			egid=NN
+				The ASCII base 10 representation of
+				the numeric value of the discretionary
+				effective group id of the process that
+				is executing the security event.
+
+			sgid=NN
+				The base 10 ASCII representation of
+				the numeric value of the saved
+				discretionary group id of the process
+				that is executing the security event.
+
+			fsuid=NN
+				The base 10 ASCII representation of
+				the numeric value of the discretionary
+				filesystem user id of the process that
+				is executing the security event.
+
+			fsgid=NN
+				The ASCII base 10 representation of
+				the numeric value of the discretionary
+				filesystem group id of the process
+				that is executing the security event.
+
+			cap=0xNNN
+				The ASCII base 16 representation of
+				the numeric value of effective
+				capabilities of the process that is
+				executing the security event.
+
+		If the CELL value for a security event includes the
+		definition of a file a file{} event field will be
+		included.  The following characteristics will be
+		encoded in this field:
+
+			flags=NN
+				The ASCII base 10 representation of
+				the flags value of the 'struct file'
+				structure that is the source of the
+				file description.
+
+			uid=NN
+				The ASCII base 10 representation of
+				the discretionary user id of the file.
+
+			gid=NN
+				The base 10 ASCII representation of
+				the discretionary group id of the
+				file.
+
+			mode=0NNN
+				The ASCII base 8 representation of the
+				mode bits of the file.
+
+			name_length=NN
+				The ASCII base 10 representation of
+				the length of the pathname that will
+				be encoded in the name= characteristic.
+
+			name=NN
+				The ASCII hexadecimal representation
+				of the SHA256 checksum of the pathname
+				of the file that is pre-pended with
+				the little-endian binary value of the
+				length of the pathname.
+
+			s_magic=0xNN
+				The ASCII base 16 representation of the
+				magic number of the filesystem that
+				contains the file.
+
+			s_id=NAME
+				The ASCII name of the block device for
+				the filesystem that contains the file.
+
+			s_UUID=HEX
+				The ASCII base 16 representation of
+				the hexadecimal value of the UUID of
+				the filesystem that contains the file.
+
+			digest=HEX
+				The ASCII base 16 representation of
+				the SHA256 digest of the file.
+
+		If the event type is the memory mapping of a file the
+		mmap_file{} event description will be included with
+		the following characteristics:
+
+			type=N
+				Where N is an ASCII 0 or 1 to indicate
+				whether or not the mapping is file
+				backed or anonymous.  A value of 1 is
+				used to indicate an anonymous mapping.
+
+			reqprot=NN
+				Where N is ASCII base 10
+				representation of the protections
+				requested for the mapping.
+
+			prot=NN
+				Where N is the ASCII base 10
+				representation of the protections that
+				will be applied to the mapping.
+
+			flags=NN
+				Where N is the ASCII base 10
+				representation of the flags that will
+				be used for the memory mapping operation.
+
+		If the event type is a socket creation event the
+		socket_create{} event description will be included
+		with the following characteristics:
+
+			family=N
+				Where N is the ASCII base 10
+				representation of the family of the
+				socket that is being created.
+
+			type=N
+				Where N is the ASCII base 10
+				representation of the type of the
+				socket being created.
+
+			protocol=N
+				Where N is the ASCII base 10
+				representation of the socket protocol.
+
+			kern=N
+				Where N is an ASCII 0 or 1 that is
+				used to represent whether or not this
+				is a kernel base socket.  A value of 1
+				indicates a kernel based socket.
+
+		If the event type is a socket creation event the
+		socket_create{} event description will be included
+		with the following characteristics:
+
+		If the event type is a socket_connect or a socket_bind,
+		a socket_connect{} or a socket_bind{} field will be
+		included that will be characterized based on an
+		encoding of either an IPV4, IPV6 or a generic socket
+		description.
+
+			family=N
+				Where N is the ASCII base 10
+				representation of the family type of
+				the socket.
+
+			port=N
+				Where N is the base ASCII base 10
+				representation of the port number that
+				is being used for either an IPV4 or
+				IPV6 socket connection or bind.
+
+			addr=N | HEXID
+				In the case of an IPV4 socket the
+				value for the addr key will be the
+				ASCII base 10 representation of the 32
+				bit IPV4 address being bound or
+				connected to.
+
+				In case case of an IPV6 connection the
+				value to the key will be the ASCII
+				base 16 representation of the 128 bit
+				address being bound connected.
+
+				In the case of any other type of
+				socket the addr value will be the
+				ASCII base 16 representation of the
+				SHA256 checksum over the entire length
+				of the address description.
+
+			flow=N
+				For an IPV6 socket the value of the
+				flow key will be the ASCII base 10
+				representation of the flow identifier
+				assigned to the socket.
+
+			scope=N
+				For an IPV6 socket the value of the
+				scope key will be the ASCII base 10
+				representation of the scope identifier
+				assigned to the socket.
+
+		If the event type is a socket_accept a socket_accept{}
+		field will be included characterizes either an IPV4,
+		IPV6 or a generic socket description with the
+		following event descriptions:
+
+			family=N
+				Where N is the ASCII base 10
+				representation of the family type of
+				the socket.
+
+			type=N
+				Where N is the ASCII base 10
+				representation of the type of the
+				socket being created.
+
+			port=N
+				Where N is the base ASCII base 10
+				representation of the port number that
+				is being used for either an IPV4 or
+				IPV6 socket connection or bind.
+
+			addr=N | HEXID
+				In the case of an IPV4 socket the
+				value for the addr key will be the
+				ASCII base 10 representation of the 32
+				bit IPV4 address being bound or
+				connected to.
+
+				In case case of an IPV6 connection the
+				value to the key will be the ASCII
+				base 16 representation of the 128 bit
+				address being bound connected.
+
+				In the case of any other type of
+				socket the addr value will be the
+				ASCII base 16 representation of the
+				SHA256 checksum over the entire length
+				of the address description.
+
+What:		/sys/fs/tsem/ExternalTMA
+Date:		November 2022
+Contact:	Greg Wettstein <greg@enjellic.com>
+Description:
+		The ExternalTMA directory is a container directory
+		that hold files that will be used to export the
+		security events, and their associated parameters, for
+		externally modeled security domains/namespaces.
+
+		The files created in this directory will be named by
+		the base 10 ASCII representation of the id value
+		assigned to the modeling domain/namespace.  See the
+		documentation for the /sys/fs/tsem/id file in this
+		documentation for more details on this value.
+
+		This file will is a read-only file that can be polled
+		by a userspace trust orchestration implementation to
+		process security events that are to be modeled by
+		an external Trusted Modeling Agent.
+
+		The type of the exported event is the first keyword of
+		the line that is output and have the following
+		values and arguments:
+
+		aggregate HEXID:
+			Where HEXID is the ASCII base 16
+			representation of the 256 bit hardware
+			platform aggregate value.
+
+		export pid{NNN} COE{} CELL_DEFINITION
+			Where the NNN in the pid field is the ASCII
+			base 10 value of the id of the process that is
+			executing the security event that will be
+			modeled.
+
+			The COE field has the same format as the field
+			emitted for a trajectory or forensics event.
+
+			The CELL_DEFINITION are the same field
+			definitions that are emitted for a trajectory
+			or forensics event.
+
+		log process{name} event{type} action{type}
+			The log event is emitted when an untrusted
+			task attempts to execute a security event.
+
+			The name value of the COE field is the name of
+			the process (comm value) that is executing the
+			security event.
+
+			The type value of the event field is the name
+			of the security event being executed as
+			defined in the tsem_names array in the
+			security/tsem/tsem.c file.
+
+			The type value of the action field is the type
+			of action the LSM enforced in response to
+			encountering the untrusted process.  This
+			value will be either LOG or EPERM to represent
+			whether or not the trust violation is being
+			logged or enforced.
+
+What:		/sys/fs/tsem/control
+Date:		November 2022
+Contact:	Greg Wettstein <greg@enjellic.com>
+Description:
+		The control file is the only writable file in the
+		filesystem and is used by the trust orchestrators to
+		configure and control the behavior of the TSEM
+		implementation.
+
+		The following keyword and arguments are recognized:
+
+		internal:
+			The internal keyword causes an internally
+			modeled domain to be created for the calling
+			process.
+
+		external:
+			The external keyword causes an externally
+			modeled domain to be created for the calling
+			process.
+
+		enforce:
+			The enforce keyword causes the modeling
+			domain/namespace of the process to enter
+			enforcing mode.  In this mode a value of
+			-EPERM will be returned for a security event
+			that does not map into the current set of
+			allowed state points for the security model
+			being implemented for the domain/namespace.
+
+		seal:
+			The seal keyword causes the security model
+			being implemented for the model to be placed
+			in sealed state.  In this state the current
+			set of security event points is considered to
+			be the only set of valid points for the
+			domain/model.  Any subsequent events that map
+			to a point not in the current model will be
+			considered a violation of the model.
+
+		trusted PID:
+			The trusted keyword is used by a trust
+			orchestrator to indicate that the process
+			identified by the PID argument should be
+			allowed to run in trusted status.
+
+		untrusted PID:
+			The untrusted keyword is used by a trust
+			orchestrator to indicate that the process
+			identified by the PID argument should be
+			allowed to run but designated as an untrusted
+			process.
+
+		state HEXID:
+			The state keyword is used to indicate that the
+			security state point identified by the ASCII
+			base 16 encoded value should be loaded into
+			the current security model as a valid security
+			event state.
+
+		pseudonym HEXID
+			The pseudonym keyword is used to indicate that
+			the pathname, identified by the 256 bit ASCII
+			base 16 encoded value HEXID, should be
+			designated to return a constant digest value
+			for the contents of the file.
+
+			The HEXID value is computed with the following
+			function:
+
+			HEXID = SHA256(PATHNAME_LENGTH || PATHNAME)
+
+		base HEXID
+			The base keyword is used to indicate that the
+			256 bit ASCII base 16 encoded value HEXID
+			should be registered as the value used to
+			generate model specific security event points.
+
+			A model specific base value is designed to be
+			used as a 'freshness' nonce, similar to an
+			attestation nonce, to prove that a model state
+			value or measurement is current and not being
+			replayed.
diff --git a/Documentation/admin-guide/LSM/index.rst b/Documentation/admin-guide/LSM/index.rst
index a6ba95fbaa9f..cebd3b02598d 100644
--- a/Documentation/admin-guide/LSM/index.rst
+++ b/Documentation/admin-guide/LSM/index.rst
@@ -47,3 +47,4 @@ subdirectories.
    tomoyo
    Yama
    SafeSetID
+   tsem
diff --git a/Documentation/admin-guide/LSM/tsem.rst b/Documentation/admin-guide/LSM/tsem.rst
new file mode 100644
index 000000000000..f03e5269cd25
--- /dev/null
+++ b/Documentation/admin-guide/LSM/tsem.rst
@@ -0,0 +1,1240 @@
+====
+TSEM
+====
+
+	"This is the story of the wine of Brule, and it shows what
+	 men love is never money itself but their own way, and
+	 that human beings love sympathy and pageant above all
+	 things."
+				- Hilaire Belloc
+				  The Path to Rome
+
+TSEM is the Trusted Security Event Modeling system.  Conceptually it
+can be thought of as an integration of system integrity measurement
+and mandatory access controls.
+
+The design and implementation of TSEM was inspired by the notion that
+the security behavior of a platform, or a workload, like all other
+physical phenomenon, can be mathematically modeled.
+
+Security, is at once, both a technical and economic problem.  One of
+the objectives of TSEM is to address inherent and structural economic
+barriers to security, by introducing technology that reduces the skill
+and time needed to implement a level of security, equivalent to what
+can be achieved by mandatory access controls, through unit testing of
+an application stack.
+
+A second objective, is to reduce the skill, complexity and
+infrastructure needed to create remotely attestable platforms and/or
+workloads.
+
+To achieve these objectives, TSEM implements the concept of a modeling
+domain, nee namespace, that reduces the complexity of a security model
+and allows it to be scoped to the level of a single process or a
+container.
+
+TSEM is the Linux kernel component of a security concept introduced by
+the Quixote Project, the notion of a Trust Orchestration System (TOS).
+The concept of a TOS is to have a system with a minimal Trusted
+Computing Base (TCB) that supervises and maintains subordinate
+modeling domains/namespaces in a known trust state.
+
+TSEM is implemented as a Linux Security Module (LSM) and is designed
+to be self-contained with little or no dependency on kernel
+infrastructure, other than the LSM hooks themselves.  It can be
+stacked in any order with existing LSM's.  Integrity modeling of
+extended attributes would require that TSEM be earlier in the LSM call
+chain then any LSM's that consume the modeled attributes.
+
+In addition, TSEM implements its equivalent of mandatory access
+controls, without a requirement for extended attributes, filesystem
+labeling or the need to protect filesystem metadata against offline
+attack.
+
+TBDHTTRAD
+=========
+
+A quick summary for those interested in experimenting with trust
+orchestration and security modeling but are constrained by: 'Too Busy
+Don't Have Time To Read Any Documentation'.
+
+A kernel with TSEM support in its list of enabled LSM's must be
+available for use.  A TSEM enabled kernel will have the tsem keyword
+in the following file:
+
+/sys/kernel/security/lsm
+
+The trust orchestrators need to have access to the TSEM management
+filesystem, that after boot, can be mounted with the following
+command:
+
+mount -t tsemfs tsemfs /sys/fs/tsem
+
+For experimentation, or integrating TSEM modeling into a CI
+development workflow, modeling can be restricted to subordinate
+modeling domains by booting a kernel with the following kernel
+command-line option:
+
+tsem_mode=1
+
+The Quixote trust orchestration utilities either need to be built or
+the statically compiled demonstration system needs to be installed.
+Source for the userspace utilities and compiled sample programs are
+available at the following location:
+
+ftp://ftp.enjellic.com/pub/Quixote
+
+After installing the utilities, two shell sessions will be needed with
+root privileges in each shell.
+
+The following directories need to be in the PATH variable of each shell:
+
+/opt/Quixote/sbin
+/opt/Quixote/bin
+
+Execute the following command to start a process in an independent
+modeling domain/namespace with the security modeling being done in the
+kernel:
+
+quixote -P -c test -o test.model
+
+In the second shell session, run the following command to display the
+security execution trajectory of the model:
+
+quixote-console -p test -T
+
+In the shell session provided by the trust orchestrator, run the
+following command:
+
+grep SOME_STRING /etc/passwd
+
+Then exit the shell.
+
+The orchestrator will indicate that the security model definition has
+been written to the test.model file.
+
+Run the following command to execute a shell in an enforced security
+model obtained from the previous session:
+
+quixote -P -c test -m test.model -e
+
+In the shell that is provided, run the following command:
+
+cat /etc/passwd
+
+The command will fail.
+
+Running the following command in the second shell session will output
+forensics on the command that failed:
+
+quixote-console -p test -F
+
+Executing additional commands in the trust orchestrated shell will
+cause additional entries to be added to the forensics trajectory.
+
+The test can be repeated using the quixote-us trust orchestrator.
+This test will model the security domain/namespace in a userspace
+process rather than in the kernel based modeling agent.
+
+Mandatory Access Controls
+=========================
+
+	"If I have seen further it is by standing on the shoulders of
+	 Giants."
+				- Sir Isaac Newton
+
+It is assumed that astute readers will be familiar with classic
+subject/object based mandatory access controls; or at least astute
+enough to use a search engine to develop a modicum of secundem artem
+in the discipline.
+
+Very simplistically, subject/object based mandatory access controls
+can be thought of as being implemented with a two dimensional access
+vector matrix, with some type of a description of a process (subject)
+on one axis and a description of a data sync/source (object),
+typically an inode, on the second axis.  The descriptions are
+commonly referred to as subjects and objects.
+
+A security policy is developed that assigns a boolean value for each
+element of the matrix that specifies whether or not permission should
+be granted for the subject to access the object.
+
+These schemes are frequently referred to as 'mandatory access
+controls', since only the kernel has the ability to implement the
+labeling and decision process.  In these systems, the root or
+administrative user has no ability to affect the kernel decision
+making with respect to whether or not permission is granted or denied.
+
+These systems were derived from governmental and military information
+classification systems and are capable of delivering security
+guarantees appropriate to classified and high sensitivity assets.  The
+delivery of these security guarantees comes with it a reputation for
+complexity and fragility.
+
+Development of a system wide security policy is a complex process and
+administration of such systems is frequently done in an iterative
+fashion.  The system is monitored for permission denials with
+modifications to correct these false denials folded back into the
+policy.  In many cases, mandatory access control systems are run in
+warning rather than enforcing mode and used as an indicator for
+potential security violations.
+
+One of the additional challenges is that the integrity of labels is
+fundamental to the ability of these systems to deliver their security
+guarantees.  This requires that the labeling process be conducted
+under security controlled conditions with the labels protected against
+offline modification by cryptographic integrity guarantees.
+
+Mandatory access controls had their origin in centralized multi-user
+platforms, and before the now, widely accepted strategy of using
+resource compartmentalization (namespaces) to isolate applications
+from each other and the system at large.  A legitimate technical
+argument can be made as to whether or not enforcement of a system wide
+security policy is suitable for these environments.
+
+At the other end of the spectrum, in embedded systems, structural
+economic barriers incent very little attention to security, where time
+to market is the primary goal.  These systems are pushed into the
+field, many time for multi-year operational lifetimes, with little
+prospect for upgrades or any notion of an iterative tuning process of
+a security policy.
+
+Security Event Modeling
+=======================
+
+	"We can no longer speak of the behavior of the particle
+	 independently of the process of observation. As a final
+	 consequence, the natural laws formulated mathematically in
+	 quantum theory no longer deal with the elementary particles
+	 themselves but with our knowledge of them. Nor is it any
+	 longer possible to ask whether or not these particles exist in
+	 space and time objectively ... When we speak of the picture of
+	 nature in the exact science of our age, we do not mean a
+	 picture of nature so much as a picture of our relationships
+	 with nature.  ...Science no longer confronts nature as an
+	 objective observer, but sees itself as an actor in this
+	 interplay between man and nature. The scientific method of
+	 analysing, explaining and classifying has become conscious of
+	 its limitations, which arise out of the fact that by its
+	 intervention science alters and refashions the object of
+	 investigation. In other words, method and object can no longer
+	 be separated."
+				- Werner Karl Heisenberg
+
+Security Event Modeling (SEM), is an alternative strategy to implement
+the security guarantees of mandatory access and integrity controls, in
+a manner that is consistent with emerging application development
+strategies such as namespaces and continuous integration testing.
+
+As was noted at the start of this document, the premise for SEM is
+that the security behavior of a platform, or alternatively a workload,
+can be modeled like any other physical phenomenon in science and
+engineering.
+
+Inspiration for this came from the primary TSEM author/architect
+having trained as a quantum chemist, conducting very early research in
+the development of multi-scale modeling strategies for molecules of
+size to be of interest to pharmaceutical intents.
+
+SEM is premised on the theory that kernel security architects have
+instrumented the LSM security event hooks to be called from all
+locations, with appropriate descriptive parameters, that are relevant
+to the security posture of the kernel.  With respect to modeling, the
+security event hooks are conceptualized as representing the
+independent variables of a basis set that yields a functional
+definition for the security state of an execution trajectory.
+
+SEM can be framed in the context of classic subject/object mandatory
+access controls, by the notion that a unique identity can be generated
+for each element of an access vector matrix, rather than a boolean
+value.  In SEM, a security execution trajectory is defined by the set
+of points in an access vector matrix that a process hierarchy
+(workload) references.  This execution trajectory produces a vector of
+identities, whose sum in an appropriate form, yields a functional
+definition of the security state of the system.
+
+Two subordinate identities are combined to yield a security event
+state point.  These subordinate identities are referred to as the
+Context Of Execution (COE) and the CELL, which are conceptually
+similar to the subject and objects in mandatory access control.  The
+COE identity is derived from the parameters that describe the security
+relevant characteristics of a process, while the CELL value is derived
+from the parameters used by a security event hook to describe the
+characteristics of the event.
+
+A security policy is implemented by a modeling algorithm that
+translates COE and CELL event parameters into their respective
+identities.  Different security policies can be developed by modifying
+how the modeling algorithm utilizes the COE and CELL characteristics.
+
+Since the security policy is implemented with a modeling algorithm, a
+single platform can support multiple and arbitrary security policies.
+The equivalent of a resource namespace in SEM is referred to as a
+modeling domain and can be conceptualized as a mandatory access
+control or integrity namespace.
+
+The formation of the security event state points from existing kernel
+parameters eliminates the need for the use of extended attributes to
+hold security label definitions.  In SEM, a cryptographically signed
+security model definition, designed to be interpreted by a modeling
+engine, becomes the bearer's token for the security of the modeling
+target, rather than information encoded in filesystem security
+attributes.
+
+Trusted Security Event Modeling
+===============================
+
+	"Do you see over yonder, friend Sancho, thirty or forty
+	 hulking giants?  I intend to do battle with them and slay
+	 them."
+				- Don Quixote
+
+In TSEM, the modeling algorithm is implemented in an entity known as a
+Trusted Modeling Agent (TMA), in a 'trusted' environment where
+modeling is immune from modification or alteration by any activity on
+the platform or in a workload.  The notion of a TMA provides a
+framework for next generation security co-processors that extend
+beyond what is defined by the concept of a Trusted Platform Module
+(TPM).
+
+In addition to providing an attestation of an execution trajectory, a
+TMA, in contrast to a TPM, has the ability to advise an operating
+system on whether or not an event being modeled is consistent with the
+security policy that is being enforced.  In this manner, it introduces
+a prospective rather than a retrospective trust model.
+
+TSEM is designed to support Trust Orchestration Systems (TOS).  In a
+TOS, the trust orchestrators are supervisory programs that run
+workloads in independent modeling domains, enforcing a workload
+specific security model.  Each trust orchestrator is paired with a
+'trusted partner TMA', that implements the workload specific modeling
+algorithm.
+
+The root of trust for a workload modeling domain is based on where the
+TMA instance is implemented.  As an example, the Quixote TOS
+implementation currently offers orchestrators for the following TMA
+execution localities:
+
+- Kernel.
+
+- Userspace process.
+
+- SGX enclave.
+
+- Xen stub domain.
+
+- Micro-controller.
+
+This partitioning of trust results in the concept of security domains
+being referred to as internally or externally modeled.  A TMA
+implementation run in the kernel is referred to as an internally
+modeled domain; TMA's run outside of the kernel are referred to as
+externally modeled domains.
+
+The TMA, regardless of locality, is responsible for processing the
+characteristics that describe a security event, computing the identity
+for the COE and CELL and then combining these two identities to create
+a security event state point.  With respect to modeling theory, the
+security event state point is a task specific coefficient representing
+the event in a security model.
+
+TSEM is dispassionate with respect to the type of algorithm that is
+implemented.  The processing of the security event characteristics and
+their conversion to state points, is driven by the security
+model/policy that will be implemented for the workload.  It is
+assumed, that security model algorithms will embrace various
+approximations, and perhaps even stochastic reasoning and machine
+learning methods, as new security models are developed in response to
+specific workload, platform and device requirements.
+
+A security model, to be enforced by a trust orchestrator, is
+implemented by providing the TMA with a set of security state points
+that are to be observed.  A TMA processes the characteristics of a
+security event and converts the characteristics to a state point that
+is evaluated against the state points provided to the TMA as the
+reference security behavior of a workload.
+
+A security event that translates to one of the provided 'good' points,
+will cause the TMA to indicate to the trust orchestrator that the
+process is to be allowed to run as a trusted process.  A security
+event that does not map to a known good point, results in the trust
+orchestrator designating that the process be run as an untrusted
+process.
+
+Trust orchestrators and their associated TMA's, are designed to
+support signed security models.  This results in the elimination of
+the requirement to verify or appraise extended attributes and other
+measures currently required to protect trusted security systems
+against offline attacks.
+
+The use of a cryptographic hash function to generate the security
+state points results in the definition of very specific security
+behaviors, that are sensitive to any variation in their
+characteristics.  Any offline modifications to files will result in a
+security state point that is inconsistent with a signed model provided
+to a TMA.
+
+In order to support the development of TSEM based security models, a
+TMA is designed to run in one of three separate modes, referred to as
+follows:
+
+- Free modeling.
+
+- Sealed.
+
+- Enforcing.
+
+In a free modeling configuration, the TMA adds the security state
+point for the characteristics of a security event to the current set
+of known good states.  In addition, the description of the security
+event is retained as a member of the security execution trajectory for
+the model.  This mode is used, in combination with unit testing of a
+workload, to generate a security model for subsequent enforcement.
+
+Placing a TMA in 'sealed' mode implies that any subsequent security
+events, that do not map into a known security state point, are to be
+considered 'forensic' violations to the security state of the model.
+A forensics mapping event does not cause the initiating process to be
+placed in untrusted mode; it is designed to provide the ability to
+either fine tune a model or provide early warning of a potential
+attempt to subvert the security status of a workload.
+
+Placing a TMA model in 'enforcing' status implies that the model is in
+a sealed state and any subsequent violations to the model will result
+in a violating process being placed in untrusted status.  The
+characteristics of the violating event will be registered in the
+forensics trajectory for the model for use in subsequent evaluation of
+the violating event and/or model refinement.
+
+Process and Platform Trust Status
+=================================
+
+A fundamental concept in TSEM is the notion of providing a precise
+definition for what it means for a platform or workload to be trusted.
+A trusted platform or workload is one where there has not been an
+attempt by a process to execute a security relevant event that does
+not map into a known security state point.
+
+The process trust status is a characteristic of the process that is
+passed to any subordinate processes that are descendants of that
+process.  Once a process is tagged as untrusted, that characteristic
+cannot be removed from the process.  In a 'fruit from the poisoned
+vine' paradigm, all subordinate processes created by an untrusted
+process are untrusted as well.
+
+On entry into each TSEM security event handler, the trust status of a
+process is checked before an attempt to model the event is made.  An
+attempt to execute a security event by an untrusted process will cause
+the event, and its characteristics, to be logged.  The return status
+of the hook will be determined by the enforcement state of the model.
+A permission denial is only returned if the TMA is running in
+enforcing mode.
+
+If the platform running the TSEM LSM has a TPM, the hardware aggregate
+value is computed at the time that TSEM is initialized.  This hardware
+aggregate value is the linear extension sum over Platform
+Configuration Registers (PCR's) 0 through 7.  This is the same
+aggregate value that is computed by the Integrity Measurement
+Architecture (IMA) and is the industry standard method of providing an
+evaluation measurement of the hardware platform state.
+
+Internally model domains have the hardware aggregate measurement
+included as the first state point in the security model.  Externally
+modeled domains export the hardware aggregate value to the TMA for
+inclusion as the first state point of the model maintained by the TMA.
+
+The root modeling domain extends each security state point into PCR
+11.  This allows hardware based TSEM measurements to coexist with IMA
+measurement values.  This hardware measurement value can be used to
+attest to the security execution trajectory that the root model
+maintains.
+
+TSEM operates under the assumption that the root domain will be a
+minimum Trusted Computing Base implementation that will only be
+running trust orchestrators.  Subordinate modeling domains are
+designed, deliberately, to be non-hierarchical, so as to decrease
+model complexity in the subordinate domains in order to support a
+single functional value describing the security state of a security
+domain.
+
+The Linux TSEM Implementation
+=============================
+
+	"Sometimes the questions are complicated and the answers are
+	 simple."
+				- Dr. Seuss
+
+The Linux TSEM implementation is deliberately simplistic and consists
+of the following two generic components:
+
+- Modeling namespace and security event export functionality.
+
+- Internal trusted modeling agent.
+
+The modeling namespace and export functionality is designed to be
+generic infrastructure that allows security domains to be created that
+are either internally or externally modeled.  The TSEM implementation
+does not pose any constraints on what type of modeling can or should
+be implemented in these domains.
+
+On the theory that security event handlers represent all of the
+security relevant points in the kernel, any security or integrity
+model can be implemented using the TSEM infrastructure.  For example,
+basic IMA functionality could be implemented by a TMA that maps the
+digests of files accessed, or mapped executable, by the root user as
+the security state points.
+
+A primary intent of the Linux TSEM implementation is to provide a
+generic method for implementing security policy in userspace rather
+than the kernel.  This is consistent with what has been the historic
+understanding in Linux architecture, that policy decisions should be
+delegated, when possible, to userspace rather than to kernel based
+implementations.
+
+The model is extremely simplistic; a TMA interprets a security event
+and its characteristics and advises whether or not the kernel should
+designate the process as trusted or untrusted after event processing
+is complete.
+
+The following sections discuss various aspects of the infrastructure
+used to implement this architecture.
+
+Internal vs external modeling
+-----------------------------
+
+When a TSEM modeling domain is created, a designation is made as to
+whether the domain is to be internally or externally modeled.
+
+In an internally modeled domain, the security event handlers pass the
+event type and its characteristics to the designated internal trusted
+modeling agent.  The agent provides the permission value for the
+security event handler to return as the result of the event and sets
+the trust status of the process executing the event.
+
+In an externally modeled domain, the event type and parameters are
+exported to userspace for processing by a trust orchestrator with an
+associated TMA.  The trust orchestrator communicates the result of the
+modeling back to the kernel to support the setting of the process
+trust status.
+
+This model poses a limitation to the ability of TSEM to model some
+security events.  This is secondary to the fact that some event
+handlers (LSM hooks) are called from a non-sleeping context, as a
+result the process cannot be scheduled.  This is particularly the case
+with the task based hooks, since they are typically called with the
+tasklist lock held.
+
+This limitation is also inherent to the root model that extends the
+security state points into TPM PCR 11, secondary to the fact that the
+process invoking the security event hook will be scheduled away while
+the TPM transaction completes.
+
+Addressing this problem directly requires a consideration of the
+context from which the security event handlers are being called.
+Subsequent implementations of TSEM will include a mechanism for
+asynchronous deferral of model processing, until when and if, a review
+of the call context would be considered worthwhile by the LSM
+community.
+
+Event handlers that cannot be directly modeled, still consider, on
+entry, whether or not they are being called by an trusted or untrusted
+process.  As a result, an untrusted process will cause a non-modeled
+event to return a permissions violation in enforcing mode, even if the
+security event cannot be directly modeled.
+
+Security event modeling typically traps violations of trust by a COE
+with unmodeled characteristics that is attempting to access/execute a
+file or map memory as executable; or by a COE with known
+characteristics attempting to access or execute a CELL not prescribed
+by a model.  As a result, the impact of the ability to not directly
+model these events is lessened.
+
+Explicit vs generic modeling
+----------------------------
+
+In addition to the COE characteristics, TMA's have the ability to
+include the parameters that characterize the CELL of the security
+event into the generation of the security state point for the event.
+The inclusion of the CELL characteristics is considered explicit
+modeling of the event.
+
+TMA's also have the ability to consider only the COE characteristics
+and the type of the event.  This is referred to as generic modeling of
+the event.
+
+In the current Linux TSEM implementation, the security event handlers
+differentiate, primarily due to code maturity reasons, some events to
+be generically modeled.  For these events, in addition to the COE
+characteristics and task identity, a default CELL value is used in the
+computation of the security state point.
+
+As was noted in the section on 'internal vs external modeling', the
+most common violation of trust is the initial execution of a binary or
+access to a file.  The inclusion of events, as generically modeled,
+allows the capture of security behaviors that are inconsistent with a
+proscribed security model, even if full characterization of the event
+is not implemented.
+
+In the following ABI document:
+
+Documentation/ABI/testing/tsemfs
+
+The /sys/fs/tsem/trajectory entry documents parameters that are
+available for modeling by both internally and externally modeled
+domains.
+
+Event modeling
+--------------
+
+TSEM security event modeling is based on the following functional
+definition for a security state point:
+
+Sp = SHA256(SHA256(EVENT_ID) || TASK_ID || SHA256(COE) || SHA256(CELL))
+
+	Where:
+		||       = Concatenation operator.
+
+		EVENT_ID = ASCII name of event.
+
+		TASK_ID  = 256 bit identity of the process executing
+			   the security event.
+
+		COE      = Characteristics of the context of execution
+			   of the event.
+
+		CELL	 = Characteristics of the object that the
+			   security event is acting on.
+
+Workload or platform specific security point state definitions are
+implemented by a TMA using whatever COE or CELL characteristics that
+are considered relevant in determining whether or not a process should
+be considered trusted or untrusted.
+
+The TASK_ID component of the function above is important with respect
+to the generation of the security state points.  The notion of a task
+identity serves to link the concepts of system integrity and mandatory
+access control.
+
+The TASK_ID is defined by the following function:
+
+TASK_ID = SHA256(SHA256(EVENT) || NULL_ID || SHA256(COE) || SHA256(CELL))
+
+	Where:
+		||        = Concatenation operator.
+
+		EVENT	  = The string "bprm_set_creds".
+
+		NULL_ID	  = A buffer contain 32 null bytes (0x00).
+
+		COE	  = Characteristics of the context of execution
+			    calling the bprm_creds_for_exec LSM hook.
+
+		CELL	  = The characteristics of the file provided
+			    by the linux_binprm structure passed to
+			    the security hook.
+
+An informed reader will quickly conclude, correctly, that the TASK_ID
+function generates an executable specific security state point for the
+bprm_creds_for_exec security hook.  The function is the same as the
+standard security point; with the exception that the task identity is
+replaced with a 'null id', one that consists of 32 null bytes.
+
+One of the CELL characteristics used in the computation of the task
+identity is the digest of the executable file.  Modifying an
+executable, or attempting to execute a binary not considered in the
+security model, will result in an alteration of the task identity that
+propagates to the generation of invalid state points.
+
+The task identity is saved in the TSEM specific task structure and is
+used to compute the state points for any security events that the task
+subsequently executes.  As noted in the previous paragraph,
+incorporating the TASK_ID into the computation of security state
+points results in the points becoming executable specific.  This
+affords a very degree of specificity with respect to the security
+models that can be implemented.
+
+As was demonstrated in the TBDHTTRAD section, TSEM will discriminate
+the following commands as different events/coefficients in a security
+model:
+
+cat /etc/shadow
+
+grep something /etc/shadow
+
+while read input
+do
+	echo $input;
+done < /etc/shadow
+
+An important, and perhaps subtle issue to note, is how these events
+result in the change of process trust status.  In the first two cases,
+if access to the /etc/shadow file is not permitted by the operative
+security model, the cat and grep process will become untrusted.
+
+In the third example, the shell process itself would become untrusted.
+This would cause any subsequent attempts to execute a binary to be
+considered untrusted events, even if access to the binary is a
+permitted point in the model.
+
+Since the modeling operates at the level of mandatory access controls,
+these permission denials would occur even if the process is running
+with root privilege levels.  This is secondary to the notion that
+security and trust status are invested in the trust orchestrator and
+ultimately the TMA.
+
+From a hardware perspective, this is important with respect to the
+notion of a TMA being a model for a successor to the TPM.  From a
+system trust or integrity perspective, a TPM is designed to provide a
+retrospective assessment of the actions that have occurred on a
+platform.  A verifying party uses the TPM event log and a PCR based
+summary measurement, to verify what actions have occurred on the host,
+in order to allow a determination of whether or not the platform
+should be 'trusted'.
+
+In contrast, a TSEM/TMA based system enforces, on a real time basis,
+that a platform or workload remains in a trusted state.  Security
+relevant actions cannot be conducted unless the TMA authorizes the
+actions as being trusted.
+
+This is particularly important with respect to embedded systems.  A
+TPM based architecture would not prevent a system from having its
+trust status altered.  Maintaining the system in a trusted state would
+require attestation polling of the system, and presumably, executing
+actions if the platform has engaged in untrusted behavior.
+
+Conversely, a trust orchestrated software implementation enforces that
+a system or workload remain in a security/trust state that it's
+security model was unit tested to.
+
+Security model functional definitions
+-------------------------------------
+
+Previously, classic trusted system implementations supported the
+notion of the 'measurement' of the system.  The measurement is the
+value of a linear extension function of all the security relevant
+actions recorded by a trust measurement system such as IMA.
+
+In TPM based trust architectures, this measurement is maintained in a
+PCR.  A measurement value is submitted to the TPM that extends the
+current measurement using the following formula:
+
+MEASUREMENT = HASH(CURRENT || NEW)
+
+	Where:
+		||	    = Concatenation operator.
+
+		MEASUREMENT = The new measurement value to be maintained
+			      in the register for the system.
+
+		CURRENT     = The current measurement value.
+
+		NEW	    = A new measurement value to be added to
+			      the current measurement.
+
+		HASH	    = A cryptographic hash function.
+
+In TPM1 based systems the HASH function was SHA1.  Due to well
+understood security concerns about the cryptographic vitality of this
+function, TPM2 based systems provide additional HASH functions with
+stronger integrity guarantees, most principally SHA related functions
+with longer digest values such as SHA256, SHA384 and SM3.
+
+The use of a cryptographic function produces a non-commutative sum
+that can be used to verify the integrity of a series of measurements.
+With respect to security modeling theory, this can be thought of as a
+'time-dependent' measurement of the system.  Stated more simply, the
+measurement value is sensitive to the order in which the measurements
+were made.
+
+In systems such as IMA, the measurement value reflects the sum of
+digest values of what are considered to be security critical entities,
+most principally, files that are accessed based on various policies.
+
+In TSEM based TMA's, the measurement of a modeling domain is the sum
+of the security state points generated by the operative security model
+being enforced.  As previously noted, on systems with a TPM, the root
+modeling domain measurement is maintained in PCR 11.
+
+The challenge associated with classic integrity measurements is the
+time dependent nature of using a non-commutative summing function.
+The almost universal embrace of SMP based hardware architectures and
+standard kernel task scheduling makes the measurement values
+non-deterministic.  This requires a verifying party to evaluate an
+event log, verified by a measurement value, to determine whether or
+not it is security appropriate.
+
+TSEM addresses this issue by implementing a strategy designed to
+produce a single functional value that represents the security state
+of a model.  This allows a TMA to attest to the trust/security status
+of a platform or workload by signing this singular value and
+presenting it to a verifying party.
+
+In TSEM nomenclature, this singular value is referred to as the
+'state' of the model.  The attestation model is to use trust
+orchestrators to generate the state value of a workload by unit
+testing.  This state value can be packaged with a utility or container
+to represent a summary trust characteristic that can be attested by a
+TMA, eliminating the need for a verifying partner to review and verify
+an event log.
+
+TMA's implement this architecture by maintaining a single instance
+vector of all the set of security model state points that have been
+generated.  A state measurement is generated by sorting the vector in
+big-endian hash format and then generating a standard measurement
+digest over this new vector.
+
+Any security event that generates an associated state point that is
+not in the model will resulted in a perturbed state function value.
+That perturbed value would be interpreted by a verifying party as an
+indication of an untrusted system.
+
+Since the TMA maintains the security event descriptions in time
+ordered form the option to provide a classic event log and measurement
+are preserved and available.  Extensive experience in the development
+of TSEM modeled systems has demonstrated the superiority of state
+value interpretation over classic measurement schemes.
+
+A TMA may choose to incorporate a 'base nonce' into a security model
+that is is implementing, this based nonce is designed to serve in a
+manner similar to an attestation nonce.  If used, the trust
+orchestrator is responsible for negotiating a random base nonce with a
+verifying party at the time of initialization of a modeling namespace
+and providing it to the TMA.
+
+The TMA uses the base nonce to extend each security event state point
+that is generated by the model.  This causes the state and measurement
+values of the model to become dependent on this base nonce, a process
+that can be used to defeat a replay attack against the security model.
+
+Control plane
+-------------
+
+Both primary functions of TSEM: security modeling domain management
+and the internal TMA implementation, are controlled by the tsemfs
+pseudo-filesystem, that uses the following mount point:
+
+/sys/fs/tsem
+
+The following file documents, in detail, the interfaces provided by
+the filesystem:
+
+Documentation/ABI/testing/tsemfs
+
+This filesystem is primarily intended for use by trust orchestrators
+and must be mounted in order for orchestrators to create and manage
+security modeling domains.
+
+The following files grouped below by generic functionality, are
+presented in the filesystem:
+
+	control
+
+	id
+	aggregate
+
+	measurement
+	state
+	points
+	trajectory
+	forensics
+
+The /sys/fs/tsem directory contains the following sub-directory:
+
+	ExternalTMA
+
+That is used to hold files that will be used to export security event
+descriptions for externally modeled domains.
+
+The files are process context sensitive.  Writing to the control file
+or reading from the informational files, will act on or reference the
+security domain that the access process is assigned to.
+
+The TSEM implementation at large is controlled by the only writable
+file, which is the 'control' file.
+
+The following keywords are used by trust orchestrators to create
+internally or externally modeled security domains for the writing
+process:
+
+	internal
+	external
+
+The following keywords are used by trust orchestrators to set the
+trust status of a process after processing of a security event by an
+external TMA:
+
+	trusted PID
+	untrusted PID
+
+	Where PID is the process identifier that is provided to the
+	TMA in the security event description
+
+By default a modeling domain runs in free modeling mode.  The modeling
+mode is changed by writing the following keywords to the control file:
+
+	seal
+	enforce
+
+The following keyword and argument are used to load a security model
+into an internal modeling domain:
+
+	state HEXID
+
+	Where HEXID is the ASCII base 16 representation of a security
+	state point that is represents a valid security event in the
+	model.
+
+	After writing a series of state values the trust orchestrator
+	would write the 'seal' keyword to the control file to complete
+	creation of a security model.  Writing the 'enforce' keyword
+	to the control file will result in that model being enforced.
+
+The following keyword and argument is used to set a base nonce for the
+internal TMA:
+
+	base HEXID
+
+	Where HEXID is the ASCII base 16 representation of a value
+	that each measurement is to be extended with before being
+	committed as a measurement value for the model.
+
+The following keyword and argument is used to create a file digest
+pseudonym for the internal TMA:
+
+	pseudonym HEXID
+
+	Where HEXID is the ASCII base 16 representation of a file
+	digest pseudonym that is to be maintained by the model.  See
+	the ABI documentation for how the argument to this verb is
+	generated.
+
+The 'id' file is used to determine the modeling domain that the
+process is running in.  The domain id value of 0 is reserved for the
+root modeling domain, a non-zero value indicates that the process is
+running in a subordinate modeling domain.
+
+The 'aggregate' file is used by trust orchestrators for internally
+modeled domains to obtain the hardware measurement value.  A trust
+orchestrator for an internally modeled domain needs this value in
+order to generate a platform specific security model for subsequent
+enforcement.  A trust orchestrator for an externally modeled domain
+can capture this value since it is exported, through the trust
+orchestrator, to the TMA.
+
+The remaining five files: measurement, state, points, trajectory and
+forensics, are used to export the security model characteristics of
+internally modeled domains.
+
+The 'measurement' file outputs the classic measurement value of the
+modeling domain that the calling process is running in.  This value is
+the linear extension sum of the security state points in the model.
+
+The 'state' file outputs the security state measurement value as
+described in the 'Security model functional definitions' section of
+this document.
+
+The 'points' file outputs the set of security state points in the
+model.  These points represent both valid and invalid state points
+generated by the security model implemented for the domain.
+
+The 'trajectory' file outputs the description of each security event
+recorded by the model in time dependent form.
+
+The 'forensics' file outputs the description of security events that
+have occurred when the domain security model is running in a sealed
+state.
+
+The ABI documentation file contains a complete description of the
+output that is generated by each of these files.
+
+A security model for an internally modeled domain is loaded by
+writing the valid security points to the 'state' file in the control
+plane.  This will result in the 'trajectory' file having no event
+descriptions for a sealed model, since the event description vector is
+only populated when a new state point is added to the model.
+
+Since the state points are generated with a cryptographic hash
+function, the first pre-image resistance characteristics of the
+function prevents a security model description from disclosing
+information about the characteristics of the workload.
+
+Trust orchestrators
+===================
+
+In security modeling, the need for a trust orchestrator system is
+embodied in Heisenberg's reflections on quantum mechanical modeling.
+A modeled system cannot model itself without affecting the functional
+value of the security model being implemented.  An external entity is
+needed to setup, configure and monitor the state of a modeled system,
+in a manner that does affect the state of the modeled system itself.
+
+After creating and configuring a modeling domain, the orchestrator is
+responsible for executing and monitoring a process that is run in the
+context of the domain.  The trust orchestrator is also responsible for
+providing access to the security model implemented by the TMA.
+
+Trust orchestrators for externally modeled domains, have an
+associated TMA that is responsible for implementing the security model
+for a domain.  The TMA represents the the root of trust for the
+modeled domain.  The TMA advises the trust orchestrator as to what the
+new trust status for a process should be set to, based on the modeling
+of the security event that is presented to it by the trust
+orchestrator.
+
+In a trust orchestration architecture, secondary to their integral
+role in maintaining the trust state of the system, the trust
+orchestrators are the highest value security asset running on the
+system.  In order to support this the Linux TSEM implementation
+implements a new security capability, CAP_TRUST, that only the trust
+orchestrators are designed to run with.
+
+The CAP_TRUST capability is defined as a capability that allows the
+ability of it's holder to modify the trust state of the system.  The
+ability to create the proposed IMA namespaces would also be a
+candidate for this capability.
+
+Trust orchestrators are designed to drop the CAP_TRUST capability
+before forking the process that will be responsible for launching a
+modeled workload.  This provides an architecture where the root of
+trust for the system can be predicated on a small body of well audited
+orchestration utilities, that can be linked to a hardware root of
+trust implemented by a TPM or hardware based TMA.
+
+Quixote
+=======
+
+	"He is awkward, past his prime and engaged in a task beyond his
+	 capacities."
+				- Don Quixote's able mount Rocinante
+
+The Quixote Trust Orchestration System, released in concert with TSEM,
+is an initial implementation of a system that embodies the
+characteristics described above.  While currently under development by
+a small team, it provides all off the basic functionality needed to
+demonstrate, and use, TSEM based security modeling.
+
+It is anticipated that Quixote would not be the only such system to
+take advantage of TSEM.  Given the burgeoning capability set of
+systemd, it would be an architecturally valid concept to have systemd,
+or other system init equivalents, gain the ability to launch critical
+system services in modeled environments.
+
+The source code for Quixote, and patches to the LTS kernels back to
+5.4, are available at the following URL:
+
+ftp://ftp.enjellic.com/pub/Quixote
+
+The build of Quixote is somewhat formidable, given that it spans the
+range from system programming though SGX programming and into embedded
+micro-controller systems.  In order to facilitate experimentation,
+binaries pre-compiled against MUSL libc are provided that have
+virtually no system dependencies, other than a TSEM enabled kernel.
+
+Sample utilities
+----------------
+
+The Quixote TSEM implementation implements a separate trust
+orchestration utility for each TMA environment, nee Sancho partner,
+that is supported:
+
+quixote	     -> TMA run in the kernel for internally modeled domains.
+
+quixote-us   -> TMA run in a userspace process.
+
+quixote-xen  -> TMA run in a Xen based stub domain.
+
+quixote-sgx  -> TMA run in an SGX enclave.
+
+quixote-mcu* -> TMA run in a micro-controller implementation.
+
+* = See discussion below.
+
+Each utility runs in one of two modes: process or container
+
+In process mode, a shell process is run as the workload process in
+modeling domain.  This mode is selected with the -P command-line
+option.
+
+In container mode, the default, the OCI runc utility is run as the
+workload process, with a 'bundle' argument that specifies a directory
+that contains a JSON container definition for a directory hierarchy in
+the bundle directory.  The /var/lib/Quixote/Magazine directory
+contains the bundle directories.
+
+The -c command-line option selects container mode, the argument to the
+option specifies the bundle directory for the runc utility.
+
+In order to support the creation of security models, each utility
+supports the -o command-line option to specify that a security model
+description be output when the modeled workload terminates.  The model
+is written name of the file supplied via the command-line option.
+
+If the -t command-line option is also specified, the security
+execution trajectory, rather than a model definition, is written to
+the output file.  This trajectory represents the description of the
+security events that were modeled.  This trajectory can be converted
+to security state points with the generate-states utility that is also
+provided in the utilities package.
+
+The -m command-line option is used to specify a model that is to be
+loaded into the TMA and optionally enforced.  By default the security
+model output with the -o command-line option will place the TMA in a
+sealed modeling state.  Any security events that are non-compliant
+with the model will be registered as forensics events.
+
+Adding the -e command-line option, with the -m option, will cause the
+loaded model to be enforced.  Any forensic events will cause a
+permission denial to be returned to the caller of the LSM hook.
+
+The Quixote package also includes a utility, quixote-console, for
+interrogating the model state of a TMA.  The following command-line
+options request output of the following characteristics of the model:
+
+-E -> The log of denied events.
+
+-F -> The current forensics execution trajectory.
+
+-M -> The current security model description.
+
+-P -> The current security state points.
+
+-S -> The state value of the model.
+
+-T -> The current security execution trajectory.
+
+Executing the utility, without these arguments, will cause a
+command-line version of the utility to be presented that takes the
+following arguments:
+
+show trajectory
+
+show forensics
+
+show points
+
+show state
+
+show model
+
+quit
+
+It is important to note that any of the values output represent the
+current state of the model and do not reflect a cumulative model of
+the workload.  Capturing a complete workload model requires the use of
+the -m command-line argument to the trust orchestrators to capture a
+model that is representative of the entire execution trajectory of the
+workload.
+
+For informative purposes the following security model definition
+represents the execution and simple termination of a shell session run
+on a system with a hardware TPM:
+
+aggregate de2b9c37eb1ceefa4bcbc6d8412920693d3272f30eb5ba98d51d2f898d620289
+state 97b29769580b412fbf55e326a98d6a1b97c6ebf446aaf78ea38c884e954ca5b2
+state 7c435854b4fa421175ec0a5d3ca7c156480913d85c03155ea3305afa56c9717d
+state 554d9f62693d522c9a43acf40780065f99cea3d67ca629ac4eaab4e22d4e63c2
+state 1b228046c4c2e7aa14db9a29fcff6f718f4f852afbfb76c8a45af7bf0485f9ce
+state 24fd04b10e2b5016e0061952f3bdea959e0fa80a55ff0f4e8e13f9f72ede7498
+state da6038511db71b08c49a838d178ed055e0b7bfc42548b4c2d71eca046e9a222e
+state 94b24ad4c8902f8ecb578a702408e8458e72c0774c402c3bd09ec5f390c4d0ae
+state 5ffa5a2a38f42d89ae74a6d58be8b687c1baed9746d9c6a7ae3c632a2e7c082f
+state a2e309d84bd4a52466c22779a622254c65ad1208583d70113751c4624baa7804
+state e93ceb0b1bf3cd58373a9e9ab4aca11a507782bbfde395ff68f8bfaf1678ed43
+state bf42388d63887368605fac9816134bc67314762c3a97b440cc48c5a30c07fdb9
+state eaa342599d682d63be4b64e159b98f21d85f0133ef5b28588e444ad12e446bf6
+state 2b9c86bc34202504c398c2f177d1dcf807b2f267c160bf8ebda863a9b427917f
+state 686fc3c958f2e4f2ce3b2c6a2cb3fff44ccc4db98869bd377b14e557a5191231
+state 613c39fd2a58413b32f448c13ea4d6bc38b77966dfc5560e39e4b37d2b2f5675
+state 70e276bfd7c20262cd9c9f5b09a922f11d16d1e3a602e8005d68e9ed6afc9b5d
+state 456aaedc5c1fc63f852ee97ae9561aba2a06c416154ecb9d7a1bf9d9a8c9c064
+state 97507c4c91af4a9b34b4d66118f6cc0ba1f8b55b8bb6e623dcafe27b100aea07
+state ea635c48031f81140b3561ed2291a3b1790a302e6adf5244320593b08a5af924
+state 2fd6a4d6ea1869a193926e998fbdf855916b510257d379762f48a1df63a810d4
+state 9c4cb7ef4848be1e29f9eb35fadaf5bfdc1fa3cbb22b6407cbd31b7088257026
+state 66640cbf9ae772515070f8613182b6852bf46220df0833fbe6b330a418fad95b
+state 6b0d1890cbd78c627e23d7a564e77a5ee88fb20e0662ce5e66f3727ebf75fa1d
+state bd28fa43b34850591fdf6fb2aa5542f33c21c20ee91b4bc2034e199b4e09edc1
+state 04425354419e53e6e73cde7d61856ff27763c2be01934e9990c1ae9f8d2a0b6e
+state 2650d86382f6404367b7fdeec07f873b67b9ce26caef09d035b4dff09fce04d5
+state df2f91f5fd84ca4621092420eaf1b0a3743b328a95e3f9e0b7b1281468462aa2
+state c730c66ecfabe99480e61a7f25962582ca7bb6f2b17983048e77adde1fe7f72b
+state 0fc937b71d0067fcc2c2f37c060763de250b3142e621174ffedc1b2520cdf6fd
+state 7f267400a3ccf462c77ae5129799558c2c62d8bc5b388882caec813ab4cf7b7f
+seal
+end
+
+As was previously discussed, the model should be cryptographically
+secure against the elucidation of the security events that resulted in
+the described security states.
+
+The Quixote package also contains utilities for generating signed
+versions of these security models.  In what is a nod to the politics
+of trusted systems, the Quixote TMA implementations support
+self-signed security models.
+
+* MCU TMA's
+-----------
+
+One of the objectives of TSEM/Quixote is to explore architectures for
+trusted systems that extend beyond what is provided by the TPM model
+for security co-processors.  The MCU based reference implementations
+allow experimentation with hardware based TMA's.
+
+The Quixote TSEM utilities include TMA implementations for the
+following following ARM32 based micro-controller platforms:
+
+STM32L496
+
+STM32L562
+
+NRF52840-DK
+
+NRF52840-DONGLE
+
+The STM32L496 platform, in addition to the base TMA implementation,
+includes support for a CAT1-M based cellular modem.  This demonstrates
+the ability of an external TMA to conduct remote, out-of-band,
+signaling of security violations for modeled platforms/workloads.
+
+The STM32L562 platform is a low power MCU designed for security
+focused IOT implementations.  It includes hardware hashing, hardware
+asymmetric encryption and Trust Zone support.
+
+Of primary interest is the NRF52840-DONGLE implementation.  This is a
+'USB fob' form factor board that GOOGLE uses as the basis for its
+OpenSK security key implementation.  This form factor allows the
+development and experimentation with deployable hardware based TMA
+implementations.
+
+The NRF52840-DONGLE architecture was also chosen by the NLnet
+sponsored 'FobNail' project, that is developing a hardware based
+attestation server:
+
+https://fobnail.3mdeb.com/
+
+The Fobnail projects discusses the notion of their architecture
+expanding to provide protection for a Linux system at large.
+Quixote/TSEM running, on the NRF52840-DONGLE micro-controller, is a
+demonstration of such an implementation.
+
+===============
+Closing Remarks
+===============
+
+	"Sometimes it is the people no one can imagine anything of who
+	 do the things no one can imagine.
+				- Alan Turing
+
+While this document is of some length and detail, it hopefully
+fulfills its obligation to provide sufficient prose for the
+justification of the security model that TSEM addresses, and in
+combination with trust orchestrators, implements.
+
+The MAINTAINERS file has contact information for feedback, patches
+and/or questions regarding TSEM and its reference TOS implementation.
+
+     The Quixote Team - Flailing at the Travails of Cybersecurity
+
+	With all due respect to Miguel de Cervantes Saavedra.
+
+   From the glacial moraine lake country of West-Central Minnesota.
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 6cfa6e3996cf..a7dafcd932b4 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -6376,6 +6376,11 @@
 			with CPUID.16h support and partial CPUID.15h support.
 			Format: <unsigned int>
 
+	tsem_mode=	[TSEM] Set the mode that the Trusted Security Event
+			Modeling LSM is to run in.
+			Format: 1
+			1 -- Disable root domain modeling.
+
 	tsx=		[X86] Control Transactional Synchronization
 			Extensions (TSX) feature in Intel processors that
 			support TSX control.
-- 
2.39.1


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 03/14] Add magic number for tsemfs.
  2023-02-04  5:09 [PATCH 00/14] Implement Trusted Security Event Modeling Dr. Greg
  2023-02-04  5:09 ` [PATCH 01/14] Update MAINTAINERS file Dr. Greg
  2023-02-04  5:09 ` [PATCH 02/14] Add TSEM specific documentation Dr. Greg
@ 2023-02-04  5:09 ` Dr. Greg
  2023-02-04  5:09 ` [PATCH 04/14] Implement CAP_TRUST capability Dr. Greg
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 42+ messages in thread
From: Dr. Greg @ 2023-02-04  5:09 UTC (permalink / raw)
  To: linux-security-module

Signed-off-by: Greg Wettstein <greg@enjellic.com>
---
 include/uapi/linux/magic.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h
index 6325d1d0e90f..6a6a2b70c529 100644
--- a/include/uapi/linux/magic.h
+++ b/include/uapi/linux/magic.h
@@ -95,6 +95,7 @@
 #define BPF_FS_MAGIC		0xcafe4a11
 #define AAFS_MAGIC		0x5a3c69f0
 #define ZONEFS_MAGIC		0x5a4f4653
+#define TSEMFS_MAGIC		0x11242022
 
 /* Since UDF 2.01 is ISO 13346 based... */
 #define UDF_SUPER_MAGIC		0x15013346
-- 
2.39.1


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 04/14] Implement CAP_TRUST capability.
  2023-02-04  5:09 [PATCH 00/14] Implement Trusted Security Event Modeling Dr. Greg
                   ` (2 preceding siblings ...)
  2023-02-04  5:09 ` [PATCH 03/14] Add magic number for tsemfs Dr. Greg
@ 2023-02-04  5:09 ` Dr. Greg
  2023-02-06 17:28   ` Serge Hallyn (shallyn)
       [not found]   ` <a12483d1-9d57-d429-789b-9e47ff575546@schaufler-ca.com>
  2023-02-04  5:09 ` [PATCH 05/14] Add TSEM master header file Dr. Greg
                   ` (10 subsequent siblings)
  14 siblings, 2 replies; 42+ messages in thread
From: Dr. Greg @ 2023-02-04  5:09 UTC (permalink / raw)
  To: linux-security-module

TSEM was designed to support a Trust Orchestration System (TOS)
security architecture.  A TOS based system uses the concept of a
minimum Trusted Computing Base of utilities, referred to as trust
orchestrators, that maintain workloads in a trusted execution
state.  The trust orchestrators are thus, from a security
perspective, the most privileged assets on the platform.

Introduce the CAP_TRUST capability that is defined as a
capability that allows a process to alter the trust status of the
platform.  In a fully trust orchestrated system only the
orchestrators carry this capability bit.

In TSEM the CAP_TRUST capability allows the holder to access the
control plane of the LSM.  This ability allows subordinate
modeling domains to be created and managed.  Most principally the
CAP_TRUST capability allows the holder to designate whether or
not a process should be trusted or untrusted.

The proposed Integrity Measurement Architecture namespaces would
also be a candidate to use the CAP_TRUST capability.

Signed-off-by: Greg Wettstein <greg@enjellic.com>
---
 include/uapi/linux/capability.h     | 6 +++++-
 security/selinux/include/classmap.h | 2 +-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/include/uapi/linux/capability.h b/include/uapi/linux/capability.h
index 3d61a0ae055d..af677b534949 100644
--- a/include/uapi/linux/capability.h
+++ b/include/uapi/linux/capability.h
@@ -417,7 +417,11 @@ struct vfs_ns_cap_data {
 
 #define CAP_CHECKPOINT_RESTORE	40
 
-#define CAP_LAST_CAP         CAP_CHECKPOINT_RESTORE
+/* Allow modifications to the trust status of the system */
+
+#define CAP_TRUST	41
+
+#define CAP_LAST_CAP         CAP_TRUST
 
 #define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
 
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
index a3c380775d41..e8c497c16271 100644
--- a/security/selinux/include/classmap.h
+++ b/security/selinux/include/classmap.h
@@ -30,7 +30,7 @@
 		"wake_alarm", "block_suspend", "audit_read", "perfmon", "bpf", \
 		"checkpoint_restore"
 
-#if CAP_LAST_CAP > CAP_CHECKPOINT_RESTORE
+#if CAP_LAST_CAP > CAP_TRUST
 #error New capability defined, please update COMMON_CAP2_PERMS.
 #endif
 
-- 
2.39.1


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 05/14] Add TSEM master header file.
  2023-02-04  5:09 [PATCH 00/14] Implement Trusted Security Event Modeling Dr. Greg
                   ` (3 preceding siblings ...)
  2023-02-04  5:09 ` [PATCH 04/14] Implement CAP_TRUST capability Dr. Greg
@ 2023-02-04  5:09 ` Dr. Greg
       [not found]   ` <ecb168ef-b82d-fd61-f2f8-54a4ef8c3b48@schaufler-ca.com>
  2023-02-04  5:09 ` [PATCH 06/14] Add primary TSEM implementation file Dr. Greg
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 42+ messages in thread
From: Dr. Greg @ 2023-02-04  5:09 UTC (permalink / raw)
  To: linux-security-module

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 the TSEM LSM implementation.

Signed-off-by: Greg Wettstein <greg@enjellic.com>
---
 security/tsem/tsem.h | 388 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 388 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..2d81a17e655a
--- /dev/null
+++ b/security/tsem/tsem.h
@@ -0,0 +1,388 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * Copyright (C) 2022 Enjellic Systems Development, LLC
+ * Author: Dr. Greg Wettstein <greg@enjellic.com>
+ *
+ * TSEM specific includes.
+ */
+
+#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_info.h>
+
+#define TSEM_CONTROL_CAPABILITY CAP_TRUST
+
+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 {
+	TSEM_ACTION_LOG = 0,
+	TSEM_ACTION_EPERM,
+	TSEM_ACTION_CNT
+};
+
+enum tsem_control_type {
+	TSEM_CONTROL_INTERNAL = 1,
+	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_task_trust {
+	TSEM_TASK_TRUSTED = 1,
+	TSEM_TASK_UNTRUSTED = 2,
+	TSEM_TASK_TRUST_PENDING = 4
+};
+
+enum tsem_inode_state {
+	TSEM_INODE_COLLECTING = 1,
+	TSEM_INODE_COLLECTED
+};
+
+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;
+	} capability;
+};
+
+struct tsem_file {
+	uid_t uid;
+	gid_t gid;
+	umode_t mode;
+	u32 flags;
+
+	u32 name_length;
+	u8 name[WP256_DIGEST_SIZE];
+
+	u32 s_magic;
+	u8 s_id[32];
+	u8 s_uuid[16];
+
+	u8 digest[WP256_DIGEST_SIZE];
+};
+
+struct tsem_event_point {
+	struct list_head list;
+	u8 point[WP256_DIGEST_SIZE];
+	bool valid;
+};
+
+struct tsem_mmap_file_args {
+	struct file *file;
+	u32 anonymous;
+	u32 reqprot;
+	u32 prot;
+	u32 flags;
+};
+
+struct tsem_socket_create_args {
+	int family;
+	int type;
+	int protocol;
+	int kern;
+};
+
+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;
+		u8 mapping[WP256_DIGEST_SIZE];
+	} u;
+};
+
+struct tsem_socket_accept_args {
+	struct tsem_inode *tsip;
+	u16 family;
+	u16 type;
+	__be16 port;
+	__be32 ipv4;
+	struct in6_addr ipv6;
+};
+
+struct tsem_task_kill_args {
+	u32 cross_model;
+	u32 signal;
+	u8 target[WP256_DIGEST_SIZE];
+};
+
+struct tsem_event {
+	struct kref kref;
+	enum tsem_event_type event;
+	pid_t pid;
+	char *pathname;
+	char comm[TASK_COMM_LEN];
+	u8 task_id[WP256_DIGEST_SIZE];
+	u8 mapping[WP256_DIGEST_SIZE];
+	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 {
+	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_trajectory {
+	struct list_head list;
+	struct tsem_event *ep;
+};
+
+struct tsem_model {
+	bool have_aggregate;
+	u8 base[WP256_DIGEST_SIZE];
+	u8 measurement[WP256_DIGEST_SIZE];
+	u8 state[WP256_DIGEST_SIZE];
+
+	unsigned int point_count;
+	struct mutex point_mutex;
+	struct list_head point_list;
+	struct list_head state_list;
+
+	unsigned int trajectory_count;
+	struct mutex trajectory_mutex;
+	struct list_head trajectory_list;
+
+	unsigned int forensics_count;
+	unsigned int max_forensics_count;
+	struct mutex forensics_mutex;
+	struct list_head forensics_list;
+
+	struct mutex pseudonym_mutex;
+	struct list_head pseudonym_list;
+};
+
+struct tsem_external {
+	char *filename;
+	struct mutex measurement_mutex;
+	struct list_head measurement_list;
+	struct dentry *dentry;
+	bool have_event;
+	wait_queue_head_t wq;
+};
+
+struct tsem_TMA_work {
+	struct work_struct work;
+	struct tsem_TMA_context *ctx;
+};
+
+struct tsem_TMA_context {
+	struct kref kref;
+	struct tsem_TMA_work work;
+	u64 id;
+	bool sealed;
+	enum tsem_action_type actions[TSEM_EVENT_CNT];
+	struct tsem_model *model;
+	struct tsem_external *external;
+};
+
+struct tsem_task {
+	int trust_status;
+	u8 task_id[WP256_DIGEST_SIZE];
+	struct tsem_TMA_context *context;
+};
+
+struct tsem_inode {
+	enum tsem_inode_state status;
+	u64 version;
+	u8 digest[WP256_DIGEST_SIZE];
+	struct mutex mutex;
+};
+
+extern struct lsm_blob_sizes tsem_blob_sizes;
+extern enum tsem_action_type tsem_root_actions[TSEM_EVENT_CNT];
+extern struct tsem_TMA_context root_TMA_context;
+extern const char * const tsem_names[TSEM_EVENT_CNT];
+
+extern int tsem_fs_init(void);
+extern struct dentry *tsem_fs_create_external(const char *name);
+extern void tsem_fs_remove_external(struct dentry *dentry);
+
+extern struct tsem_model *tsem_model_allocate(void);
+extern void tsem_model_free(struct tsem_TMA_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, u8 *mapping);
+extern void tsem_model_load_base(u8 *mapping);
+extern int tsem_model_add_aggregate(void);
+extern void tsem_model_compute_state(void);
+
+extern int tsem_ns_init(void);
+extern int tsem_ns_create(enum tsem_control_type type);
+extern void tsem_ns_put(struct tsem_TMA_context *ctx);
+extern void tsem_ns_get(struct tsem_TMA_context *ctx);
+
+extern int tsem_export_show(struct seq_file *m);
+extern int tsem_export_event(struct tsem_event *ep);
+extern int tsem_export_action(enum tsem_event_type event);
+extern int tsem_export_aggregate(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);
+
+extern struct tsem_event *tsem_event_allocate(enum tsem_event_type event,
+					struct tsem_event_parameters *params);
+extern void tsem_event_put(struct tsem_event *ep);
+extern void tsem_event_get(struct tsem_event *ep);
+extern int tsem_event_cache_init(void);
+
+extern u8 *tsem_trust_aggregate(void);
+extern int tsem_trust_add_event(u8 *coefficient);
+
+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_TMA_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;
+}
-- 
2.39.1


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 06/14] Add primary TSEM implementation file.
  2023-02-04  5:09 [PATCH 00/14] Implement Trusted Security Event Modeling Dr. Greg
                   ` (4 preceding siblings ...)
  2023-02-04  5:09 ` [PATCH 05/14] Add TSEM master header file Dr. Greg
@ 2023-02-04  5:09 ` Dr. Greg
  2023-02-04  5:09 ` [PATCH 07/14] Add root domain trust implementation Dr. Greg
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 42+ messages in thread
From: Dr. Greg @ 2023-02-04  5:09 UTC (permalink / raw)
  To: linux-security-module

The tsem.c file is the 'master' file in the TSEM implementation.
It is responsible for initializing the LSM and providing
implement of the security event hooks.

In addition to initializing the LSM, the set_ready() function
implements a secondary initialization that is used to a
statically scoped variable that indicates that security event
modeling can begin.  This is required secondary to the fact that
the cryptographic API's do not become ready until after the 'fs'
phase of system initialization is complete.

This file also handles the implementation of the tsem_mode kernel
command-line option.  If tsem_mode is set to a value of 1 the
TSEM driver does not model any events from the root domain.  This
is intended to allow development platforms to develop security
models without the overhead of full platform modeling.

This file also contains the implementation of the tsem_names
array that contains the ASCII text names that are assigned to
each security event handler.  This name is used as one of the
characteristics in the security state points that are generated.
This array is also used to provide symbolic names for the export
of security event descriptions, either through the tsemfs
filesystem or for export to external trust orchestrators.

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

diff --git a/security/tsem/tsem.c b/security/tsem/tsem.c
new file mode 100644
index 000000000000..fac40c70a474
--- /dev/null
+++ b/security/tsem/tsem.c
@@ -0,0 +1,1801 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * Copyright (C) 2022 Enjellic Systems Development, LLC
+ * Author: Dr. Greg Wettstein <greg@enjellic.com>
+ *
+ * TSEM initialization infrastructure.
+ */
+
+#define TRAPPED_MSG_LENGTH 128
+
+#include <linux/magic.h>
+#include <linux/mman.h>
+#include <linux/binfmts.h>
+#include <linux/bpf.h>
+#include <linux/ipv6.h>
+
+#include "tsem.h"
+
+static int tsem_ready __lsm_ro_after_init;
+
+static bool no_root_modeling __lsm_ro_after_init;
+
+static int __init set_modeling_mode(char *mode_value)
+{
+	unsigned long mode = 0;
+
+	if (kstrtoul(mode_value, 0, &mode)) {
+		pr_warn("tsem: Failed to parse modeling mode.\n");
+		return 1;
+	}
+
+	if (mode == 1)
+		no_root_modeling = true;
+	else
+		pr_warn("tsem: Unknown mode specified.\n");
+	return 1;
+}
+__setup("tsem_mode=", set_modeling_mode);
+
+const char * const tsem_names[TSEM_EVENT_CNT] = {
+	"undefined",
+	"bprm_set_creds",
+	"generic_event",
+	"task_kill",
+	"task_setpgid",
+	"task_getpgid",
+	"task_getsid",
+	"task_setnice",
+	"task_setioprio",
+	"task_getioprio",
+	"task_prlimit",
+	"task_setrlimit",
+	"task_setscheduler",
+	"task_getscheduler",
+	"task_prctl",
+	"file_open",
+	"mmap_file",
+	"file_ioctl",
+	"file_lock",
+	"file_fcntl",
+	"file_receive",
+	"unix_stream_connect",
+	"unix_may_send",
+	"socket_create",
+	"socket_connect",
+	"socket_bind",
+	"socket_accept",
+	"socket_listen",
+	"socket_socketpair",
+	"socket_sendmsg",
+	"socket_recvmsg",
+	"socket_getsockname",
+	"socket_getpeername",
+	"socket_setsockopt",
+	"socket_shutdown",
+	"ptrace_traceme",
+	"kernel_module_request",
+	"kernel_load_data",
+	"kernel_read_file",
+	"sb_mount",
+	"sb_umount",
+	"sb_remount",
+	"sb_pivotroot",
+	"sb_statfs",
+	"move_mount",
+	"shm_associate",
+	"shm_shmctl",
+	"shm_shmat",
+	"sem_associate",
+	"sem_semctl",
+	"sem_semop",
+	"syslog",
+	"settime",
+	"quotactl",
+	"quota_on",
+	"msg_queue_associate",
+	"msg_queue_msgctl",
+	"msg_queue_msgsnd",
+	"msg_queue_msgrcv",
+	"ipc_permission",
+	"key_alloc",
+	"key_permission",
+	"netlink_send",
+	"inode_create",
+	"inode_link",
+	"inode_unlink",
+	"inode_symlink",
+	"inode_mkdir",
+	"inode_rmdir",
+	"inode_mknod",
+	"inode_rename",
+	"inode_setattr",
+	"inode_getattr",
+	"inode_setxattr",
+	"inode_getxattr",
+	"inode_listxattr",
+	"inode_removexattr",
+	"inode_killpriv",
+	"tun_dev_create",
+	"tun_dev_attach_queue",
+	"tun_dev_attach",
+	"tun_dev_open",
+	"bpf",
+	"bpf_map",
+	"bpf_prog"
+};
+
+static const int pseudo_filesystems[] = {
+	PROC_SUPER_MAGIC,
+	SYSFS_MAGIC,
+	DEBUGFS_MAGIC,
+	TMPFS_MAGIC,
+	DEVPTS_SUPER_MAGIC,
+	BINFMTFS_MAGIC,
+	SECURITYFS_MAGIC,
+	SELINUX_MAGIC,
+	SMACK_MAGIC,
+	CGROUP_SUPER_MAGIC,
+	CGROUP2_SUPER_MAGIC,
+	NSFS_MAGIC,
+	EFIVARFS_MAGIC,
+	TSEMFS_MAGIC
+};
+
+static bool bypass_inode(struct inode *inode)
+{
+	bool retn = true;
+
+	unsigned int lp;
+
+	if (!S_ISREG(inode->i_mode))
+		goto done;
+
+	for (lp = 0; lp < ARRAY_SIZE(pseudo_filesystems); ++lp)
+		if (inode->i_sb->s_magic == pseudo_filesystems[lp])
+			goto done;
+	retn = false;
+
+ done:
+	return retn;
+}
+
+static int event_action(struct tsem_TMA_context *ctx,
+			enum tsem_event_type event)
+{
+	int retn = 0;
+
+	if (tsem_task_trusted(current))
+		return retn;
+
+	if (ctx->actions[event] == TSEM_ACTION_EPERM)
+		retn = -EPERM;
+
+	return retn;
+}
+
+int return_trapped_task(enum tsem_event_type event, char *msg)
+{
+	int retn;
+	struct tsem_TMA_context *ctx = tsem_context(current);
+
+	pr_warn("Untrusted %s: comm=%s, pid=%d, parameters='%s'\n",
+		tsem_names[event], current->comm, task_pid_nr(current), msg);
+
+	if (ctx->external) {
+		retn = tsem_export_action(event);
+		if (retn)
+			return retn;
+	}
+
+	return event_action(ctx, event);
+}
+
+static int return_trapped_inode(enum tsem_event_type event,
+				struct inode *inode, char *inode_msg)
+{
+	const char *dname;
+	char msg[TRAPPED_MSG_LENGTH];
+	struct dentry *dird;
+
+	dird = d_find_alias(inode);
+	if (dird == NULL)
+		dname = "not available";
+	else
+		dname = dird->d_name.name;
+	scnprintf(msg, sizeof(msg), "parent=%s, %s", dname, inode_msg);
+
+	return return_trapped_task(event, msg);
+}
+
+static int model_event(struct tsem_event *ep)
+{
+	int retn;
+	struct tsem_TMA_context *ctx = tsem_context(current);
+
+	if (!ctx->id && no_root_modeling)
+		return 0;
+
+	if (!ctx->external) {
+		retn = tsem_model_event(ep);
+		if (retn)
+			return retn;
+		goto done;
+	}
+
+	retn = tsem_export_event(ep);
+	if (retn)
+		return retn;
+
+ done:
+	return event_action(ctx, ep->event);
+}
+
+static int model_generic_event(enum tsem_event_type event)
+{
+	int retn;
+	struct tsem_event *ep;
+	struct tsem_event_parameters params;
+
+	if (!tsem_context(current)->id && no_root_modeling)
+		return 0;
+
+	params.u.event_type = event;
+	ep = tsem_map_event(TSEM_GENERIC_EVENT, &params);
+	if (IS_ERR(ep)) {
+		retn = PTR_ERR(ep);
+		goto done;
+	}
+
+	retn = model_event(ep);
+	tsem_event_put(ep);
+
+ done:
+	return retn;
+}
+
+static int model_generic_event_locked(enum tsem_event_type event)
+{
+	return 0;
+}
+
+static int tsem_file_open(struct file *file)
+{
+	int retn = 0;
+	char msg[TRAPPED_MSG_LENGTH];
+	struct inode *inode = file_inode(file);
+	struct tsem_event *ep = NULL;
+	struct tsem_event_parameters params;
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "filename=%s, flags=0x%x",
+			 file->f_path.dentry->d_name.name, file->f_flags);
+		return return_trapped_task(TSEM_FILE_OPEN, msg);
+	}
+
+	if (bypass_inode(inode))
+		goto done;
+	if (tsem_inode(inode)->status == TSEM_INODE_COLLECTING)
+		goto done;
+
+	params.u.file = file;
+	ep = tsem_map_event(TSEM_FILE_OPEN, &params);
+	if (IS_ERR(ep)) {
+		retn = PTR_ERR(ep);
+		goto done;
+	}
+
+	retn = model_event(ep);
+	tsem_event_put(ep);
+
+ done:
+	return retn;
+}
+
+static int tsem_mmap_file(struct file *file, unsigned long reqprot,
+			  unsigned long prot, unsigned long flags)
+{
+	int retn = 0;
+	const char *p;
+	char msg[TRAPPED_MSG_LENGTH];
+	struct inode *inode = NULL;
+	struct tsem_event *ep = NULL;
+	struct tsem_event_parameters params;
+	struct tsem_mmap_file_args args;
+
+	if (tsem_task_untrusted(current)) {
+		p = "anonymous mapping";
+		if (file)
+			p = file->f_path.dentry->d_name.name;
+		scnprintf(msg, sizeof(msg),
+			  "filename=%s, rprot=0x%lx, prot=0x%lx, flags=0x%lx",
+			  p, reqprot, prot, flags);
+		return return_trapped_task(TSEM_MMAP_FILE, msg);
+	}
+
+	if (!file && !(prot & PROT_EXEC))
+		goto done;
+	if (file) {
+		inode = file_inode(file);
+		if (bypass_inode(inode))
+			goto done;
+	}
+
+	args.file = file;
+	args.anonymous = file == NULL ? 1 : 0;
+	args.reqprot = reqprot;
+	args.prot = prot;
+	args.flags = flags;
+	params.u.mmap_file = &args;
+	ep = tsem_map_event(TSEM_MMAP_FILE, &params);
+	if (IS_ERR(ep)) {
+		retn = PTR_ERR(ep);
+		goto done;
+	}
+
+	retn = model_event(ep);
+	tsem_event_put(ep);
+
+ done:
+	return retn;
+}
+
+static int tsem_file_ioctl(struct file *file, unsigned int cmd,
+			   unsigned long arg)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "name=%s, cmd=%u",
+			  file->f_path.dentry->d_name.name, cmd);
+		return return_trapped_task(TSEM_FILE_IOCTL, msg);
+	}
+
+	if (bypass_inode(file_inode(file)))
+		return 0;
+
+	return model_generic_event(TSEM_FILE_IOCTL);
+}
+
+static int tsem_file_lock(struct file *file, unsigned int cmd)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "name=%s, cmd=%u",
+			  file->f_path.dentry->d_name.name, cmd);
+		return return_trapped_task(TSEM_FILE_LOCK, msg);
+	}
+
+	return model_generic_event(TSEM_FILE_LOCK);
+}
+
+static int tsem_file_fcntl(struct file *file, unsigned int cmd,
+			   unsigned long arg)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "name=%s, cmd=%u",
+			  file->f_path.dentry->d_name.name, cmd);
+		return return_trapped_task(TSEM_FILE_FCNTL, msg);
+	}
+
+	if (bypass_inode(file_inode(file)))
+		return 0;
+
+	return model_generic_event(TSEM_FILE_FCNTL);
+}
+
+static int tsem_file_receive(struct file *file)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "name=%s, flags=%u",
+			  file->f_path.dentry->d_name.name, file->f_flags);
+		return return_trapped_task(TSEM_FILE_RECEIVE, msg);
+	}
+
+	return model_generic_event(TSEM_FILE_RECEIVE);
+}
+
+static int tsem_task_alloc(struct task_struct *new, unsigned long flags)
+{
+	struct tsem_task *old_task = tsem_task(current);
+	struct tsem_task *new_task = tsem_task(new);
+
+	new_task->trust_status = old_task->trust_status;
+	new_task->context = old_task->context;
+	if (!new_task->context->id)
+		return 0;
+
+	if (new_task->context->id)
+		tsem_ns_get(new_task->context);
+	return 0;
+}
+
+static void tsem_task_free(struct task_struct *task)
+{
+	struct tsem_TMA_context *ctx = tsem_context(task);
+
+	if (!ctx->id)
+		return;
+	if (ctx->id)
+		tsem_ns_put(ctx);
+}
+
+static int tsem_task_kill(struct task_struct *target,
+			  struct kernel_siginfo *info, int sig,
+			  const struct cred *cred)
+{
+	int retn = 0;
+	char msg[TRAPPED_MSG_LENGTH];
+	struct tsem_TMA_context *src_ctx = tsem_context(current);
+	struct tsem_TMA_context *tgt_ctx = tsem_context(target);
+
+	if (tsem_task_untrusted(current)) {
+		snprintf(msg, sizeof(msg),
+			 "target=%s, pid=%d, signal=%d", target->comm,
+			 task_pid_nr(target), sig);
+		return return_trapped_task(TSEM_TASK_KILL, msg);
+	}
+
+	if (SI_FROMKERNEL(info))
+		return retn;
+	if (capable(CAP_TRUST))
+		return retn;
+	if (has_capability_noaudit(target, CAP_TRUST))
+		return -EPERM;
+	if (src_ctx->id != tgt_ctx->id)
+		return -EPERM;
+	if (sig == SIGURG)
+		return 0;
+
+	return model_generic_event_locked(TSEM_TASK_KILL);
+}
+
+static int tsem_ptrace_traceme(struct task_struct *parent)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "parent=%s", parent->comm);
+		return return_trapped_task(TSEM_PTRACE_TRACEME, msg);
+	}
+
+	return model_generic_event(TSEM_PTRACE_TRACEME);
+}
+
+/*
+ * The best that can be done with respect to modeling this security
+ * event is to trap an attempt by an untrusted task to exercise the
+ * functionality.  This is secondary to the fact that the invocation
+ * point for this hook holds the global tasklist lock, causing both
+ * internal and external modeling to deadlock, given that both methods
+ * can cause current task to be scheduled away.
+ */
+static int tsem_task_setpgid(struct task_struct *p, pid_t pgid)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+	struct tsem_TMA_context *ctx = tsem_context(current);
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "target=%s", p->comm);
+		pr_warn("Untrusted %s: comm=%s, pid=%d, parameters='%s'\n",
+			tsem_names[TSEM_TASK_SETPGID], current->comm,
+			task_pid_nr(current), msg);
+		return event_action(ctx, TSEM_TASK_SETPGID);
+	}
+
+	return model_generic_event_locked(TSEM_TASK_SETPGID);
+}
+
+static int tsem_task_getpgid(struct task_struct *p)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "target=%s", p->comm);
+		return return_trapped_task(TSEM_TASK_GETPGID, msg);
+	}
+
+	return model_generic_event(TSEM_TASK_GETPGID);
+}
+
+static int tsem_task_getsid(struct task_struct *p)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "target=%s", p->comm);
+		return return_trapped_task(TSEM_TASK_GETSID, msg);
+	}
+
+	return model_generic_event(TSEM_TASK_GETSID);
+}
+
+static int tsem_task_setnice(struct task_struct *p, int nice)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "target=%s, nice=%d",
+			  p->comm, nice);
+		return return_trapped_task(TSEM_TASK_SETNICE, msg);
+	}
+
+	return model_generic_event(TSEM_TASK_SETNICE);
+}
+
+static int tsem_task_setioprio(struct task_struct *p, int ioprio)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "target=%s, ioprio=%d",
+			  p->comm, ioprio);
+		return return_trapped_task(TSEM_TASK_SETIOPRIO, msg);
+	}
+
+	return model_generic_event(TSEM_TASK_SETIOPRIO);
+}
+
+static int tsem_task_getioprio(struct task_struct *p)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "target=%s", p->comm);
+		return return_trapped_task(TSEM_TASK_GETIOPRIO, msg);
+	}
+
+	return model_generic_event(TSEM_TASK_GETIOPRIO);
+}
+
+static int tsem_task_prlimit(const struct cred *cred, const struct cred *tcred,
+			     unsigned int flags)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg),
+			  "uid=%d, gid=%d, euid=%d, egid=%d, flags=%u",
+			  from_kuid(&init_user_ns, tcred->uid),
+			  from_kgid(&init_user_ns, tcred->gid),
+			  from_kuid(&init_user_ns, tcred->euid),
+			  from_kgid(&init_user_ns, tcred->egid), flags);
+		return return_trapped_task(TSEM_TASK_PRLIMIT, msg);
+	}
+
+	return model_generic_event_locked(TSEM_TASK_PRLIMIT);
+}
+
+/*
+ * See the comment above tsem_task_setrlimit for possible issues.
+ * Currently this security event hook has been tested safe but
+ * consideration should be given to global tasklist locking.
+ */
+static int tsem_task_setrlimit(struct task_struct *p, unsigned int resource,
+			       struct rlimit *new_rlim)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg),
+			  "target=%s, res=%u, cur=%lu, max=%lu",
+			  p->comm, resource, new_rlim->rlim_cur,
+			  new_rlim->rlim_max);
+		return return_trapped_task(TSEM_TASK_SETRLIMIT, msg);
+	}
+
+	return model_generic_event_locked(TSEM_TASK_SETRLIMIT);
+}
+
+static int tsem_task_setscheduler(struct task_struct *p)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "target=%s", p->comm);
+		return return_trapped_task(TSEM_TASK_SETSCHEDULER, msg);
+	}
+
+	return model_generic_event_locked(TSEM_TASK_SETSCHEDULER);
+}
+
+static int tsem_task_getscheduler(struct task_struct *p)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "target=%s", p->comm);
+		return return_trapped_task(TSEM_TASK_GETSCHEDULER, msg);
+	}
+
+	return model_generic_event_locked(TSEM_TASK_GETSCHEDULER);
+}
+
+static int tsem_task_prctl(int option, unsigned long arg2, unsigned long arg3,
+			   unsigned long arg4, unsigned long arg5)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "option=%d", option);
+		return return_trapped_task(TSEM_TASK_PRCTL, msg);
+	}
+
+	return model_generic_event_locked(TSEM_TASK_PRCTL);
+}
+
+static int tsem_bprm_creds_for_exec(struct linux_binprm *bprm)
+{
+	struct tsem_task *task = tsem_task(current);
+
+	return tsem_map_task(bprm->file, task->task_id);
+}
+
+static int tsem_inode_alloc_security(struct inode *inode)
+{
+	struct tsem_inode *tsip = tsem_inode(inode);
+
+	mutex_init(&tsip->mutex);
+	return 0;
+}
+
+#ifdef CONFIG_SECURITY_NETWORK
+static int tsem_unix_stream_connect(struct sock *sock, struct sock *other,
+				    struct sock *newsk)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "family=%u/%u, ",
+			  sock->sk_family, other->sk_family);
+		return return_trapped_task(TSEM_UNIX_STREAM_CONNECT, msg);
+	}
+
+	return model_generic_event_locked(TSEM_UNIX_STREAM_CONNECT);
+}
+
+static int tsem_unix_may_send(struct socket *sock, struct socket *other)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+	struct sock *sk = sock->sk;
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "family=%u, type=%u",
+			  sk->sk_family, sock->type);
+		return return_trapped_task(TSEM_UNIX_MAY_SEND, msg);
+	}
+
+	return model_generic_event_locked(TSEM_UNIX_MAY_SEND);
+}
+
+static int tsem_socket_create(int family, int type, int protocol, int kern)
+{
+	int retn;
+	char msg[TRAPPED_MSG_LENGTH];
+	struct tsem_event *ep;
+	struct tsem_event_parameters params;
+	struct tsem_socket_create_args args;
+
+	if (unlikely(!tsem_ready))
+		return 0;
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg),
+			  "family=%d, type=%d, protocol=%d, kern=%d", family,
+			  type, protocol, kern);
+		return return_trapped_task(TSEM_SOCKET_CREATE, msg);
+	}
+
+	args.family = family;
+	args.type = type;
+	args.protocol = protocol;
+	args.kern = kern;
+	params.u.socket_create = &args;
+
+	ep = tsem_map_event(TSEM_SOCKET_CREATE, &params);
+	if (IS_ERR(ep)) {
+		retn = PTR_ERR(ep);
+		goto done;
+	}
+
+	retn = model_event(ep);
+	tsem_event_put(ep);
+
+ done:
+	return retn;
+}
+
+static int tsem_socket_connect(struct socket *sock, struct sockaddr *addr,
+			     int addr_len)
+
+{
+	int retn;
+	char msg[TRAPPED_MSG_LENGTH];
+	struct tsem_event *ep;
+	struct tsem_event_parameters params;
+	struct tsem_socket_connect_args args;
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "family=%u", addr->sa_family);
+		return return_trapped_task(TSEM_SOCKET_CONNECT, msg);
+	}
+
+	args.tsip = tsem_inode(SOCK_INODE(sock));
+	args.addr = addr;
+	args.addr_len = addr_len;
+	params.u.socket_connect = &args;
+
+	ep = tsem_map_event(TSEM_SOCKET_CONNECT, &params);
+	if (IS_ERR(ep)) {
+		retn = PTR_ERR(ep);
+		goto done;
+	}
+
+	retn = model_event(ep);
+	tsem_event_put(ep);
+
+ done:
+	return retn;
+
+}
+
+static int tsem_socket_bind(struct socket *sock, struct sockaddr *addr,
+			    int addr_len)
+
+{
+	int retn;
+	char msg[TRAPPED_MSG_LENGTH];
+	struct tsem_event *ep;
+	struct tsem_event_parameters params;
+	struct tsem_socket_connect_args args;
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "family=%u", addr->sa_family);
+		return return_trapped_task(TSEM_SOCKET_BIND, msg);
+	}
+
+	args.tsip = tsem_inode(SOCK_INODE(sock));
+	args.addr = addr;
+	args.addr_len = addr_len;
+	params.u.socket_connect = &args;
+
+	ep = tsem_map_event(TSEM_SOCKET_BIND, &params);
+	if (IS_ERR(ep)) {
+		retn = PTR_ERR(ep);
+		goto done;
+	}
+
+	retn = model_event(ep);
+	tsem_event_put(ep);
+
+ done:
+	return retn;
+
+}
+
+static int tsem_socket_accept(struct socket *sock, struct socket *newsock)
+{
+	int retn;
+	char msg[TRAPPED_MSG_LENGTH];
+	struct sock *sk = sock->sk;
+	const struct in6_addr *ipv6;
+	struct tsem_event *ep;
+	struct tsem_event_parameters params;
+	struct tsem_socket_accept_args args;
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "family=%u", sk->sk_family);
+		return return_trapped_task(TSEM_SOCKET_ACCEPT, msg);
+	}
+
+	args.tsip = tsem_inode(SOCK_INODE(sock));
+	args.family = sk->sk_family;
+	args.type = sock->type;
+	args.port = sk->sk_num;
+	args.ipv4 = sk->sk_rcv_saddr;
+	ipv6 = inet6_rcv_saddr(sk);
+	if (ipv6)
+		args.ipv6 = *ipv6;
+	params.u.socket_accept = &args;
+
+	ep = tsem_map_event(TSEM_SOCKET_ACCEPT, &params);
+	if (IS_ERR(ep)) {
+		retn = PTR_ERR(ep);
+		goto done;
+	}
+
+	retn = model_event(ep);
+	tsem_event_put(ep);
+
+ done:
+	return retn;
+}
+
+static int tsem_socket_listen(struct socket *sock, int backlog)
+
+{
+	char msg[TRAPPED_MSG_LENGTH];
+	struct sock *sk = sock->sk;
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "family=%u, type=%u, port=%u",
+			  sk->sk_family, sock->type, sk->sk_num);
+		return return_trapped_task(TSEM_SOCKET_LISTEN, msg);
+	}
+
+	return model_generic_event(TSEM_SOCKET_LISTEN);
+}
+
+static int tsem_socket_socketpair(struct socket *socka, struct socket *sockb)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+	struct sock *ska = socka->sk, *skb = sockb->sk;
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "family a=%u, family b=%u",
+			  ska->sk_family, skb->sk_family);
+		return return_trapped_task(TSEM_SOCKET_SOCKETPAIR, msg);
+	}
+
+	return model_generic_event(TSEM_SOCKET_SOCKETPAIR);
+}
+
+static int tsem_socket_sendmsg(struct socket *sock, struct msghdr *msgmsg,
+			       int size)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+	struct sock *sk = sock->sk;
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "family=%u, size=%d",
+			  sk->sk_family, size);
+		return return_trapped_task(TSEM_SOCKET_SENDMSG, msg);
+	}
+
+	return model_generic_event(TSEM_SOCKET_SENDMSG);
+}
+
+static int tsem_socket_recvmsg(struct socket *sock, struct msghdr *msgmsg,
+			       int size, int flags)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+	struct sock *sk = sock->sk;
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "family=%u, size=%d, flags=%d",
+			  sk->sk_family, size, flags);
+		return return_trapped_task(TSEM_SOCKET_RECVMSG, msg);
+	}
+
+	return model_generic_event(TSEM_SOCKET_RECVMSG);
+}
+
+static int tsem_socket_getsockname(struct socket *sock)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+	struct sock *sk = sock->sk;
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "family=%u", sk->sk_family);
+		return return_trapped_task(TSEM_SOCKET_GETSOCKNAME, msg);
+	}
+
+	return model_generic_event(TSEM_SOCKET_GETSOCKNAME);
+}
+
+static int tsem_socket_getpeername(struct socket *sock)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+	struct sock *sk = sock->sk;
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "family=%u", sk->sk_family);
+		return return_trapped_task(TSEM_SOCKET_GETPEERNAME, msg);
+	}
+
+	return model_generic_event(TSEM_SOCKET_GETPEERNAME);
+}
+
+static int tsem_socket_setsockopt(struct socket *sock, int level, int optname)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+	struct sock *sk = sock->sk;
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "family=%u, level=%d, optname=%d",
+			  sk->sk_family, level, optname);
+		return return_trapped_task(TSEM_SOCKET_SETSOCKOPT, msg);
+	}
+
+	return model_generic_event(TSEM_SOCKET_SETSOCKOPT);
+}
+
+static int tsem_socket_shutdown(struct socket *sock, int how)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+	struct sock *sk = sock->sk;
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "family=%u, how=%d",
+			  sk->sk_family, how);
+		return return_trapped_task(TSEM_SOCKET_SHUTDOWN, msg);
+	}
+
+	return model_generic_event(TSEM_SOCKET_SHUTDOWN);
+}
+#endif
+
+static int tsem_kernel_module_request(char *kmod_name)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (unlikely(!tsem_ready))
+		return 0;
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "module=%s", kmod_name);
+		return return_trapped_task(TSEM_KERNEL_MODULE_REQUEST, msg);
+	}
+
+	return model_generic_event(TSEM_KERNEL_MODULE_REQUEST);
+}
+
+static int tsem_kernel_load_data(enum kernel_load_data_id id, bool contents)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "id=%d, contents=%d", id,
+			  contents);
+		return return_trapped_task(TSEM_KERNEL_LOAD_DATA, msg);
+	}
+
+	return model_generic_event(TSEM_KERNEL_LOAD_DATA);
+}
+
+static int tsem_kernel_read_file(struct file *file,
+				 enum kernel_read_file_id id, bool contents)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg),
+			  "filename=%s, flags=0x%x, id=%d, contents=%d",
+			  file->f_path.dentry->d_name.name, file->f_flags,
+			  id, contents);
+		return return_trapped_task(TSEM_KERNEL_READ_FILE, msg);
+	}
+
+	return model_generic_event(TSEM_KERNEL_READ_FILE);
+}
+
+static int tsem_sb_mount(const char *dev_name, const struct path *path,
+			 const char *type, unsigned long flags, void *data)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (unlikely(!tsem_ready))
+		return 0;
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "device=%s, type=%s, flags=%lu",
+			  dev_name, type, flags);
+		return return_trapped_task(TSEM_SB_MOUNT, msg);
+	}
+
+	return model_generic_event(TSEM_SB_MOUNT);
+}
+
+static	int tsem_sb_umount(struct vfsmount *mnt, int flags)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "root=%s, flags=%d",
+			  mnt->mnt_root->d_name.name, flags);
+		return return_trapped_task(TSEM_SB_UMOUNT, msg);
+	}
+
+	return model_generic_event(TSEM_SB_UMOUNT);
+}
+
+static int tsem_sb_remount(struct super_block *sb, void *mnt_opts)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (unlikely(!tsem_ready))
+		return 0;
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "fstype=%s, type=%s",
+			  sb->s_type->name, sb->s_root->d_name.name);
+		return return_trapped_task(TSEM_SB_REMOUNT, msg);
+	}
+
+	return model_generic_event(TSEM_SB_REMOUNT);
+}
+
+static int tsem_sb_pivotroot(const struct path *old_path,
+			     const struct path *new_path)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "%s -> %s",
+			  old_path->dentry->d_name.name,
+			  new_path->dentry->d_name.name);
+		return return_trapped_task(TSEM_SB_PIVOTROOT, msg);
+	}
+
+	return model_generic_event(TSEM_SB_PIVOTROOT);
+}
+
+static int tsem_sb_statfs(struct dentry *dentry)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "name=%s", dentry->d_name.name);
+		return return_trapped_task(TSEM_SB_STATFS, msg);
+	}
+
+	return model_generic_event(TSEM_SB_STATFS);
+}
+
+static int tsem_move_mount(const struct path *from_path,
+			   const struct path *to_path)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "%s -> %s",
+			  from_path->dentry->d_name.name,
+			  to_path->dentry->d_name.name);
+		return return_trapped_task(TSEM_MOVE_MOUNT, msg);
+	}
+
+	return model_generic_event(TSEM_MOVE_MOUNT);
+}
+
+static int tsem_shm_associate(struct kern_ipc_perm *perm, int shmflg)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "id=%d, mode=%u, flags=%d",
+			  perm->id, perm->mode, shmflg);
+		return return_trapped_task(TSEM_SHM_ASSOCIATE, msg);
+	}
+
+	return model_generic_event(TSEM_SHM_ASSOCIATE);
+}
+
+static int tsem_shm_shmctl(struct kern_ipc_perm *perm, int cmd)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "id=%d, mode=%u, cmd=%d",
+			  perm->id, perm->mode, cmd);
+		return return_trapped_task(TSEM_SHM_SHMCTL, msg);
+	}
+
+	return model_generic_event(TSEM_SHM_SHMCTL);
+}
+
+static int tsem_shm_shmat(struct kern_ipc_perm *perm, char __user *shmaddr,
+			  int shmflg)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "id=%d, mode=%u, flag=%d",
+			  perm->id, perm->mode, shmflg);
+		return return_trapped_task(TSEM_SHM_SHMAT, msg);
+	}
+
+	return model_generic_event(TSEM_SHM_SHMAT);
+}
+
+static int tsem_sem_associate(struct kern_ipc_perm *perm, int semflg)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "id=%d, mode=%u, flag=%d",
+			  perm->id, perm->mode, semflg);
+		return return_trapped_task(TSEM_SEM_ASSOCIATE, msg);
+	}
+
+	return model_generic_event(TSEM_SEM_ASSOCIATE);
+}
+
+static int tsem_sem_semctl(struct kern_ipc_perm *perm, int cmd)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "id=%d, mode=%u, cmd=%d",
+			  perm->id, perm->mode, cmd);
+		return return_trapped_task(TSEM_SEM_SEMCTL, msg);
+	}
+
+	return model_generic_event(TSEM_SEM_SEMCTL);
+}
+
+static int tsem_sem_semop(struct kern_ipc_perm *perm, struct sembuf *sops,
+			  unsigned int nsops, int alter)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg),
+			  "id=%d, mode=%u, nsops=%u, alter=%d", perm->id,
+			  perm->mode, nsops, alter);
+		return return_trapped_task(TSEM_SEM_SEMOP, msg);
+	}
+
+	return model_generic_event(TSEM_SEM_SEMOP);
+}
+
+static int tsem_syslog(int type)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "type=%d", type);
+		return return_trapped_task(TSEM_SYSLOG, msg);
+	}
+
+	return model_generic_event(TSEM_SYSLOG);
+}
+
+static int tsem_settime(const struct timespec64 *ts, const struct timezone *tz)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg),
+			  "secs=%lld, nsecs=%ld, mwest=%d, dsttime=%d",
+			  ts->tv_sec, ts->tv_nsec, tz->tz_minuteswest,
+			  tz->tz_dsttime);
+		return return_trapped_task(TSEM_SETTIME, msg);
+	}
+
+	return model_generic_event(TSEM_SETTIME);
+}
+
+static int tsem_quotactl(int cmds, int type, int id, struct super_block *sb)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg),
+			  "cmds=%d, type=%d, id=%d, fstype=%s, type=%s", cmds,
+			  type, id, sb->s_type->name, sb->s_root->d_name.name);
+		return return_trapped_task(TSEM_QUOTACTL, msg);
+	}
+
+	return model_generic_event(TSEM_QUOTACTL);
+}
+
+static int tsem_quota_on(struct dentry *dentry)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "name=%s", dentry->d_name.name);
+		return return_trapped_task(TSEM_QUOTA_ON, msg);
+	}
+
+	return model_generic_event(TSEM_QUOTA_ON);
+}
+
+static int tsem_msg_queue_associate(struct kern_ipc_perm *perm, int msqflg)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg),
+			  "id=%d, mode=%u, msqflg=%d", perm->id, perm->mode,
+			  msqflg);
+		return return_trapped_task(TSEM_MSG_QUEUE_ASSOCIATE, msg);
+	}
+
+	return model_generic_event(TSEM_MSG_QUEUE_ASSOCIATE);
+}
+
+static int tsem_msg_queue_msgsnd(struct kern_ipc_perm *perm,
+				 struct msg_msg *msgmsg, int msqflg)
+
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg),
+			  "id=%d, mode=%u, msqflg=%d", perm->id, perm->mode,
+			  msqflg);
+		return return_trapped_task(TSEM_MSG_QUEUE_MSGSND, msg);
+	}
+
+	return model_generic_event(TSEM_MSG_QUEUE_MSGSND);
+}
+
+static int tsem_msg_queue_msgctl(struct kern_ipc_perm *perm, int cmd)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg),
+			  "id=%d, mode=%u, cmd=%d", perm->id, perm->mode,
+			  cmd);
+		return return_trapped_task(TSEM_MSG_QUEUE_MSGCTL, msg);
+	}
+
+	return model_generic_event(TSEM_MSG_QUEUE_MSGCTL);
+}
+
+static int tsem_msg_queue_msgrcv(struct kern_ipc_perm *perm,
+				 struct msg_msg *msgmsg,
+				 struct task_struct *target, long type,
+				 int mode)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg),
+			  "id=%d, mode=%u, target=%s, type=%ld, mode=%d",
+			  perm->id, perm->mode, target->comm, type, mode);
+		return return_trapped_task(TSEM_MSG_QUEUE_MSGSND, msg);
+	}
+
+	return model_generic_event(TSEM_MSG_QUEUE_MSGSND);
+}
+
+static int tsem_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg),
+			  "uid=%d, gid=%d, mode=%u, flag=%u",
+			  from_kuid(&init_user_ns, ipcp->uid),
+			  from_kgid(&init_user_ns, ipcp->gid), ipcp->mode,
+			  flag);
+		return return_trapped_task(TSEM_IPC_PERMISSION, msg);
+	}
+
+	return model_generic_event(TSEM_IPC_PERMISSION);
+}
+
+#ifdef CONFIG_KEYS
+static int tsem_key_alloc(struct key *key, const struct cred *cred,
+			  unsigned long flags)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg),
+			  "uid=%d, gid=%d, euid=%d, egid=%d, flags=%lu",
+			  from_kuid(&init_user_ns, cred->uid),
+			  from_kgid(&init_user_ns, cred->gid),
+			  from_kuid(&init_user_ns, cred->euid),
+			  from_kgid(&init_user_ns, cred->egid), flags);
+		return return_trapped_task(TSEM_KEY_ALLOC, msg);
+	}
+
+	return model_generic_event(TSEM_KEY_ALLOC);
+}
+
+static int tsem_key_permission(key_ref_t key_ref, const struct cred *cred,
+			       unsigned int perm)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg),
+			  "uid=%d, gid=%d, euid=%d, egid=%d, perm=%u",
+			  from_kuid(&init_user_ns, cred->uid),
+			  from_kgid(&init_user_ns, cred->gid),
+			  from_kuid(&init_user_ns, cred->euid),
+			  from_kgid(&init_user_ns, cred->egid), perm);
+		return return_trapped_task(TSEM_KEY_PERMISSION, msg);
+	}
+
+	return model_generic_event_locked(TSEM_KEY_PERMISSION);
+}
+#endif
+
+static int tsem_netlink_send(struct sock *sk, struct sk_buff *skb)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+	struct scm_creds *cred;
+
+	if (tsem_task_untrusted(current)) {
+		cred = NETLINK_CREDS(skb);
+		scnprintf(msg, sizeof(msg),
+			  "uid=%d, gid=%d",
+			  from_kuid(&init_user_ns, cred->uid),
+			  from_kgid(&init_user_ns, cred->gid));
+		return return_trapped_task(TSEM_KEY_PERMISSION, msg);
+	}
+
+	return model_generic_event(TSEM_KEY_PERMISSION);
+}
+
+static int tsem_inode_create(struct inode *dir,
+			     struct dentry *dentry, umode_t mode)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "name=%s, mode=%u",
+			  dentry->d_name.name, mode);
+		return return_trapped_inode(TSEM_INODE_CREATE, dir, msg);
+	}
+
+	if (bypass_inode(dir))
+		return 0;
+	return model_generic_event(TSEM_INODE_CREATE);
+}
+
+static int tsem_inode_link(struct dentry *old_dentry, struct inode *dir,
+			   struct dentry *new_dentry)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "old_name=%s, new_name=%s",
+			  old_dentry->d_name.name, new_dentry->d_name.name);
+		return return_trapped_task(TSEM_INODE_LINK, msg);
+	}
+
+	if (bypass_inode(dir))
+		return 0;
+	return model_generic_event(TSEM_INODE_LINK);
+}
+
+static int tsem_inode_unlink(struct inode *dir, struct dentry *dentry)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "target=%s", dentry->d_name.name);
+		return return_trapped_inode(TSEM_INODE_UNLINK, dir, msg);
+	}
+
+	if (bypass_inode(dir))
+		return 0;
+	return model_generic_event(TSEM_INODE_UNLINK);
+}
+
+static int tsem_inode_symlink(struct inode *dir, struct dentry *dentry,
+			      const char *old_name)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "target=%s", dentry->d_name.name);
+		return return_trapped_task(TSEM_INODE_UNLINK, msg);
+	}
+
+	if (bypass_inode(dir))
+		return 0;
+	return model_generic_event(TSEM_INODE_UNLINK);
+}
+
+static int tsem_inode_mkdir(struct inode *dir, struct dentry *dentry,
+			    umode_t mode)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "target=%s, mode=%u",
+			  dentry->d_name.name, mode);
+		return return_trapped_task(TSEM_INODE_MKDIR, msg);
+	}
+
+	if (bypass_inode(dir))
+		return 0;
+	return model_generic_event(TSEM_INODE_MKDIR);
+}
+
+static int tsem_inode_rmdir(struct inode *dir, struct dentry *dentry)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "name=%s", dentry->d_name.name);
+		return return_trapped_task(TSEM_INODE_RMDIR, msg);
+	}
+
+	if (bypass_inode(dir))
+		return 0;
+	return model_generic_event(TSEM_INODE_RMDIR);
+}
+
+static int tsem_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
+			     struct inode *new_dir, struct dentry *new_dentry)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "old=%s, new=%s",
+			  old_dentry->d_name.name, new_dentry->d_name.name);
+		return return_trapped_task(TSEM_INODE_RENAME, msg);
+	}
+
+	if (bypass_inode(old_dir))
+		return 0;
+	return model_generic_event(TSEM_INODE_RENAME);
+}
+
+static int tsem_inode_mknod(struct inode *dir, struct dentry *dentry,
+			    umode_t mode, dev_t dev)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "name=%s, mode=%u, dev=%u",
+			  dentry->d_name.name, mode, dev);
+		return return_trapped_task(TSEM_INODE_MKNOD, msg);
+	}
+
+	return model_generic_event(TSEM_INODE_MKNOD);
+}
+
+static int tsem_inode_setattr(struct dentry *dentry, struct iattr *attr)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg),
+			  "name=%s, mode=%u, uid=%d, gid=%d, size=%llu",
+			  dentry->d_name.name, attr->ia_mode,
+			  from_kuid(&init_user_ns, attr->ia_uid),
+			  from_kgid(&init_user_ns, attr->ia_gid),
+			  attr->ia_size);
+		return return_trapped_task(TSEM_INODE_SETATTR, msg);
+	}
+
+	return model_generic_event(TSEM_INODE_SETATTR);
+}
+
+static int tsem_inode_getattr(const struct path *path)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "name=%s",
+			  path->dentry->d_name.name);
+		return return_trapped_task(TSEM_INODE_GETATTR, msg);
+	}
+
+	return model_generic_event(TSEM_INODE_GETATTR);
+}
+
+static int tsem_inode_setxattr(struct user_namespace *mnt_userns,
+			       struct dentry *dentry, const char *name,
+			       const void *value, size_t size, int flags)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg),
+			  "fname=%s, name=%s, size=%lu, flags=%d",
+			  dentry->d_name.name, name, size, flags);
+		return return_trapped_task(TSEM_INODE_SETXATTR, msg);
+	}
+
+	return model_generic_event(TSEM_INODE_SETXATTR);
+}
+
+static int tsem_inode_getxattr(struct dentry *dentry, const char *name)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg),
+			  "fname=%s, name=%s", dentry->d_name.name, name);
+		return return_trapped_task(TSEM_INODE_GETXATTR, msg);
+	}
+
+	return model_generic_event(TSEM_INODE_GETXATTR);
+}
+
+static int tsem_inode_listxattr(struct dentry *dentry)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "fname=%s", dentry->d_name.name);
+		return return_trapped_task(TSEM_INODE_LISTXATTR, msg);
+	}
+
+	return model_generic_event(TSEM_INODE_LISTXATTR);
+}
+
+static int tsem_inode_removexattr(struct user_namespace *mnt,
+				  struct dentry *dentry, const char *name)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "fname=%s, name=%s",
+			  dentry->d_name.name, name);
+		return return_trapped_task(TSEM_INODE_REMOVEXATTR, msg);
+	}
+
+	return model_generic_event(TSEM_INODE_REMOVEXATTR);
+}
+
+static int tsem_inode_killpriv(struct user_namespace *mnt_userns,
+			       struct dentry *dentry)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "fname=%s", dentry->d_name.name);
+		return return_trapped_task(TSEM_INODE_KILLPRIV, msg);
+	}
+
+	return model_generic_event(TSEM_INODE_KILLPRIV);
+}
+
+static int tsem_tun_dev_create(void)
+{
+	if (tsem_task_untrusted(current))
+		return return_trapped_task(TSEM_TUN_DEV_CREATE, "none");
+
+	return model_generic_event(TSEM_TUN_DEV_CREATE);
+}
+
+static int tsem_tun_dev_attach_queue(void *security)
+{
+	if (tsem_task_untrusted(current))
+		return return_trapped_task(TSEM_TUN_DEV_ATTACH_QUEUE, "none");
+
+	return model_generic_event(TSEM_TUN_DEV_ATTACH_QUEUE);
+}
+
+static int tsem_tun_dev_attach(struct sock *sk, void *security)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "family=%u", sk->sk_family);
+		return return_trapped_task(TSEM_TUN_DEV_ATTACH, msg);
+	}
+
+	return model_generic_event(TSEM_TUN_DEV_ATTACH);
+}
+
+static int tsem_tun_dev_open(void *security)
+{
+	if (tsem_task_untrusted(current))
+		return return_trapped_task(TSEM_TUN_DEV_OPEN, "none");
+
+	return model_generic_event(TSEM_TUN_DEV_OPEN);
+}
+
+#ifdef CONFIG_BPF_SYSCALL
+static int tsem_bpf(int cmd, union bpf_attr *attr, unsigned int size)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "cmd=%d, size=%u", cmd, size);
+		return return_trapped_task(TSEM_BPF, msg);
+	}
+
+	return model_generic_event(TSEM_BPF);
+}
+
+static int tsem_bpf_map(struct bpf_map *map, fmode_t fmode)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "type=%d, size=%u", map->map_type,
+			  fmode);
+		return return_trapped_task(TSEM_BPF_MAP, msg);
+	}
+
+	return model_generic_event(TSEM_BPF_MAP);
+}
+
+static int tsem_bpf_prog(struct bpf_prog *prog)
+{
+	char msg[TRAPPED_MSG_LENGTH];
+
+	if (tsem_task_untrusted(current)) {
+		scnprintf(msg, sizeof(msg), "type=%d", prog->type);
+		return return_trapped_task(TSEM_BPF_PROG, msg);
+	}
+
+	return model_generic_event(TSEM_BPF_PROG);
+}
+#endif
+
+static struct security_hook_list tsem_hooks[] __lsm_ro_after_init = {
+	LSM_HOOK_INIT(task_alloc, tsem_task_alloc),
+	LSM_HOOK_INIT(task_free, tsem_task_free),
+	LSM_HOOK_INIT(task_kill, tsem_task_kill),
+	LSM_HOOK_INIT(task_setpgid, tsem_task_setpgid),
+	LSM_HOOK_INIT(task_getpgid, tsem_task_getpgid),
+	LSM_HOOK_INIT(task_getsid, tsem_task_getsid),
+	LSM_HOOK_INIT(task_setnice, tsem_task_setnice),
+	LSM_HOOK_INIT(task_setioprio, tsem_task_setioprio),
+	LSM_HOOK_INIT(task_getioprio, tsem_task_getioprio),
+	LSM_HOOK_INIT(task_prlimit, tsem_task_prlimit),
+	LSM_HOOK_INIT(task_setrlimit, tsem_task_setrlimit),
+	LSM_HOOK_INIT(task_setscheduler, tsem_task_setscheduler),
+	LSM_HOOK_INIT(task_getscheduler, tsem_task_getscheduler),
+	LSM_HOOK_INIT(task_prctl, tsem_task_prctl),
+
+	LSM_HOOK_INIT(ptrace_traceme, tsem_ptrace_traceme),
+
+	LSM_HOOK_INIT(bprm_creds_for_exec, tsem_bprm_creds_for_exec),
+	LSM_HOOK_INIT(inode_alloc_security, tsem_inode_alloc_security),
+
+	LSM_HOOK_INIT(file_open, tsem_file_open),
+	LSM_HOOK_INIT(mmap_file, tsem_mmap_file),
+	LSM_HOOK_INIT(file_ioctl, tsem_file_ioctl),
+	LSM_HOOK_INIT(file_lock, tsem_file_lock),
+	LSM_HOOK_INIT(file_fcntl, tsem_file_fcntl),
+	LSM_HOOK_INIT(file_receive, tsem_file_receive),
+
+#ifdef CONFIG_SECURITY_NETWORK
+	LSM_HOOK_INIT(unix_stream_connect, tsem_unix_stream_connect),
+	LSM_HOOK_INIT(unix_may_send, tsem_unix_may_send),
+
+	LSM_HOOK_INIT(socket_create, tsem_socket_create),
+	LSM_HOOK_INIT(socket_connect, tsem_socket_connect),
+	LSM_HOOK_INIT(socket_bind, tsem_socket_bind),
+	LSM_HOOK_INIT(socket_accept, tsem_socket_accept),
+	LSM_HOOK_INIT(socket_listen, tsem_socket_listen),
+	LSM_HOOK_INIT(socket_socketpair, tsem_socket_socketpair),
+	LSM_HOOK_INIT(socket_sendmsg, tsem_socket_sendmsg),
+	LSM_HOOK_INIT(socket_recvmsg, tsem_socket_recvmsg),
+	LSM_HOOK_INIT(socket_getsockname, tsem_socket_getsockname),
+	LSM_HOOK_INIT(socket_getpeername, tsem_socket_getpeername),
+	LSM_HOOK_INIT(socket_setsockopt, tsem_socket_setsockopt),
+	LSM_HOOK_INIT(socket_shutdown, tsem_socket_shutdown),
+#endif
+
+	LSM_HOOK_INIT(kernel_module_request, tsem_kernel_module_request),
+	LSM_HOOK_INIT(kernel_load_data, tsem_kernel_load_data),
+	LSM_HOOK_INIT(kernel_read_file, tsem_kernel_read_file),
+
+	LSM_HOOK_INIT(sb_mount, tsem_sb_mount),
+	LSM_HOOK_INIT(sb_umount, tsem_sb_umount),
+	LSM_HOOK_INIT(sb_remount, tsem_sb_remount),
+	LSM_HOOK_INIT(sb_pivotroot, tsem_sb_pivotroot),
+	LSM_HOOK_INIT(sb_statfs, tsem_sb_statfs),
+	LSM_HOOK_INIT(move_mount, tsem_move_mount),
+
+	LSM_HOOK_INIT(shm_associate, tsem_shm_associate),
+	LSM_HOOK_INIT(shm_shmctl, tsem_shm_shmctl),
+	LSM_HOOK_INIT(shm_shmat, tsem_shm_shmat),
+	LSM_HOOK_INIT(sem_associate, tsem_sem_associate),
+	LSM_HOOK_INIT(sem_semctl, tsem_sem_semctl),
+	LSM_HOOK_INIT(sem_semop, tsem_sem_semop),
+
+	LSM_HOOK_INIT(syslog, tsem_syslog),
+	LSM_HOOK_INIT(settime, tsem_settime),
+
+	LSM_HOOK_INIT(quotactl, tsem_quotactl),
+	LSM_HOOK_INIT(quota_on, tsem_quota_on),
+
+	LSM_HOOK_INIT(msg_queue_associate, tsem_msg_queue_associate),
+	LSM_HOOK_INIT(msg_queue_msgctl, tsem_msg_queue_msgctl),
+	LSM_HOOK_INIT(msg_queue_msgsnd, tsem_msg_queue_msgsnd),
+	LSM_HOOK_INIT(msg_queue_msgrcv, tsem_msg_queue_msgrcv),
+
+	LSM_HOOK_INIT(ipc_permission, tsem_ipc_permission),
+
+#ifdef CONFIG_KEYS
+	LSM_HOOK_INIT(key_alloc, tsem_key_alloc),
+	LSM_HOOK_INIT(key_permission, tsem_key_permission),
+#endif
+
+	LSM_HOOK_INIT(netlink_send, tsem_netlink_send),
+
+	LSM_HOOK_INIT(inode_create, tsem_inode_create),
+	LSM_HOOK_INIT(inode_link, tsem_inode_link),
+	LSM_HOOK_INIT(inode_unlink, tsem_inode_unlink),
+	LSM_HOOK_INIT(inode_symlink, tsem_inode_symlink),
+	LSM_HOOK_INIT(inode_mkdir, tsem_inode_mkdir),
+	LSM_HOOK_INIT(inode_rmdir, tsem_inode_rmdir),
+	LSM_HOOK_INIT(inode_mknod, tsem_inode_mknod),
+	LSM_HOOK_INIT(inode_rename, tsem_inode_rename),
+	LSM_HOOK_INIT(inode_setattr, tsem_inode_setattr),
+	LSM_HOOK_INIT(inode_getattr, tsem_inode_getattr),
+	LSM_HOOK_INIT(inode_setxattr, tsem_inode_setxattr),
+	LSM_HOOK_INIT(inode_getxattr, tsem_inode_getxattr),
+	LSM_HOOK_INIT(inode_listxattr, tsem_inode_listxattr),
+	LSM_HOOK_INIT(inode_removexattr, tsem_inode_removexattr),
+	LSM_HOOK_INIT(inode_killpriv, tsem_inode_killpriv),
+
+	LSM_HOOK_INIT(tun_dev_create, tsem_tun_dev_create),
+	LSM_HOOK_INIT(tun_dev_attach_queue, tsem_tun_dev_attach_queue),
+	LSM_HOOK_INIT(tun_dev_attach, tsem_tun_dev_attach),
+	LSM_HOOK_INIT(tun_dev_open, tsem_tun_dev_open),
+
+#ifdef CONFIG_BPF_SYSCALL
+	LSM_HOOK_INIT(bpf, tsem_bpf),
+	LSM_HOOK_INIT(bpf_map, tsem_bpf_map),
+	LSM_HOOK_INIT(bpf_prog, tsem_bpf_prog)
+#endif
+};
+
+static int __init set_ready(void)
+{
+	int retn;
+
+	retn = tsem_model_add_aggregate();
+	if (retn)
+		goto done;
+
+	retn = tsem_fs_init();
+	if (retn)
+		goto done;
+
+	tsem_ready = 1;
+
+ done:
+	return retn;
+}
+
+fs_initcall(set_ready);
+
+/**
+ * tesm_init() - Register Trusted Security Event Modeling LSM.
+ *
+ * This function is responsible for initializing the TSEM LSM.  It is
+ * invoked at the fs_initcall level.  In addition to configuring the
+ * LSM hooks this function initializes the Trusted Modeling Agent
+ * context including the event actions.  The cache from which
+ * the tsem_event description structures is also initialized.
+ *
+ * Return: If the TSEM LSM is successfully initialized a value of zero
+ *	   is returned.  A non-zero error code is returned if
+ *	   initialization fails.  Currently the only failure mode can
+ *	   come from the initialization of the tsem_event cache.
+ */
+static int __init tsem_init(void)
+{
+	int retn;
+	struct tsem_task *tsk = tsem_task(current);
+
+	security_add_hooks(tsem_hooks, ARRAY_SIZE(tsem_hooks), "tsem");
+
+	tsk->context = &root_TMA_context;
+	memcpy(tsk->context->actions, tsem_root_actions,
+	       sizeof(tsem_root_actions));
+
+	retn = tsem_event_cache_init();
+	if (retn)
+		return retn;
+
+	retn = tsem_ns_init();
+	if (retn)
+		return retn;
+
+	pr_info("tsem: Initialized %s modeling.\n",
+		no_root_modeling ? "domain only" : "full");
+	tsk->trust_status = TSEM_TASK_TRUSTED;
+	return 0;
+}
+
+DEFINE_LSM(tsem) = {
+	.name = "tsem",
+	.init = tsem_init,
+	.blobs = &tsem_blob_sizes,
+};
-- 
2.39.1


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 07/14] Add root domain trust implementation.
  2023-02-04  5:09 [PATCH 00/14] Implement Trusted Security Event Modeling Dr. Greg
                   ` (5 preceding siblings ...)
  2023-02-04  5:09 ` [PATCH 06/14] Add primary TSEM implementation file Dr. Greg
@ 2023-02-04  5:09 ` Dr. Greg
  2023-02-04  5:09 ` [PATCH 08/14] Implement TSEM control plane Dr. Greg
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 42+ messages in thread
From: Dr. Greg @ 2023-02-04  5:09 UTC (permalink / raw)
  To: linux-security-module

The trust.c contains the support infrastructure for anchoring the
root modeling domain in a hardware TPM implementation if it is
available.

The security event state points are extended into Platform
Configuration Register (PCR) 11 in order to provide authentication of
the security execution trajectory for the root domain.  This
value was chosen to avoid the use of PCR register 10 that the
Integrity Measurement Architecture uses to register the integrity
events that it handles.

This file is also responsible for computing the hardware platform
aggregate measurement.  This is the linear extension sum over PCR
rsegisters 0 through 7.  This file contains an accessor function
for surfacing this value to either the internal or external
Trusted Modeling Agent implementations.

The platform hardware aggregate value is designed to be the first
security event state point injected into a model.

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

diff --git a/security/tsem/trust.c b/security/tsem/trust.c
new file mode 100644
index 000000000000..77190c07f772
--- /dev/null
+++ b/security/tsem/trust.c
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * Copyright (C) 2022 Enjellic Systems Development, LLC
+ * Author: Dr. Greg Wettstein <greg@enjellic.com>
+ *
+ * Implements management of a TPM trust root for the in kernel TMA.
+ */
+
+#include <crypto/hash.h>
+#include <linux/tpm.h>
+
+#include "tsem.h"
+
+#define TSEM_TRUST_ROOT 11
+
+static u8 hardware_aggregate[WP256_DIGEST_SIZE];
+
+static struct tpm_chip *tpm;
+
+static struct tpm_digest *digests;
+
+
+void __init generate_aggregate(struct crypto_shash *tfm)
+{
+	int retn = 0, lp;
+	struct tpm_digest pcr;
+	u8 digest[WP256_DIGEST_SIZE];
+	SHASH_DESC_ON_STACK(shash, tfm);
+
+	shash->tfm = tfm;
+	retn = crypto_shash_init(shash);
+	if (retn)
+		goto done;
+
+	if (tpm_is_tpm2(tpm))
+		pcr.alg_id = TPM_ALG_SHA256;
+	else
+		pcr.alg_id = TPM_ALG_SHA1;
+	memset(pcr.digest, '\0', TPM_MAX_DIGEST_SIZE);
+
+	for (lp = 0; lp < 8; ++lp) {
+		retn = tpm_pcr_read(tpm, lp, &pcr);
+		if (retn)
+			goto done;
+		memcpy(digest, pcr.digest, sizeof(digest));
+		retn = crypto_shash_update(shash, digest, WP256_DIGEST_SIZE);
+		if (retn)
+			goto done;
+	}
+	if (!retn)
+		retn = crypto_shash_final(shash, hardware_aggregate);
+
+ done:
+	if (retn)
+		pr_info("Unable to generate platform aggregate\n");
+}
+
+static int __init trust_init(void)
+{
+	int retn = -EINVAL, lp;
+	struct crypto_shash *tfm = NULL;
+
+	tpm = tpm_default_chip();
+	if (!tpm) {
+		pr_info("No TPM found for event modeling.\n");
+		return retn;
+	}
+
+	digests = kcalloc(tpm->nr_allocated_banks, sizeof(*digests), GFP_NOFS);
+	if (!digests) {
+		tpm = NULL;
+		return retn;
+	}
+	for (lp = 0; lp < tpm->nr_allocated_banks; lp++)
+		digests[lp].alg_id = tpm->allocated_banks[lp].alg_id;
+
+	tfm = crypto_alloc_shash("sha256", 0, 0);
+	if (IS_ERR(tfm))
+		retn = PTR_ERR(tfm);
+	else {
+		generate_aggregate(tfm);
+		retn = 0;
+	}
+	crypto_free_shash(tfm);
+
+	return retn;
+}
+
+/**
+ * tsem_trust_aggregate() - Return a pointer to the hardware aggregate.
+ *
+ * This function returns a pointer to the hardware aggregate that
+ * is computed at system boot time.
+ *
+ * Return: A byte pointer is returned to the statically scoped array
+ *	   that contains the hardware aggregate value.
+ */
+u8 *tsem_trust_aggregate(void)
+{
+	return hardware_aggregate;
+}
+
+/**
+ * tsem_trust_add_point() - Add a measurement to the trust root.
+ * @coefficient: A pointer to the event coefficient to be added.
+ *
+ * This function extends the platform configuration register being
+ * used to document the hardware root of trust for internally modeled
+ * domains with a security event coefficient value.
+ *
+ * Return: If the extension fails the error return value from the
+ *	   TPM command is returned, otherwise a value of zero is
+ *	   returned.
+ */
+int tsem_trust_add_event(u8 *coefficient)
+{
+	int amt, bank;
+
+	if (!tpm)
+		return 0;
+
+	for (bank = 0; bank < tpm->nr_allocated_banks; bank++) {
+		if (tpm->allocated_banks[bank].digest_size < WP256_DIGEST_SIZE)
+			amt = tpm->allocated_banks[bank].digest_size;
+		else
+			amt = WP256_DIGEST_SIZE;
+		memcpy(digests[bank].digest, coefficient, amt);
+	}
+
+	return tpm_pcr_extend(tpm, TSEM_TRUST_ROOT, digests);
+}
+
+late_initcall(trust_init);
-- 
2.39.1


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 08/14] Implement TSEM control plane.
  2023-02-04  5:09 [PATCH 00/14] Implement Trusted Security Event Modeling Dr. Greg
                   ` (6 preceding siblings ...)
  2023-02-04  5:09 ` [PATCH 07/14] Add root domain trust implementation Dr. Greg
@ 2023-02-04  5:09 ` Dr. Greg
  2023-02-09 11:30   ` Greg KH
  2023-02-04  5:09 ` [PATCH 09/14] Add namespace implementation Dr. Greg
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 42+ messages in thread
From: Dr. Greg @ 2023-02-04  5:09 UTC (permalink / raw)
  To: linux-security-module

The fs.c file contains the implementation of the TSEM control
plane that is in the form of a pseudo-filesystem mounted on the
following directory:

/sys/fs/tsem

The following file documents the interface provided by the
control plane:

Documentation/ABI/testing/tsemfs

The pseudo-files act on the modeling context of the process that
is acting on the file.  For example, reading the 'id'
pseudo-file, returns the modeling domain identifier that the
process is running in.

The ExternalTMA directory is used to segreate the pseudo-files
that are created in order to surface security event descriptions
to an external trust orchestrator.  The files in this directory
appear as the numeric value of the modeling domain they were
created for.

The 'control' pseudo-file is the only writable file in the plane
and is used to control the TSEM implementation.  The most
important and primary roles are to create namespaces and set the
trust status of a process modeled by an external TMA.

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

diff --git a/security/tsem/fs.c b/security/tsem/fs.c
new file mode 100644
index 000000000000..2898a1cc8c97
--- /dev/null
+++ b/security/tsem/fs.c
@@ -0,0 +1,894 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * Copyright (C) 2022 Enjellic Systems Development, LLC
+ * Author: Dr. Greg Wettstein <greg@enjellic.com>
+ *
+ * Implements the sysfs based control plane.
+ */
+
+#include <linux/seq_file.h>
+#include <linux/sysfs.h>
+#include <linux/fs_context.h>
+#include <linux/namei.h>
+#include <linux/poll.h>
+#include <uapi/linux/magic.h>
+
+#include "tsem.h"
+
+static int fs_init_context(struct fs_context *context);
+static int fs_get_tree(struct fs_context *context);
+
+static struct file_system_type fs_definition = {
+	.name = "tsemfs",
+	.init_fs_context = fs_init_context,
+	.kill_sb = kill_litter_super
+};
+
+static struct fs_context_operations fs_operations = {
+	.get_tree = fs_get_tree
+};
+
+static struct vfsmount *fs_mount;
+
+static int fs_mount_cnt;
+
+static struct dentry *external_dentry;
+
+struct control_commands {
+	char *cmd;
+	enum tsem_control_type type;
+};
+
+static struct control_commands commands[9] = {
+	{"internal", TSEM_CONTROL_INTERNAL},
+	{"external", TSEM_CONTROL_EXTERNAL},
+	{"enforce", TSEM_CONTROL_ENFORCE},
+	{"seal", TSEM_CONTROL_SEAL},
+	{"trusted ", TSEM_CONTROL_TRUSTED},
+	{"untrusted ", TSEM_CONTROL_UNTRUSTED},
+	{"state ", TSEM_CONTROL_MAP_STATE},
+	{"pseudonym ", TSEM_CONTROL_MAP_PSEUDONYM},
+	{"base ", TSEM_CONTROL_MAP_BASE}
+};
+
+static bool can_access_fs(void)
+{
+	struct tsem_TMA_context *ctx = tsem_context(current);
+
+	if (ctx->external)
+		return false;
+	if (capable(TSEM_CONTROL_CAPABILITY))
+		return true;
+	if (ctx->sealed)
+		return false;
+	return true;
+}
+
+static int control_COE(pid_t pid, unsigned long cmd)
+{
+	bool wakeup = false;
+	int retn = -ESRCH;
+	struct task_struct *COE;
+	struct tsem_task *task;
+
+	rcu_read_lock();
+	COE = find_task_by_vpid(pid);
+	if (COE != NULL) {
+		task = tsem_task(COE);
+		if (cmd == TSEM_CONTROL_UNTRUSTED)
+			task->trust_status = TSEM_TASK_UNTRUSTED;
+		if (cmd == TSEM_CONTROL_TRUSTED) {
+			task->trust_status &= ~TSEM_TASK_TRUST_PENDING;
+			if (tsem_task_trusted(COE))
+				task->trust_status = TSEM_TASK_TRUSTED;
+		}
+
+		retn = 0;
+		wakeup = true;
+	}
+	rcu_read_unlock();
+
+	if (wakeup)
+		wake_up_process(COE);
+
+	return retn;
+}
+
+static int config_context(unsigned long cmd, char *bufr)
+{
+	int retn = -EINVAL;
+	unsigned int lp;
+	struct tsem_TMA_context *ctx = tsem_context(current);
+
+	if (ctx->sealed)
+		return -EPERM;
+
+	if (cmd == TSEM_CONTROL_SEAL) {
+		ctx->sealed = true;
+		retn = 0;
+	}
+
+	if (cmd == TSEM_CONTROL_ENFORCE) {
+		for (lp = 0; lp < ARRAY_SIZE(tsem_root_actions); ++lp)
+			ctx->actions[lp] = TSEM_ACTION_EPERM;
+		retn = 0;
+	}
+
+	return retn;
+}
+
+static int config_point(enum tsem_control_type type, u8 *arg)
+{
+	int retn = -EINVAL;
+	u8 mapping[WP256_DIGEST_SIZE];
+
+	if (*++arg == '\0')
+		goto done;
+	if (strlen(arg) != sizeof(mapping) * 2)
+		goto done;
+	if (hex2bin(mapping, arg, sizeof(mapping)))
+		goto done;
+
+	if (type == TSEM_CONTROL_MAP_STATE)
+		retn = tsem_model_load_point(mapping);
+	else if (type == TSEM_CONTROL_MAP_PSEUDONYM)
+		retn = tsem_model_load_pseudonym(mapping);
+	else {
+		tsem_model_load_base(mapping);
+		retn = 0;
+	}
+
+ done:
+	return retn;
+}
+
+static void show_event(struct seq_file *c, struct tsem_event *ep, char *file)
+{
+	seq_printf(c, "event{process=%s, filename=%s, type=%s, task_id=%*phN}",
+		   ep->comm, file ? file : "none", tsem_names[ep->event],
+		   WP256_DIGEST_SIZE, ep->task_id);
+	seq_printf(c, " COE{uid=%d, euid=%d, suid=%d, gid=%d, egid=%d, sgid=%d, fsuid=%d, fsgid=%d, cap=0x%llx} ",
+		   ep->COE.uid, ep->COE.euid, ep->COE.suid, ep->COE.gid,
+		   ep->COE.egid, ep->COE.sgid, ep->COE.fsuid, ep->COE.fsgid,
+		   ep->COE.capability.value);
+}
+
+static void show_file(struct seq_file *c, struct tsem_event *ep)
+{
+	seq_printf(c, "file{flags=%u, uid=%d, gid=%d, mode=0%o, name_length=%u, name=%*phN, s_magic=0x%0x, s_id=%s, s_uuid=%*phN, digest=%*phN}\n",
+		   ep->file.flags, ep->file.uid, ep->file.gid, ep->file.mode,
+		   ep->file.name_length, WP256_DIGEST_SIZE, ep->file.name,
+		   ep->file.s_magic, ep->file.s_id,
+		   (int) sizeof(ep->file.s_uuid), ep->file.s_uuid,
+		   WP256_DIGEST_SIZE, ep->file.digest);
+}
+
+static void show_mmap(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_mmap_file_args *args = &ep->CELL.mmap_file;
+
+	show_event(c, ep, args->file ? ep->pathname : NULL);
+	seq_printf(c, "%s{type=%u, reqprot=%u, prot=%u, flags=%u} ",
+		   tsem_names[ep->event], args->file == NULL,
+		   args->reqprot, args->prot, args->flags);
+
+	if (!args->file)
+		seq_puts(c, "\n");
+	else
+		show_file(c, ep);
+}
+
+static void show_socket_create(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_socket_create_args *args = &ep->CELL.socket_create;
+
+	show_event(c, ep, NULL);
+	seq_printf(c, "%s{family=%u, type=%u, protocol=%u, kern=%u}\n",
+		   tsem_names[ep->event], args->family, args->type,
+		   args->protocol, args->kern);
+}
+
+static void show_socket(struct seq_file *c, struct tsem_event *ep)
+{
+	struct sockaddr_in *ipv4;
+	struct sockaddr_in6 *ipv6;
+	struct tsem_socket_connect_args *scp = &ep->CELL.socket_connect;
+
+	show_event(c, ep, NULL);
+	seq_printf(c, "%s{family=%u, ", tsem_names[ep->event], scp->family);
+
+	switch (scp->family) {
+	case AF_INET:
+		ipv4 = (struct sockaddr_in *) &scp->u.ipv4;
+		seq_printf(c, "port=%u, addr=%u}\n", ipv4->sin_port,
+			   ipv4->sin_addr.s_addr);
+		break;
+	case AF_INET6:
+		ipv6 = (struct sockaddr_in6 *) &scp->u.ipv6;
+		seq_printf(c, "port=%u, flow=%u, scope=%u, addr=%*phN}\n",
+			   ipv6->sin6_port, ipv6->sin6_flowinfo,
+			   ipv6->sin6_scope_id,
+			   (int) sizeof(ipv6->sin6_addr.in6_u.u6_addr8),
+			   ipv6->sin6_addr.in6_u.u6_addr8);
+		break;
+	default:
+		seq_printf(c, "addr=%*phN}\n", WP256_DIGEST_SIZE,
+			   scp->u.mapping);
+		break;
+	}
+}
+
+static void show_socket_accept(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_socket_accept_args *sap = &ep->CELL.socket_accept;
+
+	show_event(c, ep, NULL);
+	seq_printf(c, "%s{family=%u, type=%u, port=%u, addr=",
+		   tsem_names[ep->event], sap->family, sap->type, sap->port);
+
+	switch (sap->family) {
+	case AF_INET:
+		seq_printf(c, "%u}\n", sap->ipv4);
+		break;
+	case AF_INET6:
+		seq_printf(c, "%*phN}\n",
+			   (int) sizeof(sap->ipv6.in6_u.u6_addr8),
+			   sap->ipv6.in6_u.u6_addr8);
+		break;
+	default:
+		seq_printf(c, "%*phN}\n", (int) sizeof(sap->tsip->digest),
+			   sap->tsip->digest);
+		break;
+	}
+}
+
+static void show_task_kill(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_task_kill_args *args = &ep->CELL.task_kill;
+
+	show_event(c, ep, NULL);
+	seq_printf(c, "%s{cross=%u, signal=%u, target=%*phN}\n",
+		   tsem_names[ep->event], args->cross_model, args->signal,
+		   WP256_DIGEST_SIZE, args->target);
+}
+
+static void show_event_generic(struct seq_file *c, struct tsem_event *ep)
+{
+	show_event(c, ep, NULL);
+	seq_printf(c, "%s{type=%s}\n", tsem_names[ep->event],
+		   tsem_names[ep->CELL.event_type]);
+}
+
+static void show_trajectory_event(struct seq_file *c, struct tsem_event *ep)
+{
+	switch (ep->event) {
+	case TSEM_FILE_OPEN:
+		show_event(c, ep, ep->pathname);
+		show_file(c, ep);
+		break;
+	case TSEM_MMAP_FILE:
+		show_mmap(c, ep);
+		break;
+	case TSEM_SOCKET_CREATE:
+		show_socket_create(c, ep);
+		break;
+	case TSEM_SOCKET_CONNECT:
+	case TSEM_SOCKET_BIND:
+		show_socket(c, ep);
+		break;
+	case TSEM_SOCKET_ACCEPT:
+		show_socket_accept(c, ep);
+		break;
+	case TSEM_TASK_KILL:
+		show_task_kill(c, ep);
+		break;
+	case TSEM_GENERIC_EVENT:
+		show_event_generic(c, ep);
+		break;
+	default:
+		break;
+	}
+}
+
+static void *trajectory_start(struct seq_file *c, loff_t *pos)
+{
+	struct tsem_model *model = tsem_model(current);
+
+	mutex_lock(&model->trajectory_mutex);
+	return seq_list_start(&model->trajectory_list, *pos);
+}
+
+static void *trajectory_next(struct seq_file *c, void *p, loff_t *pos)
+{
+	struct tsem_model *model = tsem_model(current);
+
+	return seq_list_next(p, &model->trajectory_list, pos);
+}
+
+static void trajectory_stop(struct seq_file *c, void *pos)
+{
+	struct tsem_model *model = tsem_model(current);
+
+	mutex_unlock(&model->trajectory_mutex);
+}
+
+static int trajectory_show(struct seq_file *c, void *trajectory)
+{
+	struct tsem_trajectory *pt;
+	struct tsem_event *ep;
+
+	pt = list_entry(trajectory, struct tsem_trajectory, list);
+	ep = pt->ep;
+
+	show_trajectory_event(c, ep);
+
+	return 0;
+}
+
+static const struct seq_operations trajectory_seqops = {
+	.start = trajectory_start,
+	.next = trajectory_next,
+	.stop = trajectory_stop,
+	.show = trajectory_show
+};
+
+static int trajectory_open(struct inode *inode, struct file *file)
+{
+	if (!can_access_fs())
+		return -EACCES;
+	return seq_open(file, &trajectory_seqops);
+}
+
+static const struct file_operations trajectory_ops = {
+	.open = trajectory_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+static void *point_start(struct seq_file *c, loff_t *pos)
+{
+	struct tsem_model *model = tsem_model(current);
+
+	mutex_lock(&model->point_mutex);
+	return seq_list_start(&model->point_list, *pos);
+}
+
+static void *point_next(struct seq_file *c, void *p, loff_t *pos)
+{
+	struct tsem_model *model = tsem_model(current);
+
+	return seq_list_next(p, &model->point_list, pos);
+}
+
+static void point_stop(struct seq_file *c, void *pos)
+{
+	struct tsem_model *model = tsem_model(current);
+
+	mutex_unlock(&model->point_mutex);
+}
+
+static int point_show(struct seq_file *c, void *point)
+{
+	struct tsem_event_point *id;
+
+	id = list_entry(point, struct tsem_event_point, list);
+	seq_printf(c, "%*phN\n", WP256_DIGEST_SIZE, id->point);
+	return 0;
+}
+
+static const struct seq_operations point_seqops = {
+	.start = point_start,
+	.next = point_next,
+	.stop = point_stop,
+	.show = point_show
+};
+
+static int point_open(struct inode *inode, struct file *file)
+{
+	if (!can_access_fs())
+		return -EACCES;
+	return seq_open(file, &point_seqops);
+}
+
+static const struct file_operations point_ops = {
+	.open = point_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+static int open_control(struct inode *inode, struct file *filp)
+{
+	if (!capable(TSEM_CONTROL_CAPABILITY))
+		return -EACCES;
+	if (!(filp->f_flags & O_WRONLY))
+		return -EACCES;
+	return 0;
+}
+
+static ssize_t write_control(struct file *file, const char __user *buf,
+			     size_t datalen, loff_t *ppos)
+{
+	char *p, *arg, cmdbufr[76];
+	unsigned int lp;
+	ssize_t retn = -EINVAL;
+	long pid;
+	enum tsem_control_type type;
+
+	if (*ppos != 0)
+		goto done;
+	if (datalen > sizeof(cmdbufr)-1)
+		goto done;
+
+	memset(cmdbufr, '\0', sizeof(cmdbufr));
+	if (copy_from_user(cmdbufr, buf, datalen)) {
+		retn = -EFAULT;
+		goto done;
+	}
+
+	p = strchr(cmdbufr, '\n');
+	if (!p)
+		goto done;
+	*p = '\0';
+
+	arg = strchr(cmdbufr, ' ');
+
+	for (lp = 0; lp < ARRAY_SIZE(commands); ++lp) {
+		if (!strncmp(cmdbufr, commands[lp].cmd,
+			     strlen(commands[lp].cmd))) {
+			type = commands[lp].type;
+			break;
+		}
+	}
+
+	switch (type) {
+	case TSEM_CONTROL_EXTERNAL:
+	case TSEM_CONTROL_INTERNAL:
+		retn = tsem_ns_create(type);
+		break;
+	case TSEM_CONTROL_ENFORCE:
+	case TSEM_CONTROL_SEAL:
+		retn = config_context(type, cmdbufr);
+		break;
+	case TSEM_CONTROL_TRUSTED:
+	case TSEM_CONTROL_UNTRUSTED:
+		p = strchr(cmdbufr, ' ');
+		if (!p)
+			goto done;
+		*p++ = '\0';
+		if (kstrtol(p, 0, &pid))
+			goto done;
+		retn = control_COE(pid, type);
+		break;
+	case TSEM_CONTROL_MAP_STATE:
+	case TSEM_CONTROL_MAP_PSEUDONYM:
+	case TSEM_CONTROL_MAP_BASE:
+		retn = config_point(type, arg);
+		break;
+	}
+
+done:
+	if (!retn)
+		retn = datalen;
+	return retn;
+}
+
+static int release_control(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static const struct file_operations control_ops = {
+	.open = open_control,
+	.write = write_control,
+	.release = release_control,
+	.llseek = generic_file_llseek,
+};
+
+static void *forensics_start(struct seq_file *c, loff_t *pos)
+{
+	struct tsem_model *model = tsem_model(current);
+
+	mutex_lock(&model->forensics_mutex);
+	return seq_list_start(&model->forensics_list, *pos);
+}
+
+static void *forensics_next(struct seq_file *c, void *p, loff_t *pos)
+{
+	struct tsem_model *model = tsem_model(current);
+
+	return seq_list_next(p, &model->forensics_list, pos);
+}
+
+static void forensics_stop(struct seq_file *c, void *pos)
+{
+	struct tsem_model *model = tsem_model(current);
+
+	mutex_unlock(&model->forensics_mutex);
+}
+
+static int forensics_show(struct seq_file *c, void *event)
+{
+	struct tsem_trajectory *pt;
+	struct tsem_event *ep;
+
+	pt = list_entry(event, struct tsem_trajectory, list);
+	ep = pt->ep;
+
+	show_trajectory_event(c, ep);
+
+	return 0;
+}
+
+static const struct seq_operations forensics_seqops = {
+	.start = forensics_start,
+	.next = forensics_next,
+	.stop = forensics_stop,
+	.show = forensics_show
+};
+
+static int forensics_open(struct inode *inode, struct file *file)
+{
+	if (!can_access_fs())
+		return -EACCES;
+	return seq_open(file, &forensics_seqops);
+}
+
+static const struct file_operations forensics_ops = {
+	.open = forensics_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+static int measurement_show(struct seq_file *c, void *event)
+{
+	struct tsem_model *model = tsem_model(current);
+
+	seq_printf(c, "%*phN\n", (int) sizeof(model->measurement),
+		   model->measurement);
+	return 0;
+}
+
+static int measurement_open(struct inode *inode, struct file *file)
+{
+	if (!can_access_fs())
+		return -EACCES;
+	return single_open(file, &measurement_show, NULL);
+}
+
+static const struct file_operations measurement_ops = {
+	.open = measurement_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+static int id_show(struct seq_file *c, void *event)
+{
+	seq_printf(c, "%llu\n", tsem_context(current)->id);
+	return 0;
+}
+
+static int id_open(struct inode *inode, struct file *file)
+{
+	struct tsem_TMA_context *ctx = tsem_context(current);
+
+	if (ctx->sealed)
+		return -EACCES;
+	return single_open(file, &id_show, NULL);
+}
+
+static const struct file_operations id_ops = {
+	.open = id_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+static int state_show(struct seq_file *m, void *v)
+{
+	struct tsem_model *model = tsem_model(current);
+
+	tsem_model_compute_state();
+	seq_printf(m, "%*phN\n", WP256_DIGEST_SIZE, model->state);
+	return 0;
+}
+
+static int state_open(struct inode *inode, struct file *file)
+{
+	if (!can_access_fs())
+		return -EACCES;
+	return single_open(file, &state_show, NULL);
+}
+
+static const struct file_operations state_ops = {
+	.open = state_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+static int aggregate_show(struct seq_file *m, void *v)
+{
+	seq_printf(m, "%*phN\n", WP256_DIGEST_SIZE, tsem_trust_aggregate());
+	return 0;
+}
+
+static int aggregate_open(struct inode *inode, struct file *file)
+{
+	if (!can_access_fs())
+		return -EACCES;
+	return single_open(file, &aggregate_show, NULL);
+}
+
+static const struct file_operations aggregate_ops = {
+	.open = aggregate_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+static int export_show(struct seq_file *m, void *v)
+{
+	return tsem_export_show(m);
+}
+
+static __poll_t export_poll(struct file *file, struct poll_table_struct *wait)
+{
+	struct tsem_TMA_context *ctx = tsem_context(current);
+
+	if (!ctx->external)
+		return -ENOENT;
+
+	poll_wait(file, &ctx->external->wq, wait);
+
+	if (ctx->external->have_event) {
+		ctx->external->have_event = false;
+		return EPOLLIN | EPOLLRDNORM;
+	}
+	return 0;
+}
+
+static int export_open(struct inode *inode, struct file *file)
+{
+	if (!capable(TSEM_CONTROL_CAPABILITY))
+		return -EACCES;
+	return single_open(file, &export_show, NULL);
+}
+
+static const struct file_operations export_ops = {
+	.open = export_open,
+	.poll = export_poll,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+static int fs_fill(struct super_block *sb, struct fs_context *fc)
+{
+	int retn;
+
+	static const struct tree_descr root_files[] = {
+		[2] = {"control", &control_ops, 0200},
+		[3] = {"id", &id_ops, 0400},
+		[4] = {"trajectory", &trajectory_ops, 0400},
+		[5] = {"forensics", &forensics_ops, 0400},
+		[6] = {"points", &point_ops, 0400},
+		[7] = {"measurement", &measurement_ops, 0400},
+		[8] = {"state", &state_ops, 0400},
+		[9] = {"aggregate", &aggregate_ops, 0400},
+		{""}
+	};
+
+	retn = simple_fill_super(sb, TSEMFS_MAGIC, root_files);
+	if (retn)
+		pr_warn("Unable to create TSEM root filesystem.\n");
+
+	return retn;
+}
+
+static int fs_init_context(struct fs_context *fc)
+{
+	fc->ops = &fs_operations;
+	return 0;
+}
+
+static int fs_get_tree(struct fs_context *fc)
+{
+	return get_tree_single(fc, fs_fill);
+}
+
+static int create_update_directory(void)
+{
+	int retn = 0;
+	struct dentry *root, *dentry;
+	struct inode *root_dir, *inode;
+	static const char *name = "ExternalTMA";
+
+	root = fs_mount->mnt_root;
+	root_dir = d_inode(root);
+
+	inode_lock(root_dir);
+	dentry = lookup_one_len(name, root, strlen(name));
+	if (IS_ERR(dentry)) {
+		retn = PTR_ERR(dentry);
+		goto done;
+	}
+
+	if (d_really_is_positive(dentry)) {
+		retn = -EEXIST;
+		goto done_dentry;
+	}
+
+	inode = new_inode(root_dir->i_sb);
+	if (!inode) {
+		retn = -ENOMEM;
+		goto done_dentry;
+	}
+
+	inode->i_ino = get_next_ino();
+	inode->i_mode = 0755 | S_IFDIR;
+	inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
+	inode->i_private = NULL;
+	inode->i_fop = &export_ops;
+	inode->i_op = &simple_dir_inode_operations;
+	inode->i_fop = &simple_dir_operations;
+	inc_nlink(inode);
+	inc_nlink(root_dir);
+
+	d_instantiate(dentry, inode);
+	dget(dentry);
+	external_dentry = dentry;
+	inode_unlock(root_dir);
+	return 0;
+
+ done_dentry:
+	dput(dentry);
+
+ done:
+	inode_unlock(root_dir);
+	return retn;
+}
+
+/**
+ * tesm_fs_init() - Initialize the TSEM control filesystem.
+ *
+ * This function is called as part of the TSEM LSM initialization
+ * process.  It creates the /sys/fs/tsem mount point and populates
+ * the filesystem to be mounted there with the control plane file and
+ * internal TMA model information files.
+ *
+ * Return: If filesystem initialization is successful a return code of 0
+ *	   is returned.  A negative return value is returned if an error
+ *	   is encoutnered.
+ */
+int __init tsem_fs_init(void)
+{
+	int retn;
+
+	retn = sysfs_create_mount_point(fs_kobj, "tsem");
+	if (retn) {
+		pr_warn("Unable to create TSEM filesystem mount point.\n");
+		return retn;
+	}
+
+	retn = register_filesystem(&fs_definition);
+	if (retn) {
+		pr_warn("Unable to register TSEM filesystem.\n");
+		goto done;
+	}
+
+	fs_mount = kern_mount(&fs_definition);
+	if (IS_ERR(fs_mount)) {
+		pr_warn("Unable to mount TSEM filesystem.\n");
+		retn = PTR_ERR(fs_mount);
+		fs_mount = NULL;
+	}
+
+	retn = create_update_directory();
+
+ done:
+	if (retn)
+		sysfs_remove_mount_point(fs_kobj, "tsem");
+	return retn;
+}
+
+/**
+ * tesm_fs_create_external() - Create an external TMA update file.
+ * @id: A pointer to the ASCII representation of the modeling domain
+ *      that the export file is being created for.
+ *
+ * This function is used to create a pseudo-file that will output security
+ * event descriptions for a namespace.  This routine will create the
+ * following file:
+ *
+ * /sys/fs/tsem/ExternalTMA/N
+ *
+ * Where N is replaced with the security model context identifier.
+ *
+ * Return: If creation of the update file is successful a pointer to the
+ *	   dentry of the file is returned.  If an error was encountered
+ *	   an error code is encoded in the pointer.
+ */
+struct dentry *tsem_fs_create_external(const char *name)
+{
+	int retn = 0;
+	struct dentry *dentry;
+	struct inode *root_dir, *inode;
+
+	retn = simple_pin_fs(&fs_definition, &fs_mount, &fs_mount_cnt);
+	if (retn)
+		return ERR_PTR(retn);
+
+	root_dir = d_inode(external_dentry);
+	inode_lock(root_dir);
+
+	dentry = lookup_one_len(name, external_dentry, strlen(name));
+	if (IS_ERR(dentry)) {
+		retn = PTR_ERR(dentry);
+		goto done;
+	}
+	if (d_really_is_positive(dentry)) {
+		WARN_ON_ONCE(1);
+		retn = -EEXIST;
+		goto done_dentry;
+	}
+
+	inode = new_inode(root_dir->i_sb);
+	if (!inode) {
+		retn = -ENOMEM;
+		goto done_dentry;
+	}
+
+	inode->i_ino = get_next_ino();
+	inode->i_mode = 0400 | S_IFREG;
+	inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
+	inode->i_private = NULL;
+	inode->i_fop = &export_ops;
+
+	d_instantiate(dentry, inode);
+	dget(dentry);
+	inode_unlock(root_dir);
+	return dentry;
+
+ done_dentry:
+	dput(dentry);
+
+ done:
+	inode_unlock(root_dir);
+	simple_release_fs(&fs_mount, &fs_mount_cnt);
+	if (retn)
+		dentry = ERR_PTR(retn);
+	return dentry;
+}
+
+/**
+ * tesm_fs_remove_external() - Remove an external modeling update file.
+ * @dentry: A pointer to the dentry of the file to be removed.
+ *
+ * This function is used to remove the update file for an externally
+ * modeled security domain.
+ */
+void tsem_fs_remove_external(struct dentry *dentry)
+{
+	struct inode *root_dir;
+
+	if (!dentry || IS_ERR(dentry)) {
+		WARN_ON_ONCE(1);
+		return;
+	}
+
+	root_dir = d_inode(dentry->d_parent);
+
+	inode_lock(root_dir);
+	if (simple_positive(dentry)) {
+		simple_unlink(root_dir, dentry);
+		dput(dentry);
+	}
+	inode_unlock(root_dir);
+
+	simple_release_fs(&fs_mount, &fs_mount_cnt);
+}
-- 
2.39.1


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 09/14] Add namespace implementation.
  2023-02-04  5:09 [PATCH 00/14] Implement Trusted Security Event Modeling Dr. Greg
                   ` (7 preceding siblings ...)
  2023-02-04  5:09 ` [PATCH 08/14] Implement TSEM control plane Dr. Greg
@ 2023-02-04  5:09 ` Dr. Greg
  2023-02-04  5:09 ` [PATCH 10/14] Add security event description export facility Dr. Greg
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 42+ messages in thread
From: Dr. Greg @ 2023-02-04  5:09 UTC (permalink / raw)
  To: linux-security-module

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

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

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

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

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

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

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

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

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

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


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 10/14] Add security event description export facility.
  2023-02-04  5:09 [PATCH 00/14] Implement Trusted Security Event Modeling Dr. Greg
                   ` (8 preceding siblings ...)
  2023-02-04  5:09 ` [PATCH 09/14] Add namespace implementation Dr. Greg
@ 2023-02-04  5:09 ` Dr. Greg
  2023-02-04  5:09 ` [PATCH 11/14] Add event description implementation Dr. Greg
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 42+ messages in thread
From: Dr. Greg @ 2023-02-04  5:09 UTC (permalink / raw)
  To: linux-security-module

The functionality for surfacing security model events to an
external modeling domain is implemented in the export.c file.

ASCII descriptions of the events are presented to a userspace
trust orchestrator through the following pseudo-files:

/sys/fs/tsem/ExternalTMA/N

Where N is replaced with security model domain identifier.

The following event types are exported:

AGGREGATE_EVENT

EXPORT_EVENT

LOG_EVENT

The AGGREGATE_EVENT is used to inject the hardware platform
aggregate that was computed over TPM Platform Configuration
Registers 0 through 7 at the time the LSM was initialized.  In
TSEM modeling this is the first security state point committed to
a model.

An EXPORT_EVENT is used to surface the description of either an
explicitly or generically modeled security state event for
injection into a security model run by an external orchestrator
and its associated Trusted Modeling Agent (TMA).

A LOG_EVENT is used to export descriptions of security events
that are invoked by untrusted processes.

The modeling and logging by external orchestrators allow the
implementation of out-of-band notifications of security forensics
events that occur.

The /sys/fs/tsem/ExternalTMA/N pseudo-files implement a pollable
interface that the trust orchestrators can use to wait on events.
After placing the event description into the device queue the
process is placed in an interruptible sleep state.

After the TMA completes modeling of the event, the trust
orchestrator is responsible for using the tsemfs control plane to
wake the process that exported the event and set its status to
either trusted or untrusted.

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

diff --git a/security/tsem/export.c b/security/tsem/export.c
new file mode 100644
index 000000000000..84c71fb96153
--- /dev/null
+++ b/security/tsem/export.c
@@ -0,0 +1,388 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * Copyright (C) 2022 Enjellic Systems Development, LLC
+ * Author: Dr. Greg Wettstein <greg@enjellic.com>
+ *
+ * Implements updates to an external modeling engine.
+ */
+
+#include <linux/seq_file.h>
+
+#include "tsem.h"
+
+enum export_events_type {
+	AGGREGATE_EVENT = 1,
+	EXPORT_EVENT,
+	LOG_EVENT
+};
+
+struct action_description {
+	enum tsem_event_type type;
+	enum tsem_action_type action;
+	char comm[TASK_COMM_LEN];
+};
+
+struct export_event {
+	struct list_head list;
+	enum export_events_type type;
+	union {
+		u8 *aggregate[WP256_DIGEST_SIZE];
+		struct tsem_event *ep;
+		struct action_description action;
+	} u;
+};
+
+static const char * const tsem_actions[TSEM_ACTION_CNT] = {
+	"LOG",
+	"DENY"
+};
+
+static void trigger_event(struct tsem_TMA_context *ctx)
+{
+	ctx->external->have_event = true;
+	wake_up_interruptible(&ctx->external->wq);
+}
+
+static void show_event_coe(struct tsem_event *ep, struct seq_file *page)
+{
+	seq_printf(page, "export pid{%u} ", ep->pid);
+
+	seq_printf(page, "event{process=%s, filename=%s, ", ep->comm,
+			   ep->pathname == NULL ? "none" : ep->pathname);
+	seq_printf(page, "type=%s, task_id=%*phN} ", tsem_names[ep->event],
+		   WP256_DIGEST_SIZE, ep->task_id);
+
+	seq_printf(page, "COE{uid=%d, euid=%d, suid=%d, gid=%d, ", ep->COE.uid,
+		   ep->COE.euid, ep->COE.suid, ep->COE.gid);
+	seq_printf(page, "egid=%d, sgid=%d, fsuid=%d, fsgid=%d, ",
+		   ep->COE.egid, ep->COE.sgid, ep->COE.fsuid, ep->COE.fsgid);
+	seq_printf(page, "cap=0x%llx} ", ep->COE.capability.value);
+}
+
+static void show_file(struct tsem_event *ep, struct seq_file *page)
+{
+	seq_printf(page, "file{flags=%u, uid=%d, gid=%d, mode=0%o, ",
+		ep->file.flags, ep->file.uid, ep->file.gid, ep->file.mode);
+	seq_printf(page, "name_length=%u, name=%*phN, s_magic=0x%0x, ",
+		   ep->file.name_length, WP256_DIGEST_SIZE, ep->file.name,
+		   ep->file.s_magic);
+	seq_printf(page, "s_id=%s, s_uuid=%*phN, digest=%*phN}\n",
+		   ep->file.s_id, (int) sizeof(ep->file.s_uuid),
+		   ep->file.s_uuid, WP256_DIGEST_SIZE, ep->file.digest);
+}
+
+static void show_mmap_file(struct tsem_event *ep, struct seq_file *page)
+{
+	show_event_coe(ep, page);
+
+	seq_printf(page, "%s{type=%u, reqprot=%u, ", tsem_names[ep->event],
+		   ep->CELL.mmap_file.anonymous, ep->CELL.mmap_file.reqprot);
+	seq_printf(page, "prot=%u, flags=%u}", ep->CELL.mmap_file.prot,
+		   ep->CELL.mmap_file.flags);
+
+	if (!ep->CELL.mmap_file.anonymous) {
+		seq_puts(page, " ");
+		show_file(ep, page);
+	} else
+		seq_puts(page, "\n");
+}
+
+static void show_ipv4_socket(struct tsem_event *ep, struct seq_file *page)
+{
+	struct sockaddr_in *ipv4 = &ep->CELL.socket_connect.u.ipv4;
+
+	show_event_coe(ep, page);
+	seq_printf(page, "%s{family=%u, port=%u, addr=%u}\n",
+		   tsem_names[ep->event], ipv4->sin_family, ipv4->sin_port,
+		   ipv4->sin_addr.s_addr);
+}
+
+static void show_ipv6_socket(struct tsem_event *ep, struct seq_file *page)
+{
+	struct sockaddr_in6 *ipv6 = &ep->CELL.socket_connect.u.ipv6;
+
+	show_event_coe(ep, page);
+
+	seq_printf(page, "%s{family=%u, port=%u, flow=%u, ",
+		   tsem_names[ep->event], ipv6->sin6_family,
+		   ipv6->sin6_port, ipv6->sin6_flowinfo);
+	seq_printf(page, "scope=%u, addr=%*phN}\n", ipv6->sin6_scope_id,
+		       (int) sizeof(ipv6->sin6_addr.in6_u.u6_addr8),
+		       ipv6->sin6_addr.in6_u.u6_addr8);
+}
+
+static void show_socket(struct tsem_event *ep, struct seq_file *page)
+{
+	struct tsem_socket_connect_args *scp = &ep->CELL.socket_connect;
+
+	show_event_coe(ep, page);
+
+	seq_printf(page, "%s{family=%u, addr=%*phN}\n", tsem_names[ep->event],
+		   scp->family, WP256_DIGEST_SIZE, scp->u.mapping);
+}
+
+static void show_socket_create(struct tsem_event *ep, struct seq_file *page)
+{
+	show_event_coe(ep, page);
+
+	seq_printf(page, "%s{family=%u, type=%u, ", tsem_names[ep->event],
+		   ep->CELL.socket_create.family, ep->CELL.socket_create.type);
+	seq_printf(page, "protocol=%u, kern=%u}\n",
+		   ep->CELL.socket_create.protocol,
+		   ep->CELL.socket_create.kern);
+}
+
+static void show_socket_accept(struct tsem_event *ep, struct seq_file *page)
+{
+	u8 *p;
+	int size;
+	struct tsem_socket_accept_args *sap = &ep->CELL.socket_accept;
+
+	show_event_coe(ep, page);
+
+	seq_printf(page, "%s{family=%u, type=%u, port=%u, addr=",
+		   tsem_names[ep->event], sap->family, sap->type, sap->port);
+
+	if (sap->family == AF_INET) {
+		seq_printf(page, "%u}\n", sap->ipv4);
+		return;
+	}
+
+	if (sap->family == AF_INET6) {
+		p = sap->ipv6.in6_u.u6_addr8;
+		size = sizeof(sap->ipv6.in6_u.u6_addr8);
+	} else {
+		p = sap->tsip->digest;
+		size = sizeof(sap->tsip->digest);
+	}
+	seq_printf(page, "%*phN}\n", size, p);
+}
+
+static void show_socket_events(struct tsem_event *ep, struct seq_file *page)
+{
+	switch (ep->event) {
+	case TSEM_SOCKET_CREATE:
+		show_socket_create(ep, page);
+		break;
+
+	case TSEM_SOCKET_CONNECT:
+	case TSEM_SOCKET_BIND:
+		switch (ep->CELL.socket_connect.family) {
+		case AF_INET:
+			show_ipv4_socket(ep, page);
+			break;
+		case AF_INET6:
+			show_ipv6_socket(ep, page);
+			break;
+		default:
+			show_socket(ep, page);
+			break;
+		}
+		break;
+
+	case TSEM_SOCKET_ACCEPT:
+		show_socket_accept(ep, page);
+		break;
+
+	default:
+		break;
+	}
+}
+
+static void show_task_kill(struct tsem_event *ep, struct seq_file *page)
+{
+	struct tsem_task_kill_args *args = &ep->CELL.task_kill;
+
+	show_event_coe(ep, page);
+
+	seq_printf(page, "%s{cross=%u, signal=%u, target=%*phN}\n",
+		   tsem_names[ep->event], args->cross_model,
+		   args->signal, WP256_DIGEST_SIZE, args->target);
+}
+
+static void show_event_generic(struct tsem_event *ep, struct seq_file *page)
+{
+	show_event_coe(ep, page);
+
+	seq_printf(page, "%s{type=%s}\n", tsem_names[ep->event],
+		   tsem_names[ep->CELL.event_type]);
+}
+
+int tsem_export_show(struct seq_file *page)
+{
+	ssize_t retn = -ENODATA;
+	struct export_event *mp;
+	struct tsem_event *ep;
+	struct tsem_TMA_context *ctx = tsem_context(current);
+
+	if (!ctx->id)
+		return -EPERM;
+
+	mutex_lock(&ctx->external->measurement_mutex);
+	if (list_empty(&ctx->external->measurement_list))
+		goto done;
+	mp = list_first_entry(&ctx->external->measurement_list,
+			      struct export_event, list);
+
+	switch (mp->type) {
+	case AGGREGATE_EVENT:
+		seq_printf(page, "aggregate %*phN\n", WP256_DIGEST_SIZE,
+			   mp->u.aggregate);
+		break;
+
+	case EXPORT_EVENT:
+		ep = mp->u.ep;
+		switch (ep->event) {
+		case TSEM_FILE_OPEN:
+			show_event_coe(ep, page);
+			show_file(ep, page);
+			break;
+
+		case TSEM_MMAP_FILE:
+			show_mmap_file(ep, page);
+			break;
+
+		case TSEM_SOCKET_CREATE:
+		case TSEM_SOCKET_CONNECT:
+		case TSEM_SOCKET_BIND:
+		case TSEM_SOCKET_ACCEPT:
+			show_socket_events(ep, page);
+			break;
+
+		case TSEM_TASK_KILL:
+			show_task_kill(ep, page);
+			break;
+
+		case TSEM_GENERIC_EVENT:
+			show_event_generic(ep, page);
+			break;
+
+		default:
+			break;
+		}
+		tsem_event_put(ep);
+		break;
+
+	case LOG_EVENT:
+		seq_printf(page, "log process{%s} event{%s} action{%s}\n",
+			    mp->u.action.comm, tsem_names[mp->u.action.type],
+			    tsem_actions[mp->u.action.action]);
+		break;
+	}
+
+	list_del(&mp->list);
+	kfree(mp);
+	retn = 0;
+
+ done:
+	mutex_unlock(&ctx->external->measurement_mutex);
+	return retn;
+}
+
+int tsem_export_event(struct tsem_event *ep)
+{
+	int retn = 0;
+	struct tsem_task *task = tsem_task(current);
+	struct tsem_TMA_context *ctx = task->context;
+	struct export_event *mp;
+
+	if (!ctx->external)
+		return 0;
+
+	mp = kzalloc(sizeof(struct export_event), GFP_KERNEL);
+	if (!mp) {
+		retn = -ENOMEM;
+		goto done;
+	}
+	mp->type = EXPORT_EVENT;
+	mp->u.ep = ep;
+	tsem_event_get(ep);
+
+	mutex_lock(&ctx->external->measurement_mutex);
+	list_add_tail(&mp->list, &ctx->external->measurement_list);
+	mutex_unlock(&ctx->external->measurement_mutex);
+
+	task->trust_status |= TSEM_TASK_TRUST_PENDING;
+	trigger_event(ctx);
+
+	while (task->trust_status & TSEM_TASK_TRUST_PENDING) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule();
+		if (signal_pending(current)) {
+			if (sigismember(&current->pending.signal, SIGKILL) ||
+			    sigismember(&current->signal->shared_pending.signal,
+					SIGKILL))
+				task->trust_status = TSEM_TASK_UNTRUSTED;
+		}
+	}
+
+ done:
+	return retn;
+}
+
+/**
+ * tsem_export_action() - Exports the action taken to a security violation.
+ * @event: The TSEM event type number for which the log event is being
+ *	   generated.
+ *
+ * This function queues for export a description of an event that
+ * was being disciplined.
+ *
+ * Return: This function returns 0 if the export was successful or
+ *	   an error value if it was not.
+ */
+int tsem_export_action(enum tsem_event_type event)
+{
+	struct tsem_TMA_context *ctx = tsem_context(current);
+	struct export_event *exp;
+
+	exp = kzalloc(sizeof(struct export_event), GFP_KERNEL);
+	if (!exp)
+		return -ENOMEM;
+
+	exp->type = LOG_EVENT;
+	exp->u.action.type = event;
+	exp->u.action.action = ctx->actions[event];
+	strcpy(exp->u.action.comm, current->comm);
+
+	mutex_lock(&ctx->external->measurement_mutex);
+	list_add_tail(&exp->list, &ctx->external->measurement_list);
+	mutex_unlock(&ctx->external->measurement_mutex);
+
+	trigger_event(ctx);
+
+	return 0;
+}
+
+/**
+ * tsem_export_aggregate() - Exports the hardware aggregate value.
+ *
+ * This function exports the hardware aggregate measurement for
+ * the platform on which the TSEM LSM is being run on.
+ *
+ * Return: This function returns a value of 0 if the export was
+ *	   successful or a non-zero return value if the export was
+ *	   not successful.
+ */
+int tsem_export_aggregate(void)
+{
+	struct tsem_TMA_context *ctx = tsem_context(current);
+	struct export_event *exp;
+
+	exp = kzalloc(sizeof(struct export_event), GFP_KERNEL);
+	if (!exp)
+		return -ENOMEM;
+
+	exp->type = AGGREGATE_EVENT;
+	memcpy(exp->u.aggregate, tsem_trust_aggregate(),
+	       sizeof(exp->u.aggregate));
+
+	mutex_lock(&ctx->external->measurement_mutex);
+	list_add_tail(&exp->list, &ctx->external->measurement_list);
+	mutex_unlock(&ctx->external->measurement_mutex);
+
+	trigger_event(ctx);
+
+	return 0;
+}
-- 
2.39.1


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 11/14] Add event description implementation.
  2023-02-04  5:09 [PATCH 00/14] Implement Trusted Security Event Modeling Dr. Greg
                   ` (9 preceding siblings ...)
  2023-02-04  5:09 ` [PATCH 10/14] Add security event description export facility Dr. Greg
@ 2023-02-04  5:09 ` Dr. Greg
  2023-02-04  5:09 ` [PATCH 12/14] Implement security event mapping Dr. Greg
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 42+ messages in thread
From: Dr. Greg @ 2023-02-04  5:09 UTC (permalink / raw)
  To: linux-security-module

The event.c file implements support for packaging the description
of an event into its Context Of Execution (COE) and CELL
components for subsequent modeling by an internal Trusted
Modeling Agent or export to a trust orchestrator.

The tsem_event_allocate() function is called by every security
event handler that determines that an event is to be modeled,
either generically or explicitly.  For externally modeled domains
the event description is released after the export of the event
is completed.

For internally modeled domains the event description is retained
in order to support retention and surfacing of the security event
descriptions until the domain is terminated.

The event description structures are allocated from a TSEM
event description cache named 'tsem_event_cache'.  This cache is
created by an initialization function exported from this file
that is called as part of the TSEM LSM initialization process.o

In the case of a security event that acts on a file, ie. is
called with a 'struct file' pointer, one of the components of the
CELL value is a digest of the contents of the file.  This file
uses the integrity_kernel_read() function supplied by the
integrity infrastructure to compute the file digest value using
the SHA256 cryptographic hashing function.

In a manner similar to the Integrity Measurement Architecture the
file digest processing functionality needs to temporarily alter
the file mode characteristics if the file is not readable.  The
characteristics are returned to their normal file after reading
of the digest is complete.

The TSEM LSM allocates uses the LSM 'blob' infrastructure to
allocate a TSEM specific inode structure when an inode is
allocated.  The digest value for the value is stored in this
structure in order to eliminate subsequent re-computation of the
digest value if the file has not changed.

The inode 'iversion' value is used to detect changes to an inode
in order to trigger the re-computation of the digest value if the
file has changed.

One of the subtle issues that needs to be addressed is to handle
re-entrancy of the file_open security event hook that is caused
by the integrity_kernel_read() function opening the file.  The
TSEM specific inode structure contains a member that is used to
indicate whether or not a digest is being computed for a file.
The tsem_file_open() event handler checks for the presence of
this flag and allows permission for the open if this flag is
detected.

For IPV6 and IPV6 sockets relevant socket information is
collected to be used in the CELL computation.

For a UNIX domain socket (AF_UNIX) the digest of the pathname for
the socket is used for the CELL value.

Other socket types are generically modeled by computing the
digest of the address field supplied when the socket was created
or bound.

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

diff --git a/security/tsem/event.c b/security/tsem/event.c
new file mode 100644
index 000000000000..a6162caf2d81
--- /dev/null
+++ b/security/tsem/event.c
@@ -0,0 +1,474 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * Copyright (C) 2022 Enjellic Systems Development, LLC
+ * Author: Dr. Greg Wettstein <greg@enjellic.com>
+ *
+ * This file manages the data structures used to define a security event.
+ */
+
+#define ZERO_FILE "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+
+#include <linux/iversion.h>
+#include <crypto/hash.h>
+
+#include "tsem.h"
+#include "../integrity/integrity.h"
+
+static struct kmem_cache *event_cachep;
+
+static void get_COE(struct tsem_COE *COE)
+
+{
+	kernel_cap_t eff, per, inh;
+
+	COE->uid = from_kuid(&init_user_ns, current_uid());
+	COE->euid = from_kuid(&init_user_ns, current_euid());
+	COE->suid = from_kuid(&init_user_ns, current_suid());
+
+	COE->gid = from_kgid(&init_user_ns, current_gid());
+	COE->egid = from_kgid(&init_user_ns, current_egid());
+	COE->sgid = from_kgid(&init_user_ns, current_sgid());
+
+	COE->fsuid = from_kuid(&init_user_ns, current_fsuid());
+	COE->fsgid = from_kgid(&init_user_ns, current_fsgid());
+
+	if (security_capget(current, &eff, &inh, &per) != 0)
+		eff = CAP_FULL_SET;
+	COE->capability.mask = eff;
+}
+
+static char *get_path(struct file *file)
+{
+	int retn = 0;
+	const char *pathname = NULL;
+	char *path, *pathbuffer = NULL;
+
+	pathbuffer = __getname();
+	if (pathbuffer) {
+		pathname = d_absolute_path(&file->f_path, pathbuffer,
+					   PATH_MAX);
+		if (IS_ERR(pathname)) {
+			__putname(pathbuffer);
+			pathbuffer = NULL;
+			pathname = NULL;
+		}
+	}
+
+	if (pathname)
+		path = kstrdup(pathname, GFP_KERNEL);
+	else
+		path = kstrdup(file->f_path.dentry->d_name.name, GFP_KERNEL);
+	if (!path)
+		retn = -ENOMEM;
+
+	if (pathbuffer)
+		__putname(pathbuffer);
+	if (retn)
+		path = ERR_PTR(retn);
+	return path;
+}
+
+static int add_file_name(struct crypto_shash *tfm, struct tsem_event *ep)
+{
+	int retn;
+	SHASH_DESC_ON_STACK(shash, tfm);
+
+	shash->tfm = tfm;
+	retn = crypto_shash_init(shash);
+	if (retn)
+		goto done;
+
+	ep->file.name_length = strlen(ep->pathname);
+	retn = crypto_shash_finup(shash, ep->pathname, ep->file.name_length,
+				  ep->file.name);
+
+ done:
+	return retn;
+}
+
+static struct file *open_event_file(struct file *file, unsigned int *status)
+{
+	int flags;
+	struct file *alt_file;
+
+	if (!(file->f_mode & FMODE_CAN_READ)) {
+		file->f_mode |= FMODE_CAN_READ;
+		*status |= 4;
+	}
+	if (file->f_mode & FMODE_READ)
+		return file;
+
+	flags = file->f_flags & ~(O_WRONLY | O_APPEND | O_TRUNC | O_CREAT |
+				  O_NOCTTY | O_EXCL);
+	flags |= O_RDONLY;
+
+	alt_file = dentry_open(&file->f_path, flags, file->f_cred);
+	if (!IS_ERR(alt_file)) {
+		*status |= 1;
+		return alt_file;
+	}
+
+	file->f_flags |= FMODE_READ;
+	*status |= 2;
+	return file;
+}
+
+static int get_file_digest(struct crypto_shash *tfm, struct file *file,
+			   struct inode *inode, loff_t size, u8 *digest)
+{
+	u8 *bufr;
+	int retn = 0, rsize;
+	unsigned int open_status = 0;
+	loff_t posn = 0;
+	struct file *read_file;
+	SHASH_DESC_ON_STACK(shash, tfm);
+
+	shash->tfm = tfm;
+	retn = crypto_shash_init(shash);
+	if (retn)
+		goto done;
+
+	bufr = kzalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!bufr) {
+		retn = -ENOMEM;
+		goto done;
+	}
+
+	if (!likely(file->f_op->read || file->f_op->read_iter)) {
+		retn = -EINVAL;
+		goto done;
+	}
+	read_file = open_event_file(file, &open_status);
+
+	while (posn < size) {
+		rsize = integrity_kernel_read(read_file, posn, bufr, 4096);
+		if (rsize < 0) {
+			retn = rsize;
+			break;
+		}
+		if (rsize == 0)
+			break;
+
+		posn += rsize;
+		retn = crypto_shash_update(shash, bufr, rsize);
+		if (retn)
+			break;
+	}
+
+	kfree(bufr);
+	if (!retn)
+		retn = crypto_shash_final(shash, digest);
+
+ done:
+	if (open_status & 1)
+		fput(read_file);
+	if (open_status & 2)
+		file->f_flags &= ~FMODE_READ;
+	if (open_status & 4)
+		file->f_flags &= ~FMODE_CAN_READ;
+	return retn;
+}
+
+int add_file_digest(struct file *file, struct tsem_file *tfp)
+{
+	int retn = 0;
+	loff_t size;
+	struct inode *inode = NULL;
+	struct tsem_inode *tsip;
+	u8 measurement[WP256_DIGEST_SIZE];
+	struct tsem_TMA_context *ctx = tsem_context(current);
+	struct crypto_shash *tfm;
+
+	memset(measurement, '\0', sizeof(measurement));
+	inode = file_inode(file);
+	tsip = tsem_inode(inode);
+
+	mutex_lock(&tsip->mutex);
+	if (!ctx->external) {
+		retn = tsem_model_has_pseudonym(tsip, tfp, measurement);
+		if (retn < 0)
+			goto done;
+		if (retn) {
+			memcpy(tfp->digest, measurement, sizeof(tfp->digest));
+			retn = 0;
+			goto done;
+		}
+	}
+
+	size = i_size_read(inode);
+	if (!size) {
+		if (!hex2bin(measurement, ZERO_FILE, sizeof(measurement)))
+			memcpy(tfp->digest, measurement, sizeof(tfp->digest));
+		else
+			memset(tfp->digest, '\0', sizeof(tfp->digest));
+		goto done;
+	}
+
+	if (inode_eq_iversion(inode, tsip->version) &&
+	    tsip->status == TSEM_INODE_COLLECTED) {
+		memcpy(tfp->digest, tsip->digest, sizeof(tfp->digest));
+		goto done;
+	}
+
+	tfm = crypto_alloc_shash("sha256", 0, 0);
+	if (IS_ERR(tfm)) {
+		retn = PTR_ERR(tfm);
+		goto done;
+	}
+
+	tsip->status = TSEM_INODE_COLLECTING;
+	retn = get_file_digest(tfm, file, inode, size, measurement);
+	if (retn)
+		tsip->status = 0;
+	else {
+		memcpy(tfp->digest, measurement, sizeof(tfp->digest));
+		memcpy(tsip->digest, measurement, sizeof(tsip->digest));
+		tsip->status = TSEM_INODE_COLLECTED;
+		tsip->version = inode_query_iversion(inode);
+	}
+
+ done:
+	mutex_unlock(&tsip->mutex);
+	return retn;
+}
+
+static int get_file_cell(struct file *file, struct tsem_event *ep)
+{
+	int retn = 1;
+	struct crypto_shash *tfm;
+	struct inode *inode;
+
+	inode = file_inode(file);
+	inode_lock(inode);
+
+	ep->pathname = get_path(file);
+	if (IS_ERR(ep->pathname)) {
+		retn = PTR_ERR(ep->pathname);
+		goto done;
+	}
+
+	tfm = crypto_alloc_shash("sha256", 0, 0);
+	if (IS_ERR(tfm)) {
+		retn = PTR_ERR(tfm);
+		goto done;
+	}
+
+	retn = add_file_name(tfm, ep);
+	if (retn)
+		goto done;
+
+	retn = add_file_digest(file, &ep->file);
+	if (retn)
+		goto done;
+
+	ep->file.flags = file->f_flags;
+
+	ep->file.uid = from_kuid(&init_user_ns, inode->i_uid);
+	ep->file.gid = from_kgid(&init_user_ns, inode->i_gid);
+	ep->file.mode = inode->i_mode;
+	ep->file.s_magic = inode->i_sb->s_magic;
+	memcpy(ep->file.s_id, inode->i_sb->s_id, sizeof(ep->file.s_id));
+	memcpy(ep->file.s_uuid, inode->i_sb->s_uuid.b,
+	       sizeof(ep->file.s_uuid));
+
+ done:
+	inode_unlock(inode);
+	crypto_free_shash(tfm);
+	return retn;
+}
+
+static int get_socket_mapping(struct crypto_shash *tfm,
+			      struct tsem_socket_connect_args *scp)
+{
+	int retn, size;
+	u8 *p;
+	SHASH_DESC_ON_STACK(shash, tfm);
+
+	shash->tfm = tfm;
+	retn = crypto_shash_init(shash);
+	if (retn)
+		goto done;
+
+	switch (scp->family) {
+	case AF_UNIX:
+		p = (u8 *) scp->addr->sa_data;
+		size = strlen(p);
+		retn = crypto_shash_finup(shash, p, size, scp->u.mapping);
+		break;
+	default:
+		p = (u8 *) scp->addr->sa_data;
+		size = sizeof(scp->addr) - offsetof(struct sockaddr, sa_data);
+		retn = crypto_shash_finup(shash, p, size, scp->u.mapping);
+		break;
+	}
+	memcpy(scp->tsip->digest, scp->u.mapping, sizeof(scp->tsip->digest));
+
+ done:
+	return retn;
+}
+
+static int get_socket_cell(struct tsem_event *ep)
+
+{
+	int retn = 0;
+	struct crypto_shash *tfm = NULL;
+	struct tsem_socket_connect_args *scp = &ep->CELL.socket_connect;
+
+	scp->family = scp->addr->sa_family;
+
+	switch (scp->family) {
+	case AF_INET:
+		memcpy(&scp->u.ipv4, scp->addr, sizeof(scp->u.ipv4));
+		break;
+	case AF_INET6:
+		memcpy(&scp->u.ipv6, scp->addr, sizeof(scp->u.ipv6));
+		break;
+	default:
+		tfm = crypto_alloc_shash("sha256", 0, 0);
+		if (IS_ERR(tfm)) {
+			retn = PTR_ERR(tfm);
+			tfm = NULL;
+			goto done;
+		}
+		retn = get_socket_mapping(tfm, scp);
+		break;
+	}
+
+ done:
+	crypto_free_shash(tfm);
+	return retn;
+}
+
+/**
+ * tsem_event_allocate() - Allocate a security event description structure.
+ * @event: The security event number for which the structure is being
+ *	   allocated.
+ * @params: A pointer to the aggregation structure used to hold the
+ *	    parameters that describe the function.
+ *
+ * This function is responsible for allocating the primary tsem_event
+ * structure and populating it based on the event type.
+ *
+ * Return: This function returns a pointer to the allocated structure which
+ *	   on failure will have an error return code embedded in it.
+ */
+struct tsem_event *tsem_event_allocate(enum tsem_event_type event,
+				       struct tsem_event_parameters *params)
+{
+	int retn = 0;
+	struct tsem_event *ep;
+	struct tsem_task *task = tsem_task(current);
+
+	ep = kmem_cache_zalloc(event_cachep, GFP_KERNEL);
+	if (!ep) {
+		retn = -ENOMEM;
+		goto done;
+	}
+
+	ep->event = event;
+	ep->pid = task_pid_nr(current);
+	memcpy(ep->comm, current->comm, sizeof(ep->comm));
+	memcpy(ep->task_id, task->task_id, sizeof(ep->task_id));
+
+	get_COE(&ep->COE);
+	switch (event) {
+	case TSEM_FILE_OPEN:
+	case TSEM_BPRM_SET_CREDS:
+		retn = get_file_cell(params->u.file, ep);
+		break;
+	case TSEM_MMAP_FILE:
+		ep->CELL.mmap_file = *params->u.mmap_file;
+		if (!ep->CELL.mmap_file.anonymous)
+			retn = get_file_cell(ep->CELL.mmap_file.file, ep);
+		break;
+	case TSEM_SOCKET_CREATE:
+		ep->CELL.socket_create = *params->u.socket_create;
+		break;
+	case TSEM_SOCKET_CONNECT:
+	case TSEM_SOCKET_BIND:
+		ep->CELL.socket_connect = *params->u.socket_connect;
+		retn = get_socket_cell(ep);
+		break;
+	case TSEM_SOCKET_ACCEPT:
+		ep->CELL.socket_accept = *params->u.socket_accept;
+		break;
+	case TSEM_TASK_KILL:
+		ep->CELL.task_kill = *params->u.task_kill;
+		break;
+	case TSEM_GENERIC_EVENT:
+		ep->CELL.event_type = params->u.event_type;
+		break;
+	default:
+		WARN_ONCE(true, "Unhandled event type: %d\n", event);
+		break;
+	}
+
+ done:
+	if (retn) {
+		kfree(ep);
+		ep = ERR_PTR(retn);
+	} else
+		kref_init(&ep->kref);
+
+	return ep;
+}
+
+/**
+ * tsem_free_event() - Free a security event description.
+ * @ep: A pointer to the security event description that is to be freed.
+ *
+ * This function is responsible for freeing the resources that were
+ * allocated by the tsem_event_allocate_COE_cell() function.
+ */
+static void tsem_event_free(struct kref *kref)
+{
+	struct tsem_event *ep;
+
+	ep = container_of(kref, struct tsem_event, kref);
+	if (ep)
+		kfree(ep->pathname);
+	kmem_cache_free(event_cachep, ep);
+}
+
+/**
+ * tsem_event_put() - Release a referenceto a TSEM event description.
+ *
+ * This function is called each time the use of a TSEM event description
+ * is dropped.
+ */
+void tsem_event_put(struct tsem_event *ep)
+{
+	kref_put(&ep->kref, tsem_event_free);
+}
+
+/**
+ * tsem_event_get() - Obtain a reference to a TSEM event description.
+ *
+ * This function is called on each invocation of the tsem_task_free
+ * function to release one of the references on the TMA modeling
+ * structure.
+ */
+void tsem_event_get(struct tsem_event *ep)
+{
+	kref_get(&ep->kref);
+}
+
+/**
+ * tsem event_cache_init() - Initialize the TSEM event cache.
+ *
+ * This function is called by the TSEM initialization function and sets
+ * up the cache that will hold tsem_event structures.
+ *
+ * Return: This function returns a value of zero on success and a negative
+ *	   error code on failure.
+ */
+int __init tsem_event_cache_init(void)
+{
+	event_cachep = kmem_cache_create("tsem_event_cache",
+					 sizeof(struct tsem_event), 0,
+					 SLAB_PANIC, 0);
+	if (!event_cachep)
+		return -ENOMEM;
+	return 0;
+}
-- 
2.39.1


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 12/14] Implement security event mapping.
  2023-02-04  5:09 [PATCH 00/14] Implement Trusted Security Event Modeling Dr. Greg
                   ` (10 preceding siblings ...)
  2023-02-04  5:09 ` [PATCH 11/14] Add event description implementation Dr. Greg
@ 2023-02-04  5:09 ` Dr. Greg
  2023-02-04  5:09 ` [PATCH 13/14] Implement an internal Trusted Modeling Agent Dr. Greg
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 42+ messages in thread
From: Dr. Greg @ 2023-02-04  5:09 UTC (permalink / raw)
  To: linux-security-module

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

Documentation/admin-guide/LSM/tsem.rst

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

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

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

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

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

The TASK_ID mapping function uses the same functional expression
as the security state point mapping but substitutes a TASK_ID
that consists of 32 null bytes.

Since a generically modeled event does not have a format CELL
definition this file contains a default CELL digest value that is
used in the generation for a security state point for these
events.  A generic value is currently supplied with a roadmap
that would allow trust orchestrators to set this value in order
to avoid a kernel ABI dependency on this value.

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

diff --git a/security/tsem/map.c b/security/tsem/map.c
new file mode 100644
index 000000000000..04108dd36c1e
--- /dev/null
+++ b/security/tsem/map.c
@@ -0,0 +1,497 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * Copyright (C) 2022 Enjellic Systems Development, LLC
+ * Author: Dr. Greg Wettstein <greg@enjellic.com>
+ *
+ * This file implements mapping of events into security event points.
+ */
+
+#include <crypto/hash.h>
+
+#include "tsem.h"
+
+const u8 generic_cell[WP256_DIGEST_SIZE] = {
+	0x61, 0x87, 0x8a, 0xe5, 0x8a, 0x7c, 0x22, 0xb4,
+	0xea, 0xb9, 0x32, 0xed, 0x3f, 0xdf, 0x34, 0x54,
+	0x39, 0x9b, 0xeb, 0x48, 0xd7, 0x44, 0xa7, 0x0e,
+	0xab, 0x80, 0xc1, 0xd1, 0x99, 0xd8, 0x69, 0xc8
+};
+
+static int get_COE_mapping(struct crypto_shash *tfm, struct tsem_event *ep,
+			   u8 *mapping)
+{
+	int retn = 0, size;
+	u8 *p;
+	SHASH_DESC_ON_STACK(shash, tfm);
+
+	shash->tfm = tfm;
+	retn = crypto_shash_init(shash);
+	if (retn)
+		goto done;
+
+	p = (u8 *) &ep->COE.uid;
+	size = sizeof(ep->COE.uid);
+	retn = crypto_shash_update(shash, p, size);
+	if (retn)
+		goto done;
+
+	p = (u8 *) &ep->COE.euid;
+	size = sizeof(ep->COE.euid);
+	retn = crypto_shash_update(shash, p, size);
+	if (retn)
+		goto done;
+
+	p = (u8 *) &ep->COE.suid;
+	size = sizeof(ep->COE.suid);
+	retn = crypto_shash_update(shash, p, size);
+	if (retn)
+		goto done;
+
+	p = (u8 *) &ep->COE.gid;
+	size = sizeof(ep->COE.gid);
+	retn = crypto_shash_update(shash, p, size);
+	if (retn)
+		goto done;
+
+	p = (u8 *) &ep->COE.egid;
+	size = sizeof(ep->COE.egid);
+	retn = crypto_shash_update(shash, p, size);
+	if (retn)
+		goto done;
+
+	p = (u8 *) &ep->COE.sgid;
+	size = sizeof(ep->COE.sgid);
+	retn = crypto_shash_update(shash, p, size);
+	if (retn)
+		goto done;
+
+	p = (u8 *) &ep->COE.fsuid;
+	size = sizeof(ep->COE.fsuid);
+	retn = crypto_shash_update(shash, p, size);
+	if (retn)
+		goto done;
+
+	p = (u8 *) &ep->COE.fsgid;
+	size = sizeof(ep->COE.fsgid);
+	retn = crypto_shash_update(shash, p, size);
+	if (retn)
+		goto done;
+
+	p = (u8 *) &ep->COE.capability;
+	size = sizeof(ep->COE.capability);
+	retn = crypto_shash_finup(shash, p, size, mapping);
+
+ done:
+	return retn;
+}
+
+static int get_cell_mapping(struct crypto_shash *tfm, struct tsem_event *ep,
+			    u8 *mapping)
+{
+	int retn = 0, size;
+	u8 *p;
+	struct sockaddr_in *ipv4;
+	struct sockaddr_in6 *ipv6;
+	struct tsem_mmap_file_args *mm_args = &ep->CELL.mmap_file;
+	struct tsem_socket_connect_args *scp = &ep->CELL.socket_connect;
+	struct tsem_socket_accept_args *sap = &ep->CELL.socket_accept;
+	SHASH_DESC_ON_STACK(shash, tfm);
+
+	shash->tfm = tfm;
+	retn = crypto_shash_init(shash);
+	if (retn)
+		goto done;
+
+	if (ep->event == TSEM_MMAP_FILE) {
+		p = (u8 *) &mm_args->reqprot;
+		size = sizeof(mm_args->reqprot);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &mm_args->prot;
+		size = sizeof(mm_args->prot);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &mm_args->flags;
+		size = sizeof(mm_args->flags);
+		if (!mm_args->file) {
+			retn = crypto_shash_finup(shash, p, size, mapping);
+			goto done;
+		}
+
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+	}
+
+	switch (ep->event) {
+	case TSEM_FILE_OPEN:
+	case TSEM_MMAP_FILE:
+	case TSEM_BPRM_SET_CREDS:
+		p = (u8 *) &ep->file.flags;
+		size = sizeof(ep->file.flags);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->file.uid;
+		size = sizeof(ep->file.uid);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->file.gid;
+		size = sizeof(ep->file.gid);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->file.mode;
+		size = sizeof(ep->file.mode);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->file.name_length;
+		size = sizeof(ep->file.name_length);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->file.name;
+		size = sizeof(ep->file.name);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->file.s_magic;
+		size = sizeof(ep->file.s_magic);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->file.s_id;
+		size = sizeof(ep->file.s_id);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->file.s_uuid;
+		size = sizeof(ep->file.s_uuid);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->file.digest;
+		size = sizeof(ep->file.digest);
+		retn = crypto_shash_finup(shash, p, size, mapping);
+		break;
+
+	case TSEM_SOCKET_CREATE:
+		p = (u8 *) &ep->CELL.socket_create.family;
+		size = sizeof(ep->CELL.socket_create.family);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->CELL.socket_create.type;
+		size = sizeof(ep->CELL.socket_create.type);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->CELL.socket_create.protocol;
+		size = sizeof(ep->CELL.socket_create.protocol);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->CELL.socket_create.kern;
+		size = sizeof(ep->CELL.socket_create.kern);
+		retn = crypto_shash_finup(shash, p, size, mapping);
+		if (retn)
+			goto done;
+		break;
+
+	case TSEM_SOCKET_CONNECT:
+	case TSEM_SOCKET_BIND:
+		p = (u8 *) &scp->family;
+		size = sizeof(scp->family);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		switch (scp->family) {
+		case AF_INET:
+			ipv4 = (struct sockaddr_in *) &scp->u.ipv4;
+			p = (u8 *) &ipv4->sin_port;
+			size = sizeof(ipv4->sin_port);
+			retn = crypto_shash_update(shash, p, size);
+			if (retn)
+				goto done;
+
+			p = (u8 *) &ipv4->sin_addr.s_addr;
+			size = sizeof(ipv4->sin_addr.s_addr);
+			retn = crypto_shash_finup(shash, p, size, mapping);
+			break;
+
+		case AF_INET6:
+			ipv6 = (struct sockaddr_in6 *) &scp->u.ipv6;
+			p = (u8 *) &ipv6->sin6_port;
+			size = sizeof(ipv6->sin6_port);
+			retn = crypto_shash_update(shash, p, size);
+			if (retn)
+				goto done;
+
+			p = (u8 *) ipv6->sin6_addr.in6_u.u6_addr8;
+			size = sizeof(ipv6->sin6_addr.in6_u.u6_addr8);
+			retn = crypto_shash_update(shash, p, size);
+			if (retn)
+				goto done;
+
+			p = (u8 *) &ipv6->sin6_flowinfo;
+			size = sizeof(ipv6->sin6_flowinfo);
+			retn = crypto_shash_update(shash, p, size);
+			if (retn)
+				goto done;
+
+			p = (u8 *) &ipv6->sin6_scope_id;
+			size = sizeof(ipv6->sin6_scope_id);
+			retn = crypto_shash_finup(shash, p, size, mapping);
+			if (retn)
+				goto done;
+			break;
+
+		default:
+			p = (u8 *) scp->u.mapping;
+			size = sizeof(scp->u.mapping);
+			retn = crypto_shash_finup(shash, p, size, mapping);
+			if (retn)
+				goto done;
+			break;
+		}
+		break;
+
+	case TSEM_SOCKET_ACCEPT:
+		p = (u8 *) &sap->family;
+		size = sizeof(sap->family);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &sap->type;
+		size = sizeof(sap->type);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &sap->port;
+		size = sizeof(sap->port);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		switch (sap->family) {
+		case AF_INET:
+			p = (u8 *) &sap->ipv4;
+			size = sizeof(sap->ipv4);
+			retn = crypto_shash_finup(shash, p, size, mapping);
+			if (retn)
+				goto done;
+			break;
+
+		case AF_INET6:
+			p = (u8 *) sap->ipv6.in6_u.u6_addr8;
+			size = sizeof(sap->ipv6.in6_u.u6_addr8);
+			retn = crypto_shash_finup(shash, p, size, mapping);
+			if (retn)
+				goto done;
+			break;
+
+		default:
+			p = sap->tsip->digest;
+			size = sizeof(sap->tsip->digest);
+			retn = crypto_shash_finup(shash, p, size, mapping);
+			if (retn)
+				goto done;
+			break;
+		}
+		break;
+
+	case TSEM_TASK_KILL:
+		p = (u8 *) &ep->CELL.task_kill.cross_model;
+		size = sizeof(ep->CELL.task_kill.cross_model);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->CELL.task_kill.signal;
+		size = sizeof(ep->CELL.task_kill.signal);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) &ep->CELL.task_kill.target;
+		size = sizeof(ep->CELL.task_kill.target);
+		retn = crypto_shash_finup(shash, p, size, mapping);
+		if (retn)
+			goto done;
+		break;
+
+	case TSEM_GENERIC_EVENT:
+		p = (u8 *) tsem_names[ep->CELL.event_type];
+		size = strlen(tsem_names[ep->CELL.event_type]);
+		retn = crypto_shash_update(shash, p, size);
+		if (retn)
+			goto done;
+
+		p = (u8 *) generic_cell;
+		size = sizeof(generic_cell);
+		retn = crypto_shash_finup(shash, p, size, mapping);
+		if (retn)
+			goto done;
+		break;
+
+	default:
+		break;
+	}
+
+ done:
+	return retn;
+}
+
+static int get_event_mapping(struct crypto_shash *tfm, int event, u8 *task_id,
+			     u8 *COE_id, u8 *cell_id, u8 *mapping)
+{
+	int retn = 0;
+	u32 event_id = (u32) event;
+	SHASH_DESC_ON_STACK(shash, tfm);
+
+	shash->tfm = tfm;
+	retn = crypto_shash_init(shash);
+	if (retn)
+		goto done;
+
+	retn = crypto_shash_update(shash, tsem_names[event_id],
+				   strlen(tsem_names[event_id]));
+	if (retn)
+		goto done;
+	if (task_id) {
+		retn = crypto_shash_update(shash, task_id, WP256_DIGEST_SIZE);
+		if (retn)
+			goto done;
+	}
+	retn = crypto_shash_update(shash, COE_id, WP256_DIGEST_SIZE);
+	if (retn)
+		goto done;
+	retn = crypto_shash_finup(shash, cell_id, WP256_DIGEST_SIZE, mapping);
+
+ done:
+	return retn;
+}
+
+static int map_event(enum tsem_event_type event, struct tsem_event *ep,
+		     u8 *task_id, u8 *event_mapping)
+{
+	int retn;
+	u8 COE_mapping[WP256_DIGEST_SIZE];
+	u8 cell_mapping[WP256_DIGEST_SIZE];
+	struct crypto_shash *tfm = NULL;
+
+	tfm = crypto_alloc_shash("sha256", 0, 0);
+	if (IS_ERR(tfm)) {
+		retn = PTR_ERR(tfm);
+		tfm = NULL;
+		goto done;
+	}
+
+	retn = get_COE_mapping(tfm, ep, COE_mapping);
+	if (retn)
+		goto done;
+
+	retn = get_cell_mapping(tfm, ep, cell_mapping);
+	if (retn)
+		goto done;
+
+	retn = get_event_mapping(tfm, event, task_id, COE_mapping,
+				 cell_mapping, event_mapping);
+ done:
+	crypto_free_shash(tfm);
+	return retn;
+}
+
+/**
+ * tsem_map_task() - Create the task identity description structure.
+ * @file: A pointer to the file structure defining the executable.
+ * @task_id: Pointer to the buffer that the task id will be copied to.
+ *
+ * This function creates the security event state point that will be used
+ * as the task identifier for the generation of security state points
+ * that are created by the process that task identifier is assigned to.
+ *
+ * Return: This function returns 0 if the mapping was successfully
+ *	   created and an error value otherwise.
+ */
+int tsem_map_task(struct file *file, u8 *task_id)
+{
+	int retn = 0;
+	u8 null_taskid[WP256_DIGEST_SIZE];
+	struct tsem_event *ep;
+	struct tsem_event_parameters params;
+
+	params.u.file = file;
+	ep = tsem_event_allocate(TSEM_BPRM_SET_CREDS, &params);
+	if (IS_ERR(ep)) {
+		retn = PTR_ERR(ep);
+		ep = NULL;
+		goto done;
+	}
+
+	memset(null_taskid, '\0', sizeof(null_taskid));
+	retn = map_event(TSEM_BPRM_SET_CREDS, ep, null_taskid, task_id);
+	tsem_event_put(ep);
+
+ done:
+	return retn;
+}
+
+/**
+ * tsem_map_event() - Create a security event mapping.
+ * @event: The number of the event to be mapped.
+ * @file: A pointer to the structure containing the event description
+ *	  parameters.
+ *
+ * This function creates the tsem_event structure that describes
+ * a security event.
+ *
+ * Return: On success the function returns a pointer to the tsem_event
+ *	   structure that describes the event.  If an error is encountered
+ *	   an error return value is encoded in the pointer.
+ */
+struct tsem_event *tsem_map_event(enum tsem_event_type event,
+				  struct tsem_event_parameters *params)
+{
+	int retn = 0;
+	struct tsem_event *ep;
+	struct tsem_task *task = tsem_task(current);
+
+	ep = tsem_event_allocate(event, params);
+	if (IS_ERR(ep))
+		goto done;
+
+	if (task->context->external)
+		goto done;
+
+	retn = map_event(event, ep, task->task_id, ep->mapping);
+	if (retn) {
+		tsem_event_put(ep);
+		ep = ERR_PTR(retn);
+	}
+
+ done:
+	return ep;
+}
-- 
2.39.1


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 13/14] Implement an internal Trusted Modeling Agent.
  2023-02-04  5:09 [PATCH 00/14] Implement Trusted Security Event Modeling Dr. Greg
                   ` (11 preceding siblings ...)
  2023-02-04  5:09 ` [PATCH 12/14] Implement security event mapping Dr. Greg
@ 2023-02-04  5:09 ` Dr. Greg
  2023-02-04  5:09 ` [PATCH 14/14] Activate the configuration and build of the TSEM LSM Dr. Greg
       [not found] ` <20230204115917.1015-1-hdanton@sina.com>
  14 siblings, 0 replies; 42+ messages in thread
From: Dr. Greg @ 2023-02-04  5:09 UTC (permalink / raw)
  To: linux-security-module

A Trusted Modeling Agent (TMA) is an implementation of a modeling
algorithm that converts a description of a security event (LSM
hook) into a security state point.  The sum of these state points
is considered to be the functional value of the security model
implemented for the modeling domain.

The current model implemented is the simple deterministic model
used by the Quixote trust orchestrators.  These orchestrators
represent an initial implementation of the support infrastructure
needed to use the TSEM modeling LSM.  It is anticipated that
other in-kernel modeling implementations will be developed.

The TMA takes the mapping of a security event state point, as
generated by the tsem_map_event() function, and determines
whether or not this point is a valid coefficient in the
implemented model.  If it is a valid point the process executing
the security event is designated as being trusted, otherwise the
state of the process is set to be untrusted.

By default the TMA runs in free modeling mode where all security
events are considered valid.  In this mode, the security state
point is registered as a valid point and the description of the
event is added to the security execution trajectory for the
model.

The model implementation can be 'sealed' through the TSEM control
plane, a condition that causes any state points not registered in
the model to be considered a 'forensics' event.  The description
of such an event is added to the forensics execution trajectory
for the model.  A forensics event does not result in permission
to the event to be denied unless the model is placed in
'enforcing' mode.

While the current in-kernel TMA is largely deterministic, one
approximation method is provided by this model, which is the
notion of a file digest 'pseudonym'.  A pseudonym can be declared
for an inode by registering the value of the following function
with the model:

Pseudonym = SHA256(PATH_LENGTH || PATHNAME)

If a file pseudonym is detected the file digest value used for
the CELL definition is set to a default value that is the SHA256
value of a zero length file.  The model.c file implementing the
in kernel modeling agent defines this value.

The pseudonym value is model specific.  A separate modeling
domain, with a pseudonym definition, will use the actual computed
digest of the file.

The TMA implementation also supports the definition of 'base'
point that is a 32 byte nonce that can be used to extend each
security event state point before it is added to the model.  This
allows a verifying partner to specify a random value that will
allow a verifying partner to confirm the 'freshness' of an
attestation of the function state of the model.

The modeling implementation supports two different functional
values for the model being implemented.  The classic linear
extension sum of all the security state points and a value
referred to as the 'state' of the security model.

The 'state' value is designed to make the measurement value
invariant to scheduling variations that cause the classic trusted
system measurement to be non-deterministic between runs of a
workload.  The state value is computed by sorting the security
event state points in the model in big-endian (natural hash byte
order) format and then computing the extension sum over this
sorted vector of points.

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

diff --git a/security/tsem/model.c b/security/tsem/model.c
new file mode 100644
index 000000000000..e2fb7307c1b0
--- /dev/null
+++ b/security/tsem/model.c
@@ -0,0 +1,598 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * Copyright (C) 2022 Enjellic Systems Development, LLC
+ * Author: Dr. Greg Wettstein <greg@enjellic.com>
+ *
+ * Implements the an kernel modeling agent.
+ */
+
+#include <linux/list_sort.h>
+#include <crypto/hash.h>
+
+#include "tsem.h"
+
+const u8 pseudonym_digest[WP256_DIGEST_SIZE] = {
+	0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
+	0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
+	0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
+	0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55
+};
+
+struct state_point {
+	struct list_head list;
+	struct tsem_event_point *point;
+};
+
+struct pseudonym {
+	struct list_head list;
+	u8 mapping[WP256_DIGEST_SIZE];
+};
+
+static int generate_pseudonym(struct crypto_shash *tfm, struct tsem_file *ep,
+			      u8 *pseudonym)
+{
+	int retn = 0;
+	SHASH_DESC_ON_STACK(shash, tfm);
+
+	shash->tfm = tfm;
+
+	retn = crypto_shash_init(shash);
+	if (retn)
+		goto done;
+	retn = crypto_shash_update(shash, (u8 *) &ep->name_length,
+				   sizeof(ep->name_length));
+	if (retn)
+		goto done;
+	retn = crypto_shash_finup(shash, ep->name, WP256_DIGEST_SIZE,
+				  pseudonym);
+ done:
+	return retn;
+}
+
+static int have_point(u8 *point)
+{
+	int retn = 0;
+	struct tsem_event_point *entry;
+	struct tsem_model *model = tsem_model(current);
+
+	mutex_lock(&model->point_mutex);
+	list_for_each_entry(entry, &model->point_list, list) {
+		if (memcmp(entry->point, point, WP256_DIGEST_SIZE) == 0) {
+			if (entry->valid)
+				retn = 1;
+			else
+				retn = -EPERM;
+			goto done;
+		}
+	}
+
+ done:
+	mutex_unlock(&model->point_mutex);
+	return retn;
+}
+
+static int add_event_point(u8 *point, bool valid)
+{
+	int retn = 1;
+	struct tsem_event_point *entry;
+	struct state_point *state;
+	struct tsem_model *model = tsem_model(current);
+
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		goto done;
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (!state)
+		goto done;
+	state->point = entry;
+
+	mutex_lock(&model->point_mutex);
+	memcpy(entry->point, point, WP256_DIGEST_SIZE);
+	entry->valid = valid;
+	list_add_tail(&entry->list, &model->point_list);
+	list_add_tail(&state->list, &model->state_list);
+	++model->point_count;
+	mutex_unlock(&model->point_mutex);
+	retn = 0;
+
+ done:
+	return retn;
+}
+
+static int add_trajectory_point(struct tsem_event *ep)
+{
+	struct tsem_trajectory *entry;
+	struct tsem_model *model = tsem_model(current);
+
+	entry = kzalloc(sizeof(struct tsem_trajectory), GFP_KERNEL);
+	if (!entry)
+		return -ENOMEM;
+	entry->ep = ep;
+	tsem_event_get(ep);
+
+	mutex_lock(&model->trajectory_mutex);
+	list_add_tail(&entry->list, &model->trajectory_list);
+	++model->trajectory_count;
+	mutex_unlock(&model->trajectory_mutex);
+
+	return 0;
+}
+
+static int add_forensic_point(struct tsem_event *ep)
+{
+	struct tsem_trajectory *entry;
+	struct tsem_model *model = tsem_model(current);
+
+	if (model->forensics_count == model->max_forensics_count)
+		return -E2BIG;
+
+	entry = kzalloc(sizeof(struct tsem_trajectory), GFP_KERNEL);
+	if (!entry)
+		return -ENOMEM;
+	entry->ep = ep;
+	tsem_event_get(ep);
+
+	mutex_lock(&model->forensics_mutex);
+	list_add_tail(&entry->list, &model->forensics_list);
+	++model->forensics_count;
+	mutex_unlock(&model->forensics_mutex);
+
+	return 0;
+}
+
+static int get_host_measurement(struct crypto_shash *tfm, u8 *id,
+				size_t idlength, u8 *digest)
+{
+	int retn;
+	SHASH_DESC_ON_STACK(shash, tfm);
+	struct tsem_model *model = tsem_model(current);
+
+	shash->tfm = tfm;
+	retn = crypto_shash_init(shash);
+	if (retn)
+		goto done;
+	retn = crypto_shash_update(shash, model->base, WP256_DIGEST_SIZE);
+	if (retn)
+		goto done;
+	retn = crypto_shash_finup(shash, id, idlength, digest);
+
+ done:
+	return retn;
+}
+
+static int update_events_measurement(struct crypto_shash *tfm, u8 *id)
+{
+	int retn;
+	u8 digest[WP256_DIGEST_SIZE];
+	struct tsem_model *model = tsem_model(current);
+	SHASH_DESC_ON_STACK(shash, tfm);
+
+	retn = get_host_measurement(tfm, id, WP256_DIGEST_SIZE, digest);
+	if (retn)
+		goto done;
+
+	shash->tfm = tfm;
+	retn = crypto_shash_init(shash);
+	if (retn)
+		goto done;
+
+	retn = crypto_shash_update(shash, model->measurement,
+				   WP256_DIGEST_SIZE);
+	if (retn)
+		goto done;
+
+	retn = crypto_shash_finup(shash, digest, sizeof(digest),
+				  model->measurement);
+	if (retn)
+		goto done;
+
+	if (!tsem_context(current)->id)
+		retn = tsem_trust_add_event(digest);
+
+ done:
+	return retn;
+}
+
+static int state_sort(void *priv, const struct list_head *a,
+		      const struct list_head *b)
+{
+	unsigned int lp, retn;
+	struct state_point *ap = container_of(a, struct state_point, list);
+	struct state_point *bp = container_of(b, struct state_point, list);
+
+	for (lp = 0; lp < WP256_DIGEST_SIZE - 1; ++lp) {
+		if (ap->point->point[lp] == bp->point->point[lp])
+			continue;
+		retn = ap->point->point[lp] > bp->point->point[lp];
+		goto done;
+	}
+	retn = ap->point->point[lp] > bp->point->point[lp];
+
+ done:
+	return retn;
+}
+
+/**
+ * tesm_model_compute_state() - Calculate a security model state value.
+ *
+ * This value is used to trigger the computation of the security
+ * state description value for a modeling domain.
+ */
+void tsem_model_compute_state(void)
+{
+	u8 state[WP256_DIGEST_SIZE];
+	struct state_point *entry;
+	struct tsem_model *model = tsem_model(current);
+	struct crypto_shash *sha256 = NULL;
+	SHASH_DESC_ON_STACK(shash, tfm);
+
+	sha256 = crypto_alloc_shash("sha256", 0, 0);
+	if (IS_ERR(sha256))
+		return;
+
+	shash->tfm = sha256;
+	if (crypto_shash_init(shash))
+		goto done;
+
+	memset(state, '\0', sizeof(state));
+	if (crypto_shash_update(shash, state, WP256_DIGEST_SIZE))
+		goto done;
+
+	if (get_host_measurement(sha256, tsem_trust_aggregate(),
+				 WP256_DIGEST_SIZE, state))
+		goto done;
+
+	if (crypto_shash_finup(shash, state, sizeof(state), state))
+		goto done;
+
+	mutex_lock(&model->point_mutex);
+	list_sort(NULL, &model->state_list, state_sort);
+
+	memcpy(model->state, state, sizeof(model->state));
+	list_for_each_entry(entry, &model->state_list, list) {
+		if (get_host_measurement(sha256, entry->point->point,
+					 WP256_DIGEST_SIZE, state))
+			goto unlock_done;
+
+		if (crypto_shash_init(shash))
+			goto unlock_done;
+		if (crypto_shash_update(shash, model->state,
+					WP256_DIGEST_SIZE))
+			goto unlock_done;
+		if (crypto_shash_finup(shash, state, WP256_DIGEST_SIZE,
+				       model->state))
+			goto unlock_done;
+	}
+
+ unlock_done:
+	mutex_unlock(&model->point_mutex);
+ done:
+	if (sha256)
+		crypto_free_shash(sha256);
+}
+
+/**
+ * tsem_model_has_pseudonym() - Test for a model pseudonym.
+ * @tsip: A pointer to the TSEM inode security structure.
+ * @ep: A pointer to the TSEM event description structure.
+ * @mapping: A byte array into which the pseudonym state is
+ *	     to be copied.
+ *
+ * This function is used to test whether a pseudonym has been
+ * declared for a modeling domain.  The pseudonym state point is
+ * made available via the array pointed to by the mapping variable.
+ *
+ * Return: If an error occurs during the pseudonym probe a negative
+ *	   return value is returned.  A zero return value indicates that
+ *	   a pseudonym was not present.  A value of one indicates that a
+ *	   psuedonym had been defined and the mapping variable contains
+ *	   the pseudonym state point.
+ */
+int tsem_model_has_pseudonym(struct tsem_inode *tsip, struct tsem_file *ep,
+			     u8 *mapping)
+{
+	int retn = 0;
+	u8 pseudo_mapping[WP256_DIGEST_SIZE];
+	struct tsem_model *model = tsem_model(current);
+	struct crypto_shash *tfm;
+	struct pseudonym *entry;
+
+	tfm = crypto_alloc_shash("sha256", 0, 0);
+	if (IS_ERR(tfm)) {
+		retn = PTR_ERR(tfm);
+		goto done;
+	}
+	retn = generate_pseudonym(tfm, ep, pseudo_mapping);
+	if (retn)
+		goto done;
+
+	mutex_lock(&model->pseudonym_mutex);
+	list_for_each_entry(entry, &model->pseudonym_list, list) {
+		if (!memcmp(entry->mapping, pseudo_mapping,
+			    sizeof(entry->mapping))) {
+			retn = 1;
+			goto done;
+		}
+	}
+	retn = 0;
+
+ done:
+	if (retn)
+		memcpy(mapping, pseudonym_digest, WP256_DIGEST_SIZE);
+
+	mutex_unlock(&model->pseudonym_mutex);
+	crypto_free_shash(tfm);
+	return retn;
+}
+
+/**
+ * tesm_model_event() - Inject a security event into a modeling domain.
+ * @ep: A pointer to the event description structure.
+ *
+ * This function is the entry point for the in kernel Trusted Modeling
+ * Agent (TMA).  It takes a description of an event encoded in a
+ * tsem_event structure and generates and updates the security model
+ * description.
+ *
+ * Return: If an error occurs during the injection of an event into a
+ *	   model a negative error value is returned.  A value of zero
+ *	   is returned if the event was successfully modeled.  The
+ *	   security status of the event is returned by encoding the value
+ *	   in the bad_COE member of the tsem_task structure.
+ */
+int tsem_model_event(struct tsem_event *ep)
+{
+	int retn;
+	struct crypto_shash *sha256 = NULL;
+	struct tsem_task *task = tsem_task(current);
+	struct tsem_TMA_context *ctx = task->context;
+
+	sha256 = crypto_alloc_shash("sha256", 0, 0);
+	if (IS_ERR(sha256))
+		return PTR_ERR(sha256);
+
+	retn = have_point(ep->mapping);
+	if (retn) {
+		if (retn != 1)
+			task->trust_status = TSEM_TASK_UNTRUSTED;
+		return 0;
+	}
+
+	retn = update_events_measurement(sha256, ep->mapping);
+	if (retn)
+		goto done;
+
+	if (ctx->sealed) {
+		retn = add_event_point(ep->mapping, false);
+		if (!retn)
+			retn = add_forensic_point(ep);
+		task->trust_status = TSEM_TASK_UNTRUSTED;
+	} else {
+		retn = add_event_point(ep->mapping, true);
+		if (!retn)
+			retn = add_trajectory_point(ep);
+	}
+	if (retn)
+		retn = -EPERM;
+
+ done:
+	crypto_free_shash(sha256);
+	return retn;
+}
+
+/**
+ * tesm_model_load_point() - Load a security state event into a model.
+ * @point: A pointer to the array containing the security state
+ *	   point to be added to the model.
+ *
+ * This function takes the binary representation of a security state
+ * point and loads it into the current model domain.
+ *
+ * Return: If an error occurs during the processing of the security state
+ *	   point a negative return value is returned.  A return value of
+ *	   zero indicates the point was successfully loaded into the domain.
+ */
+int tsem_model_load_point(u8 *point)
+{
+	ssize_t retn = 0;
+	struct crypto_shash *tfmsha256 = NULL;
+	struct tsem_TMA_context *ctx = tsem_context(current);
+
+	if (have_point(point))
+		goto done;
+	if (add_event_point(point, true)) {
+		retn = -ENOMEM;
+		goto done;
+	}
+
+	tfmsha256 = crypto_alloc_shash("sha256", 0, 0);
+	if (IS_ERR(tfmsha256)) {
+		retn = PTR_ERR(tfmsha256);
+		goto done;
+	}
+
+	if (!ctx->model->have_aggregate) {
+		ctx->model->have_aggregate = true;
+		retn = update_events_measurement(tfmsha256,
+						 tsem_trust_aggregate());
+		if (retn)
+			goto done;
+	}
+
+	retn = update_events_measurement(tfmsha256, point);
+
+done:
+	if (tfmsha256)
+		crypto_free_shash(tfmsha256);
+	return retn;
+
+}
+
+/**
+ * tesm_model_load_pseudonym() - Load a pseudonym state point to a model.
+ * @mapping: A pointer to the array containing the pseudonym state
+ *	     point that is to be added to the model.
+ *
+ * This function takes the binary representation of a file pseudonym
+ * and declares the presence of the pseudonym in the modeling domain.
+ *
+ * Return: If an error occurs during the processing of the pseudonym
+ *	   state point a negative return value is returned.  A return
+ *	   value of zero indicates the point was successfully loaded
+ *	   into the model.
+ */
+int tsem_model_load_pseudonym(u8 *mapping)
+{
+	struct pseudonym *psp = NULL;
+	struct tsem_model *model = tsem_model(current);
+
+	psp = kzalloc(sizeof(struct pseudonym), GFP_KERNEL);
+	if (!psp)
+		return -ENOMEM;
+	memcpy(psp->mapping, mapping, sizeof(psp->mapping));
+
+	mutex_lock(&model->pseudonym_mutex);
+	list_add_tail(&psp->list, &model->pseudonym_list);
+	mutex_unlock(&model->pseudonym_mutex);
+	return 0;
+}
+
+/**
+ * tesm_model_load_base() - Load a model base point.
+ * @mapping: A pointer to the array containing the base point to be
+ *	     set for the model.
+ *
+ * This function takes the binary representation of a base point and
+ * sets this point as the base point for the model.
+ */
+void tsem_model_load_base(u8 *mapping)
+{
+	struct tsem_model *model = tsem_model(current);
+
+	memcpy(model->base, mapping, sizeof(model->base));
+}
+
+/**
+ * tesm_model_add_aggregate() - Add the hardware aggregate to a model.
+ *
+ * This function adds the hardware aggregate value to an internally
+ * modeled security domain.
+ *
+ * Return: If an error occurs during the injection of the aggregate
+ *	   value into the model a negative error value is returned.
+ *	   A return value of zero indicates the aggregate was
+ *	   successfully added.
+ */
+int tsem_model_add_aggregate(void)
+{
+	int retn;
+	struct crypto_shash *tfm = NULL;
+
+	tfm = crypto_alloc_shash("sha256", 0, 0);
+	if (IS_ERR(tfm))
+		return PTR_ERR(tfm);
+
+	retn = update_events_measurement(tfm, tsem_trust_aggregate());
+	crypto_free_shash(tfm);
+	return retn;
+}
+
+/**
+ * tsem_model_allocate() - Allocates a kernel TMA modeling structure.
+ *
+ * This function allocates and initializes a tsem_model structure
+ * that is used to hold modeling information for an in kernel
+ * modeling domain.
+ *
+ * Return: On success a pointer to the model description structure is
+ *	   returned.  If an error occurs an error return value is
+ *	   encoded in the returned pointer.
+ */
+struct tsem_model *tsem_model_allocate(void)
+{
+	struct tsem_model *model = NULL;
+
+	model = kzalloc(sizeof(struct tsem_model), GFP_KERNEL);
+	if (!model)
+		return NULL;
+
+	mutex_init(&model->point_mutex);
+	INIT_LIST_HEAD(&model->point_list);
+	INIT_LIST_HEAD(&model->state_list);
+
+	mutex_init(&model->trajectory_mutex);
+	INIT_LIST_HEAD(&model->trajectory_list);
+
+	model->max_forensics_count = 100;
+	mutex_init(&model->forensics_mutex);
+	INIT_LIST_HEAD(&model->forensics_list);
+
+	mutex_init(&model->pseudonym_mutex);
+	INIT_LIST_HEAD(&model->pseudonym_list);
+
+	return model;
+}
+
+/**
+ * tsem_model_free() - Frees an a kernel TMA description structure.
+ * @ctx: A pointer to the TMA modeling description structure whose
+ *	 model definition is to be deleted.
+ *
+ * This function is called when the last reference to a kernel
+ * based TMA model description structure is released.
+ */
+void tsem_model_free(struct tsem_TMA_context *ctx)
+{
+	unsigned int cnt;
+	struct tsem_event_point *centry, *tmp_centry;
+	struct state_point *state, *tmp_state;
+	struct tsem_trajectory *tentry, *tmp_tentry;
+	struct pseudonym *sentry, *tmp_sentry;
+	struct tsem_model *model = ctx->model;
+
+	cnt = 0;
+	list_for_each_entry_safe(centry, tmp_centry, &model->point_list,
+				 list) {
+		list_del(&centry->list);
+		kfree(centry);
+		++cnt;
+	}
+
+	cnt = 0;
+	list_for_each_entry_safe(state, tmp_state, &model->state_list,
+				 list) {
+		list_del(&state->list);
+		kfree(state);
+		++cnt;
+	}
+
+	cnt = 0;
+	list_for_each_entry_safe(tentry, tmp_tentry, &model->trajectory_list,
+				 list) {
+		list_del(&tentry->list);
+		tsem_event_put(tentry->ep);
+		++cnt;
+	}
+
+	cnt = 0;
+	list_for_each_entry_safe(sentry, tmp_sentry, &model->pseudonym_list,
+				 list) {
+		list_del(&sentry->list);
+		kfree(sentry);
+		++cnt;
+	}
+
+	if (ctx->sealed) {
+		cnt = 0;
+		list_for_each_entry_safe(tentry, tmp_tentry,
+					 &model->forensics_list, list) {
+			list_del(&tentry->list);
+			tsem_event_put(tentry->ep);
+			++cnt;
+		}
+	}
+
+	kfree(model);
+}
-- 
2.39.1


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 14/14] Activate the configuration and build of the TSEM LSM.
  2023-02-04  5:09 [PATCH 00/14] Implement Trusted Security Event Modeling Dr. Greg
                   ` (12 preceding siblings ...)
  2023-02-04  5:09 ` [PATCH 13/14] Implement an internal Trusted Modeling Agent Dr. Greg
@ 2023-02-04  5:09 ` Dr. Greg
  2023-02-08 22:15   ` Casey Schaufler
       [not found] ` <20230204115917.1015-1-hdanton@sina.com>
  14 siblings, 1 reply; 42+ messages in thread
From: Dr. Greg @ 2023-02-04  5:09 UTC (permalink / raw)
  To: linux-security-module

Complete the implementation by integrating the LSM into the
configuration and kernel build infrastructure.

Signed-off-by: Greg Wettstein <greg@enjellic.com>
---
 security/Kconfig       | 11 ++++++-----
 security/Makefile      |  1 +
 security/tsem/Kconfig  | 22 ++++++++++++++++++++++
 security/tsem/Makefile |  2 ++
 4 files changed, 31 insertions(+), 5 deletions(-)
 create mode 100644 security/tsem/Kconfig
 create mode 100644 security/tsem/Makefile

diff --git a/security/Kconfig b/security/Kconfig
index e6db09a779b7..98c538ad6790 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -207,6 +207,7 @@ source "security/yama/Kconfig"
 source "security/safesetid/Kconfig"
 source "security/lockdown/Kconfig"
 source "security/landlock/Kconfig"
+source "security/tsem/Kconfig"
 
 source "security/integrity/Kconfig"
 
@@ -246,11 +247,11 @@ endchoice
 
 config LSM
 	string "Ordered list of enabled LSMs"
-	default "landlock,lockdown,yama,loadpin,safesetid,integrity,smack,selinux,tomoyo,apparmor,bpf" if DEFAULT_SECURITY_SMACK
-	default "landlock,lockdown,yama,loadpin,safesetid,integrity,apparmor,selinux,smack,tomoyo,bpf" if DEFAULT_SECURITY_APPARMOR
-	default "landlock,lockdown,yama,loadpin,safesetid,integrity,tomoyo,bpf" if DEFAULT_SECURITY_TOMOYO
-	default "landlock,lockdown,yama,loadpin,safesetid,integrity,bpf" if DEFAULT_SECURITY_DAC
-	default "landlock,lockdown,yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor,bpf"
+	default "landlock,lockdown,yama,loadpin,safesetid,integrity,smack,selinux,tomoyo,apparmor,bpf,tsem" if DEFAULT_SECURITY_SMACK
+	default "landlock,lockdown,yama,loadpin,safesetid,integrity,apparmor,selinux,smack,tomoyo,bpf,tsem" if DEFAULT_SECURITY_APPARMOR
+	default "landlock,lockdown,yama,loadpin,safesetid,integrity,tomoyo,bpf,tsem" if DEFAULT_SECURITY_TOMOYO
+	default "landlock,lockdown,yama,loadpin,safesetid,integrity,bpf,tsem" if DEFAULT_SECURITY_DAC
+	default "landlock,lockdown,yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor,bpf,tsem"
 	help
 	  A comma-separated list of LSMs, in initialization order.
 	  Any LSMs left off this list will be ignored. This can be
diff --git a/security/Makefile b/security/Makefile
index 18121f8f85cd..11d93885c806 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_SECURITY_LOCKDOWN_LSM)	+= lockdown/
 obj-$(CONFIG_CGROUPS)			+= device_cgroup.o
 obj-$(CONFIG_BPF_LSM)			+= bpf/
 obj-$(CONFIG_SECURITY_LANDLOCK)		+= landlock/
+obj-$(CONFIG_SECURITY_TSEM)		+= tsem/
 
 # Object integrity file lists
 obj-$(CONFIG_INTEGRITY)			+= integrity/
diff --git a/security/tsem/Kconfig b/security/tsem/Kconfig
new file mode 100644
index 000000000000..f9199686844a
--- /dev/null
+++ b/security/tsem/Kconfig
@@ -0,0 +1,22 @@
+config SECURITY_TSEM
+	bool "Trusted Security Event Modeling"
+	depends on SECURITY
+	depends on NET && INET
+	select SECURITY_NETWORK
+	select SECURITYFS
+	select CRYPTO
+	select CRYPTO_SHA256
+	select CRYPTO_HASH_INFO
+	select TCG_TPM if HAS_IOMEM && !UML
+	select TCG_TIS if TCG_TPM && X86
+	select TCG_CRB if TCG_TPM && ACPI
+	default n
+	help
+	  This option selects support for Trusted Security Event
+	  Modeling (TSEM).  TSEM implements the ability to model
+	  the security state of either the system at large or in a
+	  restricted namespace on the basis of the LSM security
+	  events and attributes that occur in the scope of the model.
+	  The model may be implemented either in the kernel proper
+	  or exported to an external Trusted Modeling Agent (TMA).
+	  If you are unsure how to answer this question, answer N.
diff --git a/security/tsem/Makefile b/security/tsem/Makefile
new file mode 100644
index 000000000000..d43cf2ae2142
--- /dev/null
+++ b/security/tsem/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_SECURITY_TSEM) := tsem.o model.o namespace.o map.o event.o fs.o \
+	export.o trust.o
-- 
2.39.1


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* Re: [PATCH 05/14] Add TSEM master header file.
       [not found]   ` <ecb168ef-b82d-fd61-f2f8-54a4ef8c3b48@schaufler-ca.com>
@ 2023-02-06  0:10     ` Dr. Greg
  0 siblings, 0 replies; 42+ messages in thread
From: Dr. Greg @ 2023-02-06  0:10 UTC (permalink / raw)
  To: Casey Schaufler; +Cc: linux-security-module

On Sat, Feb 04, 2023 at 06:58:08PM -0800, Casey Schaufler wrote:

> On 2/3/2023 9:09 PM, 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 the TSEM LSM implementation.

Hi Casey, thanks for taking the time to look at all of this and raise
issues, we appreciate the feedback.

> This is really awkward.

With respect to awkward, those who know me well would never accuse me
of terpsichoric elegance, either balletic or in technology.... :-)

> Without the uses of the structures and constants it's very difficult
> to understand how any of this makes sense. It would be easier to
> review if the structures and constants were introduced as they are
> used rather than being presented in one massive dump.

With respect to any of this making sense, we've read and studied the
existing LSM's fairly extensively as we built TSEM, we accept our
prejudices of course, but we think that TSEM is probably one of the
easiest to follow conceptually.

Doesn't mean we can't do better though, particularly as we look at the
issue of that header file retrospectively.

I think where the presentation of the structures and enumeration
types, as a single entity falls down, is not explicitly documenting
the role and function of the structures and constants in that file.
We did that for the external functions in the compilation units and
should have done that for the contents of the include file.

I'm not sure that adding things to the include file incrementally will
be any more understandable without more explicit documentation.  If we
document them now, it should help not only the review process but
anyone who needs to look at the code down the road with a mind on
understanding whqt is going on.

Having the include file introduced as a standalone entity also assists
in reliably rolling a review patch set.  It is already easy enough to
make a mistake and we don't want to waste reviewer time and list
bandwidith with a blown patchset.

We will collect whatever additional comments are forthcoming and fully
document the contents of that file for the second spin of the patch.

Thanks again for your observations.

As always,
Dr. Greg

The Quixote Project - Flailing at the Travails of Cybersecurity

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 04/14] Implement CAP_TRUST capability.
  2023-02-04  5:09 ` [PATCH 04/14] Implement CAP_TRUST capability Dr. Greg
@ 2023-02-06 17:28   ` Serge Hallyn (shallyn)
  2023-02-11  0:32     ` Dr. Greg
       [not found]   ` <a12483d1-9d57-d429-789b-9e47ff575546@schaufler-ca.com>
  1 sibling, 1 reply; 42+ messages in thread
From: Serge Hallyn (shallyn) @ 2023-02-06 17:28 UTC (permalink / raw)
  To: Dr. Greg; +Cc: linux-security-module

On Fri, Feb 03, 2023 at 11:09:44PM -0600, Dr. Greg wrote:
> TSEM was designed to support a Trust Orchestration System (TOS)
> security architecture.  A TOS based system uses the concept of a
> minimum Trusted Computing Base of utilities, referred to as trust
> orchestrators, that maintain workloads in a trusted execution
> state.  The trust orchestrators are thus, from a security
> perspective, the most privileged assets on the platform.
> 
> Introduce the CAP_TRUST capability that is defined as a
> capability that allows a process to alter the trust status of the

This sounds like CAP_MAC_ADMIN.  Any reason not to re-use that?

> platform.  In a fully trust orchestrated system only the
> orchestrators carry this capability bit.
> 
> In TSEM the CAP_TRUST capability allows the holder to access the
> control plane of the LSM.  This ability allows subordinate
> modeling domains to be created and managed.  Most principally the
> CAP_TRUST capability allows the holder to designate whether or
> not a process should be trusted or untrusted.
> 
> The proposed Integrity Measurement Architecture namespaces would
> also be a candidate to use the CAP_TRUST capability.
> 
> Signed-off-by: Greg Wettstein <greg@enjellic.com>
> ---
>  include/uapi/linux/capability.h     | 6 +++++-
>  security/selinux/include/classmap.h | 2 +-
>  2 files changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/include/uapi/linux/capability.h b/include/uapi/linux/capability.h
> index 3d61a0ae055d..af677b534949 100644
> --- a/include/uapi/linux/capability.h
> +++ b/include/uapi/linux/capability.h
> @@ -417,7 +417,11 @@ struct vfs_ns_cap_data {
>  
>  #define CAP_CHECKPOINT_RESTORE	40
>  
> -#define CAP_LAST_CAP         CAP_CHECKPOINT_RESTORE
> +/* Allow modifications to the trust status of the system */
> +
> +#define CAP_TRUST	41
> +
> +#define CAP_LAST_CAP         CAP_TRUST
>  
>  #define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
>  
> diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
> index a3c380775d41..e8c497c16271 100644
> --- a/security/selinux/include/classmap.h
> +++ b/security/selinux/include/classmap.h
> @@ -30,7 +30,7 @@
>  		"wake_alarm", "block_suspend", "audit_read", "perfmon", "bpf", \
>  		"checkpoint_restore"
>  
> -#if CAP_LAST_CAP > CAP_CHECKPOINT_RESTORE
> +#if CAP_LAST_CAP > CAP_TRUST
>  #error New capability defined, please update COMMON_CAP2_PERMS.
>  #endif
>  
> -- 
> 2.39.1
> 

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 14/14] Activate the configuration and build of the TSEM LSM.
  2023-02-04  5:09 ` [PATCH 14/14] Activate the configuration and build of the TSEM LSM Dr. Greg
@ 2023-02-08 22:15   ` Casey Schaufler
  2023-02-09 22:21     ` Dr. Greg
  0 siblings, 1 reply; 42+ messages in thread
From: Casey Schaufler @ 2023-02-08 22:15 UTC (permalink / raw)
  To: Dr. Greg, linux-security-module; +Cc: casey

On 2/3/2023 9:09 PM, Dr. Greg wrote:
> Complete the implementation by integrating the LSM into the
> configuration and kernel build infrastructure.
>
> Signed-off-by: Greg Wettstein <greg@enjellic.com>
> ---
>  security/Kconfig       | 11 ++++++-----
>  security/Makefile      |  1 +
>  security/tsem/Kconfig  | 22 ++++++++++++++++++++++
>  security/tsem/Makefile |  2 ++
>  4 files changed, 31 insertions(+), 5 deletions(-)
>  create mode 100644 security/tsem/Kconfig
>  create mode 100644 security/tsem/Makefile
>
> diff --git a/security/Kconfig b/security/Kconfig
> index e6db09a779b7..98c538ad6790 100644
> --- a/security/Kconfig
> +++ b/security/Kconfig
> @@ -207,6 +207,7 @@ source "security/yama/Kconfig"
>  source "security/safesetid/Kconfig"
>  source "security/lockdown/Kconfig"
>  source "security/landlock/Kconfig"
> +source "security/tsem/Kconfig"
>  
>  source "security/integrity/Kconfig"
>  
> @@ -246,11 +247,11 @@ endchoice
>  
>  config LSM
>  	string "Ordered list of enabled LSMs"
> -	default "landlock,lockdown,yama,loadpin,safesetid,integrity,smack,selinux,tomoyo,apparmor,bpf" if DEFAULT_SECURITY_SMACK
> -	default "landlock,lockdown,yama,loadpin,safesetid,integrity,apparmor,selinux,smack,tomoyo,bpf" if DEFAULT_SECURITY_APPARMOR
> -	default "landlock,lockdown,yama,loadpin,safesetid,integrity,tomoyo,bpf" if DEFAULT_SECURITY_TOMOYO
> -	default "landlock,lockdown,yama,loadpin,safesetid,integrity,bpf" if DEFAULT_SECURITY_DAC
> -	default "landlock,lockdown,yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor,bpf"
> +	default "landlock,lockdown,yama,loadpin,safesetid,integrity,smack,selinux,tomoyo,apparmor,bpf,tsem" 

Better check with the BPF team to see if they're OK with TSEM
following BPF in loading order.

> if DEFAULT_SECURITY_SMACK
> +	default "landlock,lockdown,yama,loadpin,safesetid,integrity,apparmor,selinux,smack,tomoyo,bpf,tsem" if DEFAULT_SECURITY_APPARMOR
> +	default "landlock,lockdown,yama,loadpin,safesetid,integrity,tomoyo,bpf,tsem" if DEFAULT_SECURITY_TOMOYO
> +	default "landlock,lockdown,yama,loadpin,safesetid,integrity,bpf,tsem" if DEFAULT_SECURITY_DAC
> +	default "landlock,lockdown,yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor,bpf,tsem"
>  	help
>  	  A comma-separated list of LSMs, in initialization order.
>  	  Any LSMs left off this list will be ignored. This can be
> diff --git a/security/Makefile b/security/Makefile
> index 18121f8f85cd..11d93885c806 100644
> --- a/security/Makefile
> +++ b/security/Makefile
> @@ -24,6 +24,7 @@ obj-$(CONFIG_SECURITY_LOCKDOWN_LSM)	+= lockdown/
>  obj-$(CONFIG_CGROUPS)			+= device_cgroup.o
>  obj-$(CONFIG_BPF_LSM)			+= bpf/
>  obj-$(CONFIG_SECURITY_LANDLOCK)		+= landlock/
> +obj-$(CONFIG_SECURITY_TSEM)		+= tsem/
>  
>  # Object integrity file lists
>  obj-$(CONFIG_INTEGRITY)			+= integrity/
> diff --git a/security/tsem/Kconfig b/security/tsem/Kconfig
> new file mode 100644
> index 000000000000..f9199686844a
> --- /dev/null
> +++ b/security/tsem/Kconfig
> @@ -0,0 +1,22 @@
> +config SECURITY_TSEM
> +	bool "Trusted Security Event Modeling"
> +	depends on SECURITY
> +	depends on NET && INET
> +	select SECURITY_NETWORK
> +	select SECURITYFS
> +	select CRYPTO
> +	select CRYPTO_SHA256
> +	select CRYPTO_HASH_INFO
> +	select TCG_TPM if HAS_IOMEM && !UML
> +	select TCG_TIS if TCG_TPM && X86
> +	select TCG_CRB if TCG_TPM && ACPI
> +	default n
> +	help
> +	  This option selects support for Trusted Security Event
> +	  Modeling (TSEM).  TSEM implements the ability to model
> +	  the security state of either the system at large or in a
> +	  restricted namespace on the basis of the LSM security
> +	  events and attributes that occur in the scope of the model.
> +	  The model may be implemented either in the kernel proper
> +	  or exported to an external Trusted Modeling Agent (TMA).
> +	  If you are unsure how to answer this question, answer N.
> diff --git a/security/tsem/Makefile b/security/tsem/Makefile
> new file mode 100644
> index 000000000000..d43cf2ae2142
> --- /dev/null
> +++ b/security/tsem/Makefile
> @@ -0,0 +1,2 @@
> +obj-$(CONFIG_SECURITY_TSEM) := tsem.o model.o namespace.o map.o event.o fs.o \
> +	export.o trust.o

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 08/14] Implement TSEM control plane.
  2023-02-04  5:09 ` [PATCH 08/14] Implement TSEM control plane Dr. Greg
@ 2023-02-09 11:30   ` Greg KH
  2023-02-11  0:18     ` Dr. Greg
  0 siblings, 1 reply; 42+ messages in thread
From: Greg KH @ 2023-02-09 11:30 UTC (permalink / raw)
  To: Dr. Greg; +Cc: linux-security-module

On Fri, Feb 03, 2023 at 11:09:48PM -0600, Dr. Greg wrote:
> The fs.c file contains the implementation of the TSEM control
> plane that is in the form of a pseudo-filesystem mounted on the
> following directory:
> 
> /sys/fs/tsem

Why are you using sysfs to mount this?

> 
> The following file documents the interface provided by the
> control plane:
> 
> Documentation/ABI/testing/tsemfs
> 
> The pseudo-files act on the modeling context of the process that
> is acting on the file.  For example, reading the 'id'
> pseudo-file, returns the modeling domain identifier that the
> process is running in.
> 
> The ExternalTMA directory is used to segreate the pseudo-files
> that are created in order to surface security event descriptions
> to an external trust orchestrator.  The files in this directory
> appear as the numeric value of the modeling domain they were
> created for.
> 
> The 'control' pseudo-file is the only writable file in the plane
> and is used to control the TSEM implementation.  The most
> important and primary roles are to create namespaces and set the
> trust status of a process modeled by an external TMA.
> 
> Signed-off-by: Greg Wettstein <greg@enjellic.com>
> ---
>  security/tsem/fs.c | 894 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 894 insertions(+)
>  create mode 100644 security/tsem/fs.c
> 
> diff --git a/security/tsem/fs.c b/security/tsem/fs.c
> new file mode 100644
> index 000000000000..2898a1cc8c97
> --- /dev/null
> +++ b/security/tsem/fs.c
> @@ -0,0 +1,894 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +
> +/*
> + * Copyright (C) 2022 Enjellic Systems Development, LLC

It's 2023 :)

> + * Author: Dr. Greg Wettstein <greg@enjellic.com>
> + *
> + * Implements the sysfs based control plane.

This is NOT sysfs, it is your own filesystem, please don't confuse the
two.

> + */
> +
> +#include <linux/seq_file.h>
> +#include <linux/sysfs.h>
> +#include <linux/fs_context.h>
> +#include <linux/namei.h>
> +#include <linux/poll.h>
> +#include <uapi/linux/magic.h>
> +
> +#include "tsem.h"
> +
> +static int fs_init_context(struct fs_context *context);
> +static int fs_get_tree(struct fs_context *context);
> +
> +static struct file_system_type fs_definition = {
> +	.name = "tsemfs",
> +	.init_fs_context = fs_init_context,
> +	.kill_sb = kill_litter_super
> +};
> +
> +static struct fs_context_operations fs_operations = {
> +	.get_tree = fs_get_tree
> +};
> +
> +static struct vfsmount *fs_mount;
> +
> +static int fs_mount_cnt;
> +
> +static struct dentry *external_dentry;
> +
> +struct control_commands {
> +	char *cmd;
> +	enum tsem_control_type type;
> +};
> +
> +static struct control_commands commands[9] = {
> +	{"internal", TSEM_CONTROL_INTERNAL},
> +	{"external", TSEM_CONTROL_EXTERNAL},
> +	{"enforce", TSEM_CONTROL_ENFORCE},
> +	{"seal", TSEM_CONTROL_SEAL},
> +	{"trusted ", TSEM_CONTROL_TRUSTED},
> +	{"untrusted ", TSEM_CONTROL_UNTRUSTED},
> +	{"state ", TSEM_CONTROL_MAP_STATE},
> +	{"pseudonym ", TSEM_CONTROL_MAP_PSEUDONYM},
> +	{"base ", TSEM_CONTROL_MAP_BASE}
> +};
> +
> +static bool can_access_fs(void)
> +{
> +	struct tsem_TMA_context *ctx = tsem_context(current);
> +
> +	if (ctx->external)
> +		return false;
> +	if (capable(TSEM_CONTROL_CAPABILITY))
> +		return true;
> +	if (ctx->sealed)
> +		return false;
> +	return true;
> +}
> +
> +static int control_COE(pid_t pid, unsigned long cmd)
> +{
> +	bool wakeup = false;
> +	int retn = -ESRCH;
> +	struct task_struct *COE;
> +	struct tsem_task *task;
> +
> +	rcu_read_lock();
> +	COE = find_task_by_vpid(pid);
> +	if (COE != NULL) {
> +		task = tsem_task(COE);
> +		if (cmd == TSEM_CONTROL_UNTRUSTED)
> +			task->trust_status = TSEM_TASK_UNTRUSTED;
> +		if (cmd == TSEM_CONTROL_TRUSTED) {
> +			task->trust_status &= ~TSEM_TASK_TRUST_PENDING;
> +			if (tsem_task_trusted(COE))
> +				task->trust_status = TSEM_TASK_TRUSTED;
> +		}
> +
> +		retn = 0;
> +		wakeup = true;
> +	}
> +	rcu_read_unlock();
> +
> +	if (wakeup)
> +		wake_up_process(COE);
> +
> +	return retn;
> +}
> +
> +static int config_context(unsigned long cmd, char *bufr)
> +{
> +	int retn = -EINVAL;
> +	unsigned int lp;
> +	struct tsem_TMA_context *ctx = tsem_context(current);
> +
> +	if (ctx->sealed)
> +		return -EPERM;
> +
> +	if (cmd == TSEM_CONTROL_SEAL) {
> +		ctx->sealed = true;
> +		retn = 0;
> +	}
> +
> +	if (cmd == TSEM_CONTROL_ENFORCE) {
> +		for (lp = 0; lp < ARRAY_SIZE(tsem_root_actions); ++lp)
> +			ctx->actions[lp] = TSEM_ACTION_EPERM;
> +		retn = 0;
> +	}
> +
> +	return retn;
> +}
> +
> +static int config_point(enum tsem_control_type type, u8 *arg)
> +{
> +	int retn = -EINVAL;
> +	u8 mapping[WP256_DIGEST_SIZE];
> +
> +	if (*++arg == '\0')
> +		goto done;
> +	if (strlen(arg) != sizeof(mapping) * 2)
> +		goto done;
> +	if (hex2bin(mapping, arg, sizeof(mapping)))
> +		goto done;
> +
> +	if (type == TSEM_CONTROL_MAP_STATE)
> +		retn = tsem_model_load_point(mapping);
> +	else if (type == TSEM_CONTROL_MAP_PSEUDONYM)
> +		retn = tsem_model_load_pseudonym(mapping);
> +	else {
> +		tsem_model_load_base(mapping);
> +		retn = 0;
> +	}
> +
> + done:
> +	return retn;
> +}
> +
> +static void show_event(struct seq_file *c, struct tsem_event *ep, char *file)
> +{
> +	seq_printf(c, "event{process=%s, filename=%s, type=%s, task_id=%*phN}",
> +		   ep->comm, file ? file : "none", tsem_names[ep->event],
> +		   WP256_DIGEST_SIZE, ep->task_id);
> +	seq_printf(c, " COE{uid=%d, euid=%d, suid=%d, gid=%d, egid=%d, sgid=%d, fsuid=%d, fsgid=%d, cap=0x%llx} ",
> +		   ep->COE.uid, ep->COE.euid, ep->COE.suid, ep->COE.gid,
> +		   ep->COE.egid, ep->COE.sgid, ep->COE.fsuid, ep->COE.fsgid,
> +		   ep->COE.capability.value);
> +}

You are printing out a lot of specific data in a specific format that is
documented no where that I can see :(

Also, you are making the same mistake that /proc made decades ago,
creating files that must be parsed and can NEVER be changed in the
future.  Why not make this a one-value-per-file filesystem instead so
that you have flexibility going forward?

> +static void show_file(struct seq_file *c, struct tsem_event *ep)
> +{
> +	seq_printf(c, "file{flags=%u, uid=%d, gid=%d, mode=0%o, name_length=%u, name=%*phN, s_magic=0x%0x, s_id=%s, s_uuid=%*phN, digest=%*phN}\n",
> +		   ep->file.flags, ep->file.uid, ep->file.gid, ep->file.mode,
> +		   ep->file.name_length, WP256_DIGEST_SIZE, ep->file.name,
> +		   ep->file.s_magic, ep->file.s_id,
> +		   (int) sizeof(ep->file.s_uuid), ep->file.s_uuid,
> +		   WP256_DIGEST_SIZE, ep->file.digest);

Same here, where is the documentation for all of this and what userspace
tools parse it?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 02/14] Add TSEM specific documentation.
  2023-02-04  5:09 ` [PATCH 02/14] Add TSEM specific documentation Dr. Greg
@ 2023-02-09 11:47   ` Greg KH
  2023-02-09 23:47     ` Dr. Greg
  2023-02-13  4:33   ` Paul Moore
  1 sibling, 1 reply; 42+ messages in thread
From: Greg KH @ 2023-02-09 11:47 UTC (permalink / raw)
  To: Dr. Greg; +Cc: linux-security-module

On Fri, Feb 03, 2023 at 11:09:42PM -0600, Dr. Greg wrote:
> An entry was added to the ABI testing documentation to document
> the files in the TSEM management filesystem.
> 
> The file documenting the kernel command-line parameters was
> updated to document the tsem_mode command-line parameter.
> 
> The primary TSEM documentation file was added to the LSM
> administration guide and the file was linked to the index of LSM
> documentation.
> 
> Signed-off-by: Greg Wettstein <greg@enjellic.com>
> ---
>  Documentation/ABI/testing/tsemfs              |  576 ++++++++

Ah, here's the documentation, thanks.

>  Documentation/admin-guide/LSM/index.rst       |    1 +
>  Documentation/admin-guide/LSM/tsem.rst        | 1240 +++++++++++++++++
>  .../admin-guide/kernel-parameters.txt         |    5 +
>  4 files changed, 1822 insertions(+)
>  create mode 100644 Documentation/ABI/testing/tsemfs
>  create mode 100644 Documentation/admin-guide/LSM/tsem.rst
> 
> diff --git a/Documentation/ABI/testing/tsemfs b/Documentation/ABI/testing/tsemfs
> new file mode 100644
> index 000000000000..3d326934624c
> --- /dev/null
> +++ b/Documentation/ABI/testing/tsemfs
> @@ -0,0 +1,576 @@
> +What:		/sys/fs/tsem
> +Date:		November 2022

It's not November 2022 anymore :(

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 14/14] Activate the configuration and build of the TSEM LSM.
  2023-02-08 22:15   ` Casey Schaufler
@ 2023-02-09 22:21     ` Dr. Greg
  0 siblings, 0 replies; 42+ messages in thread
From: Dr. Greg @ 2023-02-09 22:21 UTC (permalink / raw)
  To: Casey Schaufler; +Cc: linux-security-module

On Wed, Feb 08, 2023 at 02:15:26PM -0800, Casey Schaufler wrote:
> On 2/3/2023 9:09 PM, Dr. Greg wrote:
> > Complete the implementation by integrating the LSM into the
> > configuration and kernel build infrastructure.
> >
> > Signed-off-by: Greg Wettstein <greg@enjellic.com>
> > ---
> >  security/Kconfig       | 11 ++++++-----
> >  security/Makefile      |  1 +
> >  security/tsem/Kconfig  | 22 ++++++++++++++++++++++
> >  security/tsem/Makefile |  2 ++
> >  4 files changed, 31 insertions(+), 5 deletions(-)
> >  create mode 100644 security/tsem/Kconfig
> >  create mode 100644 security/tsem/Makefile
> >
> > diff --git a/security/Kconfig b/security/Kconfig
> > index e6db09a779b7..98c538ad6790 100644
> > --- a/security/Kconfig
> > +++ b/security/Kconfig
> > @@ -207,6 +207,7 @@ source "security/yama/Kconfig"
> >  source "security/safesetid/Kconfig"
> >  source "security/lockdown/Kconfig"
> >  source "security/landlock/Kconfig"
> > +source "security/tsem/Kconfig"
> >  
> >  source "security/integrity/Kconfig"
> >  
> > @@ -246,11 +247,11 @@ endchoice
> >  
> >  config LSM
> >  	string "Ordered list of enabled LSMs"
> > -	default "landlock,lockdown,yama,loadpin,safesetid,integrity,smack,selinux,tomoyo,apparmor,bpf" if DEFAULT_SECURITY_SMACK
> > -	default "landlock,lockdown,yama,loadpin,safesetid,integrity,apparmor,selinux,smack,tomoyo,bpf" if DEFAULT_SECURITY_APPARMOR
> > -	default "landlock,lockdown,yama,loadpin,safesetid,integrity,tomoyo,bpf" if DEFAULT_SECURITY_TOMOYO
> > -	default "landlock,lockdown,yama,loadpin,safesetid,integrity,bpf" if DEFAULT_SECURITY_DAC
> > -	default "landlock,lockdown,yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor,bpf"
> > +	default "landlock,lockdown,yama,loadpin,safesetid,integrity,smack,selin
ux,tomoyo,apparmor,bpf,tsem" 

Hi Casey, thanks for the note, I hope your week is going well.

> Better check with the BPF team to see if they're OK with TSEM
> following BPF in loading order.

We can do that, however, as we noted in the documentation, TSEM, being
the first LSM to be based on a narratival security logic philosophy,
should be largely ambivalent with respect to its stacking order.

We would thus, happily, entertain suggestions from the community as to
where it would like us to stand in line.

As an example, without going off into the weeds, since TSEM is a
generic security modeling architecture, it can implement any integrity
policies, including validation of extended security attributes.
Placing it first in line would allow a security workload architect to
reject any modifications to expected MAC security labels as an invalid
security model state point before the event got to the deontological
handlers.

However, being the new kid on the block, we would never presume to be
first or last, given that they may be coveted positions.

So we will remain open to suggestions for the second spin of the
patches.

Have a good afternoon.

As always,
Dr. Greg

The Quixote Project - Flailing at the Travails of Cybersecurity

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 02/14] Add TSEM specific documentation.
  2023-02-09 11:47   ` Greg KH
@ 2023-02-09 23:47     ` Dr. Greg
  0 siblings, 0 replies; 42+ messages in thread
From: Dr. Greg @ 2023-02-09 23:47 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-security-module

On Thu, Feb 09, 2023 at 12:47:22PM +0100, Greg KH wrote:
> On Fri, Feb 03, 2023 at 11:09:42PM -0600, Dr. Greg wrote:
> > An entry was added to the ABI testing documentation to document
> > the files in the TSEM management filesystem.
> > 
> > The file documenting the kernel command-line parameters was
> > updated to document the tsem_mode command-line parameter.
> > 
> > The primary TSEM documentation file was added to the LSM
> > administration guide and the file was linked to the index of LSM
> > documentation.
> > 
> > Signed-off-by: Greg Wettstein <greg@enjellic.com>
> > ---
> >  Documentation/ABI/testing/tsemfs              |  576 ++++++++

> Ah, here's the documentation, thanks.

Very good, hopefully it was found to be complete.

I will respond to the control plane filesystem concerns in your
comments in response to the patch that introduces the filesytem.

> > diff --git a/Documentation/ABI/testing/tsemfs b/Documentation/ABI/testing/tsemfs
> > new file mode 100644
> > index 000000000000..3d326934624c
> > --- /dev/null
> > +++ b/Documentation/ABI/testing/tsemfs
> > @@ -0,0 +1,576 @@
> > +What:		/sys/fs/tsem
> > +Date:		November 2022

> It's not November 2022 anymore :(

I know, we will fix all of the 2022 dates in the second spin of the
patchset.

> thanks,
> 
> greg k-h

Have a good evening.

As always,
Dr. Greg

The Quixote Project - Flailing at the Travails of Cybersecurity

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 08/14] Implement TSEM control plane.
  2023-02-09 11:30   ` Greg KH
@ 2023-02-11  0:18     ` Dr. Greg
  2023-02-11 10:59       ` Greg KH
  0 siblings, 1 reply; 42+ messages in thread
From: Dr. Greg @ 2023-02-11  0:18 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-security-module

On Thu, Feb 09, 2023 at 12:30:51PM +0100, Greg KH wrote:

Good afternoon Greg, thanks for taking the time to review the patches
and pass along comments.

> On Fri, Feb 03, 2023 at 11:09:48PM -0600, Dr. Greg wrote:
> > The fs.c file contains the implementation of the TSEM control
> > plane that is in the form of a pseudo-filesystem mounted on the
> > following directory:
> > 
> > /sys/fs/tsem

> Why are you using sysfs to mount this?

We followed the lead of the SMACK and SeLinux LSM's, both of which
create the mount points for their control plane filesystems in
/sys/fs.

In addition, as a filesystem, we chose to have tsemfs closely follow
their design for continuity across the LSM's.  So they share similar
functionality and design, modulo of course, the event description and
trajectory export files that we will chat about below.

We can't use securityfs, secondary to the fact that it doesn't
implement pollable files, which are a requirement for trust
orchestrators based on external Trusted Modeling Agents.

So the question is, where would you like us to put the control plane,
I'm assuming on a mount point created in /sys/kernel/security?

Which would seem to leave the question of why some LSM's put their
control planes in /sys/fs and others elsewhere.

> > The following file documents the interface provided by the
> > control plane:
> > 
> > Documentation/ABI/testing/tsemfs
> > 
> > The pseudo-files act on the modeling context of the process that
> > is acting on the file.  For example, reading the 'id'
> > pseudo-file, returns the modeling domain identifier that the
> > process is running in.
> > 
> > The ExternalTMA directory is used to segreate the pseudo-files
> > that are created in order to surface security event descriptions
> > to an external trust orchestrator.  The files in this directory
> > appear as the numeric value of the modeling domain they were
> > created for.
> > 
> > The 'control' pseudo-file is the only writable file in the plane
> > and is used to control the TSEM implementation.  The most
> > important and primary roles are to create namespaces and set the
> > trust status of a process modeled by an external TMA.
> > 
> > Signed-off-by: Greg Wettstein <greg@enjellic.com>
> > ---
> >  security/tsem/fs.c | 894 +++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 894 insertions(+)
> >  create mode 100644 security/tsem/fs.c
> > 
> > diff --git a/security/tsem/fs.c b/security/tsem/fs.c
> > new file mode 100644
> > index 000000000000..2898a1cc8c97
> > --- /dev/null
> > +++ b/security/tsem/fs.c
> > @@ -0,0 +1,894 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +
> > +/*
> > + * Copyright (C) 2022 Enjellic Systems Development, LLC

> It's 2023 :)

Already fixed... :-)

> > + * Author: Dr. Greg Wettstein <greg@enjellic.com>
> > + *
> > + * Implements the sysfs based control plane.

> This is NOT sysfs, it is your own filesystem, please don't confuse
> the two.

Mea culpa of course, the code now reads; 'Implements the tsemfs based
control plane'.

I think that sysfs tends to fall prey to the 'Kleenex' problem, with
control plane filesystems being generically referred to as 'sysfs'
filesystems, which of course, as you indicate, is technically
incorrect.

> > + */
> > +
> > +#include <linux/seq_file.h>
> > +#include <linux/sysfs.h>
> > +#include <linux/fs_context.h>
> > +#include <linux/namei.h>
> > +#include <linux/poll.h>
> > +#include <uapi/linux/magic.h>
> > +
> > +#include "tsem.h"
> > +
> > +static int fs_init_context(struct fs_context *context);
> > +static int fs_get_tree(struct fs_context *context);
> > +
> > +static struct file_system_type fs_definition = {
> > +	.name = "tsemfs",
> > +	.init_fs_context = fs_init_context,
> > +	.kill_sb = kill_litter_super
> > +};
> > +
> > +static struct fs_context_operations fs_operations = {
> > +	.get_tree = fs_get_tree
> > +};
> > +
> > +static struct vfsmount *fs_mount;
> > +
> > +static int fs_mount_cnt;
> > +
> > +static struct dentry *external_dentry;
> > +
> > +struct control_commands {
> > +	char *cmd;
> > +	enum tsem_control_type type;
> > +};
> > +
> > +static struct control_commands commands[9] = {
> > +	{"internal", TSEM_CONTROL_INTERNAL},
> > +	{"external", TSEM_CONTROL_EXTERNAL},
> > +	{"enforce", TSEM_CONTROL_ENFORCE},
> > +	{"seal", TSEM_CONTROL_SEAL},
> > +	{"trusted ", TSEM_CONTROL_TRUSTED},
> > +	{"untrusted ", TSEM_CONTROL_UNTRUSTED},
> > +	{"state ", TSEM_CONTROL_MAP_STATE},
> > +	{"pseudonym ", TSEM_CONTROL_MAP_PSEUDONYM},
> > +	{"base ", TSEM_CONTROL_MAP_BASE}
> > +};
> > +
> > +static bool can_access_fs(void)
> > +{
> > +	struct tsem_TMA_context *ctx = tsem_context(current);
> > +
> > +	if (ctx->external)
> > +		return false;
> > +	if (capable(TSEM_CONTROL_CAPABILITY))
> > +		return true;
> > +	if (ctx->sealed)
> > +		return false;
> > +	return true;
> > +}
> > +
> > +static int control_COE(pid_t pid, unsigned long cmd)
> > +{
> > +	bool wakeup = false;
> > +	int retn = -ESRCH;
> > +	struct task_struct *COE;
> > +	struct tsem_task *task;
> > +
> > +	rcu_read_lock();
> > +	COE = find_task_by_vpid(pid);
> > +	if (COE != NULL) {
> > +		task = tsem_task(COE);
> > +		if (cmd == TSEM_CONTROL_UNTRUSTED)
> > +			task->trust_status = TSEM_TASK_UNTRUSTED;
> > +		if (cmd == TSEM_CONTROL_TRUSTED) {
> > +			task->trust_status &= ~TSEM_TASK_TRUST_PENDING;
> > +			if (tsem_task_trusted(COE))
> > +				task->trust_status = TSEM_TASK_TRUSTED;
> > +		}
> > +
> > +		retn = 0;
> > +		wakeup = true;
> > +	}
> > +	rcu_read_unlock();
> > +
> > +	if (wakeup)
> > +		wake_up_process(COE);
> > +
> > +	return retn;
> > +}
> > +
> > +static int config_context(unsigned long cmd, char *bufr)
> > +{
> > +	int retn = -EINVAL;
> > +	unsigned int lp;
> > +	struct tsem_TMA_context *ctx = tsem_context(current);
> > +
> > +	if (ctx->sealed)
> > +		return -EPERM;
> > +
> > +	if (cmd == TSEM_CONTROL_SEAL) {
> > +		ctx->sealed = true;
> > +		retn = 0;
> > +	}
> > +
> > +	if (cmd == TSEM_CONTROL_ENFORCE) {
> > +		for (lp = 0; lp < ARRAY_SIZE(tsem_root_actions); ++lp)
> > +			ctx->actions[lp] = TSEM_ACTION_EPERM;
> > +		retn = 0;
> > +	}
> > +
> > +	return retn;
> > +}
> > +
> > +static int config_point(enum tsem_control_type type, u8 *arg)
> > +{
> > +	int retn = -EINVAL;
> > +	u8 mapping[WP256_DIGEST_SIZE];
> > +
> > +	if (*++arg == '\0')
> > +		goto done;
> > +	if (strlen(arg) != sizeof(mapping) * 2)
> > +		goto done;
> > +	if (hex2bin(mapping, arg, sizeof(mapping)))
> > +		goto done;
> > +
> > +	if (type == TSEM_CONTROL_MAP_STATE)
> > +		retn = tsem_model_load_point(mapping);
> > +	else if (type == TSEM_CONTROL_MAP_PSEUDONYM)
> > +		retn = tsem_model_load_pseudonym(mapping);
> > +	else {
> > +		tsem_model_load_base(mapping);
> > +		retn = 0;
> > +	}
> > +
> > + done:
> > +	return retn;
> > +}
> > +
> > +static void show_event(struct seq_file *c, struct tsem_event *ep, char *file)
> > +{
> > +	seq_printf(c, "event{process=%s, filename=%s, type=%s, task_id=%*phN}",
> > +		   ep->comm, file ? file : "none", tsem_names[ep->event],
> > +		   WP256_DIGEST_SIZE, ep->task_id);
> > +	seq_printf(c, " COE{uid=%d, euid=%d, suid=%d, gid=%d, egid=%d, sgid=%d, fsuid=%d, fsgid=%d, cap=0x%llx} ",
> > +		   ep->COE.uid, ep->COE.euid, ep->COE.suid, ep->COE.gid,
> > +		   ep->COE.egid, ep->COE.sgid, ep->COE.fsuid, ep->COE.fsgid,
> > +		   ep->COE.capability.value);
> > +}

> You are printing out a lot of specific data in a specific format
> that is documented no where that I can see :(

It appears you found the ABI documentation in the second patch that
was posted in the series, hopefully it was found to be complete, we
are currently in 13th position out of 494 files with respect to
quantity of ABI documentation... :-)

For the sake of 'lore':

After applying the patch series, the control plane API is documented in the
following file:

Documentation/ABI/testing/tsemfs

The TSEM LSM documentation proper will be in the following file:

Documentation/admin-guide/LSM/tsem.rst

Where we currently hold the poll position.

> Also, you are making the same mistake that /proc made decades ago,
> creating files that must be parsed and can NEVER be changed in the
> future.  Why not make this a one-value-per-file filesystem instead
> so that you have flexibility going forward?

Personally, I've been working on Linux since late 1991, so we, as a
team, are well aware, and sensitive, to the issues and discussions
surrounding the file formatting decisions that were made with the
/proc filesystem.  So we did not make the decision with respect to
formatted output lightly.

In fact, I presumed that the top two things we would hear about with
respect to TSEM, would be about the introduction of CAP_TRUST from
Casey and the format of the event export and execution trajectory
files from you.

The issue is that the kernel needs to present to trust orchestrators,
a description of each LSM security hook, in the form of an atomic
update or transaction.

To help clarify the discussion, here are examples of records that are
output for a file_open and socket_bind hook event:

pid{1186} event{process=quixote-us, filename=/opt/Quixote/bin/runc, type=file_open, task_id=0000000000000000000000000000000000000000000000000000000000000000} COE{uid=0, euid=0, suid=0, gid=0, egid=0, sgid=0, fsuid=0, fsgid=0, cap=0x3ffffffffff} file{flags=32800, uid=2, gid=2, mode=0100755, name_length=21, name=4829ead93d026770746f9cdebc76cc4d2a27f45db2d3ac436aa6fce4e2640415, s_magic=0xef53, s_id=xvda, s_uuid=feadbeaffeadbeaffeadbeaffeadbeaf, digest=7c1a43eb99fa739056d6554001d450ca1c9c184ca7e2d8a785bd1e5fd53bad8c}

pid{1204} event{process=ncat, filename=none, type=socket_bind, task_id=a5bc0eb22141657132f29e80ca6ea9b211e8443ead1f4b6b766935a14995040f} COE{uid=0, euid=0, suid=0, gid=0, egid=0, sgid=0, fsuid=0, fsgid=0, cap=0x20000420} socket_bind{family=2, port=28695, addr=0}

TSEM is currently modeling 84 LSM hooks.  We would certainly be open
to suggestions as to how we would architect the one-value-per-file
filesystem model in a manner that would scale, both with respect to
pseudo-filesystem complexity and system call overhead.

> > +static void show_file(struct seq_file *c, struct tsem_event *ep)
> > +{
> > +	seq_printf(c, "file{flags=%u, uid=%d, gid=%d, mode=0%o, name_length=%u, name=%*phN, s_magic=0x%0x, s_id=%s, s_uuid=%*phN, digest=%*phN}\n",
> > +		   ep->file.flags, ep->file.uid, ep->file.gid, ep->file.mode,
> > +		   ep->file.name_length, WP256_DIGEST_SIZE, ep->file.name,
> > +		   ep->file.s_magic, ep->file.s_id,
> > +		   (int) sizeof(ep->file.s_uuid), ep->file.s_uuid,
> > +		   WP256_DIGEST_SIZE, ep->file.digest);

> Same here, where is the documentation for all of this and what
> userspace tools parse it?

We will presume the documentation issue to be addressed.

The cover letter for the patch series, and the LSM documentation
itself, has the URL for the directory on our FTP server that has the
source code for the Quixote trust orchestration system as well as
compiled trust orchestration utilities and an SGX enclave, a Xen
stubdomain executable and micro-controller firmware for the SanchoSGX,
SachoXen and SanchoMCU implementations.

More specifically, the following URL's will, at the time of this
writing, February 2023... :-), pull the source and binaries:

ftp://ftp.enjellic.com/pub/Quixote/Quixote-1.4.tar.gz

ftp://ftp.enjellic.com/pub/Quixote/Quixote-1.4-1.x86_64.rpm

ftp://ftp.enjellic.com/pub/Quixote/quixote_1.4-2_amd64.deb

For some reason 'alien' bumps the release number when it creates the
.deb from the rpm.... :-(

After unpacking the source archive, the code that handles the parsing
of an exported security event description will be found in the
following files:

SecurityModel/EventParser.c

SecurityModel/SecurityEvent.c

SecurityModel/COE.c

SecurityModel/Cell.c

The formatted output was designed to be self-descriptive, extensible
and extremely low cost to parse, without the use of an external
library.  The same codebase runs in everything from a userspace
process, to a Xen stubdomin, through an SGX enclave and multiple
32-bit ARM micro-controller implementations.

The trust orchestration utilities that use the above code, and
implement drivers for the various Sancho trust roots, are in the
'Quixote' directory in the source tree.

> thanks,
> 
> greg k-h

As I indicated above, we are all ears if someone has a better idea on
how to handle the security event description export issue.

Have a good weekend.

As always,
Dr. Greg

The Quixote Project - Flailing at the Travails of Cybersecurity

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 04/14] Implement CAP_TRUST capability.
  2023-02-06 17:28   ` Serge Hallyn (shallyn)
@ 2023-02-11  0:32     ` Dr. Greg
  0 siblings, 0 replies; 42+ messages in thread
From: Dr. Greg @ 2023-02-11  0:32 UTC (permalink / raw)
  To: Serge Hallyn (shallyn); +Cc: linux-security-module

On Mon, Feb 06, 2023 at 05:28:06PM +0000, Serge Hallyn (shallyn) wrote:
> On Fri, Feb 03, 2023 at 11:09:44PM -0600, Dr. Greg wrote:
> > TSEM was designed to support a Trust Orchestration System (TOS)
> > security architecture.  A TOS based system uses the concept of a
> > minimum Trusted Computing Base of utilities, referred to as trust
> > orchestrators, that maintain workloads in a trusted execution
> > state.  The trust orchestrators are thus, from a security
> > perspective, the most privileged assets on the platform.
> > 
> > Introduce the CAP_TRUST capability that is defined as a
> > capability that allows a process to alter the trust status of the

> This sounds like CAP_MAC_ADMIN.  Any reason not to re-use that?

Hi Serge, thanks for passing along the question.

Casey raised the same issue, will respond in more detail in a reply to
his e-mail.

Have a good weekend.

As always,
Dr. Greg

The Quixote Project - Flailing at the Travails of Cybersecurity

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 08/14] Implement TSEM control plane.
  2023-02-11  0:18     ` Dr. Greg
@ 2023-02-11 10:59       ` Greg KH
  2023-02-12  6:54         ` Dr. Greg
  0 siblings, 1 reply; 42+ messages in thread
From: Greg KH @ 2023-02-11 10:59 UTC (permalink / raw)
  To: Dr. Greg; +Cc: linux-security-module

On Fri, Feb 10, 2023 at 06:18:06PM -0600, Dr. Greg wrote:
> On Thu, Feb 09, 2023 at 12:30:51PM +0100, Greg KH wrote:
> 
> Good afternoon Greg, thanks for taking the time to review the patches
> and pass along comments.
> 
> > On Fri, Feb 03, 2023 at 11:09:48PM -0600, Dr. Greg wrote:
> > > The fs.c file contains the implementation of the TSEM control
> > > plane that is in the form of a pseudo-filesystem mounted on the
> > > following directory:
> > > 
> > > /sys/fs/tsem
> 
> > Why are you using sysfs to mount this?
> 
> We followed the lead of the SMACK and SeLinux LSM's, both of which
> create the mount points for their control plane filesystems in
> /sys/fs.
> 
> In addition, as a filesystem, we chose to have tsemfs closely follow
> their design for continuity across the LSM's.  So they share similar
> functionality and design, modulo of course, the event description and
> trajectory export files that we will chat about below.
> 
> We can't use securityfs, secondary to the fact that it doesn't
> implement pollable files, which are a requirement for trust
> orchestrators based on external Trusted Modeling Agents.

Why not fix securityfs to provide pollable files?  Other than that, why
can't you just use securityfs?

> > > +static void show_event(struct seq_file *c, struct tsem_event *ep, char *file)
> > > +{
> > > +	seq_printf(c, "event{process=%s, filename=%s, type=%s, task_id=%*phN}",
> > > +		   ep->comm, file ? file : "none", tsem_names[ep->event],
> > > +		   WP256_DIGEST_SIZE, ep->task_id);
> > > +	seq_printf(c, " COE{uid=%d, euid=%d, suid=%d, gid=%d, egid=%d, sgid=%d, fsuid=%d, fsgid=%d, cap=0x%llx} ",
> > > +		   ep->COE.uid, ep->COE.euid, ep->COE.suid, ep->COE.gid,
> > > +		   ep->COE.egid, ep->COE.sgid, ep->COE.fsuid, ep->COE.fsgid,
> > > +		   ep->COE.capability.value);
> > > +}
> 
> > You are printing out a lot of specific data in a specific format
> > that is documented no where that I can see :(
> 
> It appears you found the ABI documentation in the second patch that
> was posted in the series, hopefully it was found to be complete, we
> are currently in 13th position out of 494 files with respect to
> quantity of ABI documentation... :-)
> 
> For the sake of 'lore':
> 
> After applying the patch series, the control plane API is documented in the
> following file:
> 
> Documentation/ABI/testing/tsemfs
> 
> The TSEM LSM documentation proper will be in the following file:
> 
> Documentation/admin-guide/LSM/tsem.rst
> 
> Where we currently hold the poll position.
> 
> > Also, you are making the same mistake that /proc made decades ago,
> > creating files that must be parsed and can NEVER be changed in the
> > future.  Why not make this a one-value-per-file filesystem instead
> > so that you have flexibility going forward?
> 
> Personally, I've been working on Linux since late 1991, so we, as a
> team, are well aware, and sensitive, to the issues and discussions
> surrounding the file formatting decisions that were made with the
> /proc filesystem.  So we did not make the decision with respect to
> formatted output lightly.
> 
> In fact, I presumed that the top two things we would hear about with
> respect to TSEM, would be about the introduction of CAP_TRUST from
> Casey and the format of the event export and execution trajectory
> files from you.
> 
> The issue is that the kernel needs to present to trust orchestrators,
> a description of each LSM security hook, in the form of an atomic
> update or transaction.
> 
> To help clarify the discussion, here are examples of records that are
> output for a file_open and socket_bind hook event:
> 
> pid{1186} event{process=quixote-us, filename=/opt/Quixote/bin/runc, type=file_open, task_id=0000000000000000000000000000000000000000000000000000000000000000} COE{uid=0, euid=0, suid=0, gid=0, egid=0, sgid=0, fsuid=0, fsgid=0, cap=0x3ffffffffff} file{flags=32800, uid=2, gid=2, mode=0100755, name_length=21, name=4829ead93d026770746f9cdebc76cc4d2a27f45db2d3ac436aa6fce4e2640415, s_magic=0xef53, s_id=xvda, s_uuid=feadbeaffeadbeaffeadbeaffeadbeaf, digest=7c1a43eb99fa739056d6554001d450ca1c9c184ca7e2d8a785bd1e5fd53bad8c}
> 
> pid{1204} event{process=ncat, filename=none, type=socket_bind, task_id=a5bc0eb22141657132f29e80ca6ea9b211e8443ead1f4b6b766935a14995040f} COE{uid=0, euid=0, suid=0, gid=0, egid=0, sgid=0, fsuid=0, fsgid=0, cap=0x20000420} socket_bind{family=2, port=28695, addr=0}
> 
> TSEM is currently modeling 84 LSM hooks.  We would certainly be open
> to suggestions as to how we would architect the one-value-per-file
> filesystem model in a manner that would scale, both with respect to
> pseudo-filesystem complexity and system call overhead.

You are creating a new structure-type-api here, why not use a
already-designed protocol instead like varlink if you need userspace to
parse events in an atomic way?  Or heck even json would be better as
there are universal userspace tools for that today.

Or use the audit interface, this feels very close to that, why not just
tie into that subsystem instead?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 08/14] Implement TSEM control plane.
  2023-02-11 10:59       ` Greg KH
@ 2023-02-12  6:54         ` Dr. Greg
  2023-02-16  6:53           ` Greg KH
  0 siblings, 1 reply; 42+ messages in thread
From: Dr. Greg @ 2023-02-12  6:54 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-security-module, paul

On Sat, Feb 11, 2023 at 11:59:19AM +0100, Greg KH wrote:

Looping in Paul Moore in order to get his thoughts.

> On Fri, Feb 10, 2023 at 06:18:06PM -0600, Dr. Greg wrote:
> > On Thu, Feb 09, 2023 at 12:30:51PM +0100, Greg KH wrote:
> > 
> > Good afternoon Greg, thanks for taking the time to review the patches
> > and pass along comments.
> > 
> > > On Fri, Feb 03, 2023 at 11:09:48PM -0600, Dr. Greg wrote:
> > > > The fs.c file contains the implementation of the TSEM control
> > > > plane that is in the form of a pseudo-filesystem mounted on the
> > > > following directory:
> > > > 
> > > > /sys/fs/tsem
> > 
> > > Why are you using sysfs to mount this?

> > We followed the lead of the SMACK and SeLinux LSM's, both of which
> > create the mount points for their control plane filesystems in
> > /sys/fs.
> > 
> > In addition, as a filesystem, we chose to have tsemfs closely follow
> > their design for continuity across the LSM's.  So they share similar
> > functionality and design, modulo of course, the event description and
> > trajectory export files that we will chat about below.
> > 
> > We can't use securityfs, secondary to the fact that it doesn't
> > implement pollable files, which are a requirement for trust
> > orchestrators based on external Trusted Modeling Agents.

> Why not fix securityfs to provide pollable files?  Other than that,
> why can't you just use securityfs?

Now that we have had some additional bandwidth to look at issues after
the first round release, it may be more straight forward to implement
the pollable files in securityfs than we thought.  We will take
another run at this and see what is possible without having to meddle
with the internals of securityfs proper.

As the diffstat for the patch series indicates, we spent considerable
time working to implement TSEM without touching anything outside its
implementation directory.  I think this is something that anyone who
has tried to upstream functionality into the mainline kernel would
understand the merit of.

Paul, I know you are busy, but if you can, weigh in briefly with any
thoughts you may have on where we put the control plane so we can
optimize everyone's time with the second spin of the patch set.

> > > > +static void show_event(struct seq_file *c, struct tsem_event *ep, char *file)
> > > > +{
> > > > +	seq_printf(c, "event{process=%s, filename=%s, type=%s, task_id=%*phN}",
> > > > +		   ep->comm, file ? file : "none", tsem_names[ep->event],
> > > > +		   WP256_DIGEST_SIZE, ep->task_id);
> > > > +	seq_printf(c, " COE{uid=%d, euid=%d, suid=%d, gid=%d, egid=%d, sgid=%d, fsuid=%d, fsgid=%d, cap=0x%llx} ",
> > > > +		   ep->COE.uid, ep->COE.euid, ep->COE.suid, ep->COE.gid,
> > > > +		   ep->COE.egid, ep->COE.sgid, ep->COE.fsuid, ep->COE.fsgid,
> > > > +		   ep->COE.capability.value);
> > > > +}
> > 
> > > You are printing out a lot of specific data in a specific format
> > > that is documented no where that I can see :(
> > 
> > It appears you found the ABI documentation in the second patch that
> > was posted in the series, hopefully it was found to be complete, we
> > are currently in 13th position out of 494 files with respect to
> > quantity of ABI documentation... :-)
> > 
> > For the sake of 'lore':
> > 
> > After applying the patch series, the control plane API is documented in the
> > following file:
> > 
> > Documentation/ABI/testing/tsemfs
> > 
> > The TSEM LSM documentation proper will be in the following file:
> > 
> > Documentation/admin-guide/LSM/tsem.rst
> > 
> > Where we currently hold the poll position.
> > 
> > > Also, you are making the same mistake that /proc made decades ago,
> > > creating files that must be parsed and can NEVER be changed in the
> > > future.  Why not make this a one-value-per-file filesystem instead
> > > so that you have flexibility going forward?
> > 
> > Personally, I've been working on Linux since late 1991, so we, as a
> > team, are well aware, and sensitive, to the issues and discussions
> > surrounding the file formatting decisions that were made with the
> > /proc filesystem.  So we did not make the decision with respect to
> > formatted output lightly.
> > 
> > In fact, I presumed that the top two things we would hear about with
> > respect to TSEM, would be about the introduction of CAP_TRUST from
> > Casey and the format of the event export and execution trajectory
> > files from you.
> > 
> > The issue is that the kernel needs to present to trust orchestrators,
> > a description of each LSM security hook, in the form of an atomic
> > update or transaction.
> > 
> > To help clarify the discussion, here are examples of records that are
> > output for a file_open and socket_bind hook event:
> > 
> > pid{1186} event{process=quixote-us, filename=/opt/Quixote/bin/runc, type=file_open, task_id=0000000000000000000000000000000000000000000000000000000000000000} COE{uid=0, euid=0, suid=0, gid=0, egid=0, sgid=0, fsuid=0, fsgid=0, cap=0x3ffffffffff} file{flags=32800, uid=2, gid=2, mode=0100755, name_length=21, name=4829ead93d026770746f9cdebc76cc4d2a27f45db2d3ac436aa6fce4e2640415, s_magic=0xef53, s_id=xvda, s_uuid=feadbeaffeadbeaffeadbeaffeadbeaf, digest=7c1a43eb99fa739056d6554001d450ca1c9c184ca7e2d8a785bd1e5fd53bad8c}
> > 
> > pid{1204} event{process=ncat, filename=none, type=socket_bind, task_id=a5bc0eb22141657132f29e80ca6ea9b211e8443ead1f4b6b766935a14995040f} COE{uid=0, euid=0, suid=0, gid=0, egid=0, sgid=0, fsuid=0, fsgid=0, cap=0x20000420} socket_bind{family=2, port=28695, addr=0}
> > 
> > TSEM is currently modeling 84 LSM hooks.  We would certainly be open
> > to suggestions as to how we would architect the one-value-per-file
> > filesystem model in a manner that would scale, both with respect to
> > pseudo-filesystem complexity and system call overhead.

> You are creating a new structure-type-api here, why not use a
> already-designed protocol instead like varlink if you need userspace
> to parse events in an atomic way?  Or heck even json would be better
> as there are universal userspace tools for that today.

As an industry, we are in the middle of a software supply chain
security crisis.  In a trust orchestrated architecture, the trust
orchestrators, and their Sancho TMA implementations, are the most
security critical components on the system.  Our objective is to keep
the supply chain footprint for Quixote as small as possible.

To that point:

size /usr/local/lib/libyajl.so.2.1.1:
   text    data     bss     dec     hex filename
  33333     784      16   34133    8555 /usr/local/lib/libyajl.so.2.1.1

size /u/usr/sources/quixote-1.4/SecurityModel/EventParser.o
   text    data     bss     dec     hex filename
   2520       0       0    2520     9d8 /u/usr/sources/quixote-1.4/SecurityModel/EventParser.o

If we were to use JSON, we would use yajl, it is probably as light as
anything out there.  Given that, on face value, this would represent
over an order of magnitude increase in code size to achieve the same
objective, plus add an external dependency.

We can't claim to have dealt with varlink very much, but that actually
may make sense, down the road, given that TSEM can be conceptualized
as being about advertising resources that a client application needs
to provide a security service to the kernel.

Hopefully our concerns about software dependency issues make sense,
given the context that we wrote, and released, as part of Quixote, a
complete SGX Platform Software Implementation in order to avoid
exposing the SanchoSGX implementation to the 20+ shared library
dependencies that come with the Intel SGX software stack.

> Or use the audit interface, this feels very close to that, why not
> just tie into that subsystem instead?

I'm not sure the audit system is a good fit for all of this, but I
will defer to Paul on that, given that he stewards over audit as well
as the security sub-system.

So, I was doing some thinking, while I was cross-country skiing for
about 10 miles across what the weather service is calling the glacial
icepack that is currently covering our wheat and soybean fields out
here in eastern North Dakota.

How about this for an idea, why don't we let the trust orchestrators
select the output format for the security event description interfaces?

We can start with the format that we are currently using and then add
things like varlink or other alternatives down the road.  That allows
different trust orchestration implementations to select what they feel
is the most desirable output format and doesn't lock the kernel into a
specific ABI format until we are actually covered by the next ice age.

Unless I miss my guess, in 25 years, if we have a reunion of trust
orchestration architectects, it will be pretty cheap to buy a round of
drinks, even if everyone is drinking 25 year old McAllen.

Paul, thoughts, given that if we move this to securityfs it will be
completely in your domain?

> thanks,
> 
> greg k-h

Have a good remainder of the weekend.

As always,
Dr. Greg

The Quixote Project - Flailing at the Travails of Cybersecurity

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 02/14] Add TSEM specific documentation.
  2023-02-04  5:09 ` [PATCH 02/14] Add TSEM specific documentation Dr. Greg
  2023-02-09 11:47   ` Greg KH
@ 2023-02-13  4:33   ` Paul Moore
  2023-02-14 11:58     ` Dr. Greg
  1 sibling, 1 reply; 42+ messages in thread
From: Paul Moore @ 2023-02-13  4:33 UTC (permalink / raw)
  To: Dr. Greg; +Cc: linux-security-module

On Sat, Feb 4, 2023 at 12:33 AM Dr. Greg <greg@enjellic.com> wrote:
>
> An entry was added to the ABI testing documentation to document
> the files in the TSEM management filesystem.
>
> The file documenting the kernel command-line parameters was
> updated to document the tsem_mode command-line parameter.
>
> The primary TSEM documentation file was added to the LSM
> administration guide and the file was linked to the index of LSM
> documentation.
>
> Signed-off-by: Greg Wettstein <greg@enjellic.com>
> ---
>  Documentation/ABI/testing/tsemfs              |  576 ++++++++
>  Documentation/admin-guide/LSM/index.rst       |    1 +
>  Documentation/admin-guide/LSM/tsem.rst        | 1240 +++++++++++++++++
>  .../admin-guide/kernel-parameters.txt         |    5 +
>  4 files changed, 1822 insertions(+)
>  create mode 100644 Documentation/ABI/testing/tsemfs
>  create mode 100644 Documentation/admin-guide/LSM/tsem.rst

One of the more important requirements for any new LSM is that it
documents a clear, understandable, and reasonable security model along
with an implementation that faithfully implements that model.  Before
I looked at your code I wanted to try and understand the TSEM security
model and a few things jumped out at me rather quickly, I imagine
there would be others as I start to look a bit closer but I wanted to
send these questions/comments along now to get your take on them ...

> diff --git a/Documentation/ABI/testing/tsemfs b/Documentation/ABI/testing/tsemfs
> new file mode 100644
> index 000000000000..3d326934624c
> --- /dev/null
> +++ b/Documentation/ABI/testing/tsemfs
> @@ -0,0 +1,576 @@

...

> +What:          /sys/fs/tsem/aggregate
> +Date:          November 2022
> +Contact:       Greg Wettstein <greg@enjellic.com>
> +Description:
> +               The aggregate file contains the ASCII base 16
> +               representation of the 256 bit hardware platform
> +               aggregate that TSEM is modeling under.  The platform
> +               aggregate is the extension measurement of the Trusted
> +               Platform Module PCR registers 0 through 8.

I'm guessing the above is a typo and you mean PCRs 0 through 7 (not
8)?  If not, you need to provide an explanation somewhere as to what
you are using PCR 8 for in TSEM and how it is extended, etc.

> +What:          /sys/fs/tsem/measurement
> +Date:          November 2022
> +Contact:       Greg Wettstein <greg@enjellic.com>
> +Description:
> +               The measurement file contains the ASCII base 16
> +               hexadecimal representation of the 256 bit measurement
> +               value of the security model that the process is
> +               operating in.
> +
> +               The measurement value is the classic linear extension
> +               measurement of the model.  An updated measurement
> +               value is created by extending the current measurement
> +               value with the state coefficient computed for a
> +               security event.
> +
> +               This measurement value represents a time dependent
> +               measurement of a model and is susceptible to
> +               deviations caused by scheduling differences between
> +               subsequent invocations of a workload.

Given the very volatile nature of this value, what is it used for in
userspace?  My apologies if I missed it in the docs.

> +What:          /sys/fs/tsem/points
> +Date:          November 2022
> +Contact:       Greg Wettstein <greg@enjellic.com>
> +Description:
> +               The points file contains the ASCII base 16
> +               representation of the 256 bit security state points of
> +               a security domain/model.  The number of entries in
> +               this file represent the number of security events that
> +               are represented by the model.

A similar questions to the tsem/measurement file.  If I understand you
correctly, this is basically a series of SHA256 digests without any
additional annotations, and without any ordering guarantees, yes?
What is it used for in userspace?

> +What:          /sys/fs/tsem/state
> +Date:          November 2022
> +Contact:       Greg Wettstein <greg@enjellic.com>
> +Description:
> +               The state file contains the ASCII base 16
> +               representation of the 256 bit value of the functional
> +               state of a security domain/model.
> +
> +               The state value is a time independent representation
> +               of the measurement of a model/domain, and unlike the
> +               measurement value, is a time independent
> +               representation of the security state of a workload.
> +
> +               This value is designed to be a single value that can
> +               be attested to represent whether or not a workload has
> +               deviated from a defined security behavior.

It might be nice to explain how this value is calculated here in this
file to remove any time or ordering dependencies.  Once again my
apologies if I missed it in the rest of the docs.

> +What:          /sys/fs/tsem/trajectory
> +Date:          November 2022
> +Contact:       Greg Wettstein <greg@enjellic.com>
> +Description:
> +               The trajectory file contains a description of the
> +               security events that have occurred in a security
> +               domain/model.
> +
> +               Each entry in this file represents a single security
> +               event and consists of brace {} delimited fields that
> +               describe the characteristics of a security event.
> +               Each field has key=value pairs that define
> +               characteristics of the field.
> +
> +               Each line in a trajectory, or forensics, file will
> +               always have the event{} and COE{} fields.  The event
> +               field describes the characteristics of a security
> +               event while the COE field describes the Context Of
> +               Execution that is executing the security event.

I think it would be good to provide a concrete definition of
CELL_DEFINITION field as other areas of the documentation make
reference to it within the tsem/trajectory file documentation.  We can
somewhat infer it's format, fields, etc. but it's much better to be
explicit about these things.

> +               The event{} field consists of the following
> +               characteristic definitions:

I'm unclear as to the purpose of the event{} field as it is neither
part of the COE or the CELL, is it here simply to make the event
easier to read?  Or am I misunderstanding things and the event{} field
is part of the COE?

> +                       process=COMM
> +                               Where COMM is the ASCII representation
> +                               of the name of the process executing
> +                               the event.
> +
> +                       filename=PATH
> +                               If the CELL definition for an event
> +                               references a file the filename
> +                               characteristic contains a definition
> +                               of the path to the file.
> +
> +                               In the case where an event does not
> +                               have a file the PATH value is set to a
> +                               value of none.

What happens in cases where multiple file paths are present in an
event?  Also, given this is visible to userspace, and multiple things
can affect the path to a file (e.g. namespaces), how is the file path
determined?

> +                       type=EVENT_TYPE
> +                               The value field for a type key is the
> +                               name of the security event that is
> +                               being modeled.  The list of value
> +                               EVENT_TYPE names is defined in the
> +                               following source file:
> +
> +                               security/tsem/tsem.c
> +
> +                               If the security event is a generically
> +                               modeled event the EVENT_TYPE will be
> +                               generic_event.  In this case the CELL
> +                               characteristics for the event will be
> +                               described by a generic_event{} field.
> +
> +                       task_id=TASK_ID
> +                               The value of the task_id key will the
> +                               ASCII base 16 representation of the
> +                               model identity of the task that is
> +                               executing the security event.
> +
> +                               The following documentation file:
> +
> +                               Documentation/admin-guide/LSM/TSEM.rst
> +
> +                               Describes how the TASK_ID value is
> +                               generated.
> +
> +               The COE{} field consists of the following
> +               characteristic definitions:
> +
> +                       uid=NN
> +                               The ASCII base 10 representation of
> +                               the numeric value of the discretionary
> +                               user id of the process that is
> +                               executing the security event.

Given the ability to map UID/GID values in the kernel, what will be
used as the basis for the COE?  What happens when the basis used in
the kernel's COE generation does not match the basis used by the
external modeler?

> +                       euid=NN
> +                               The ASCII base 10 representation of
> +                               the numeric value of the effective
> +                               discretionary user id of the process
> +                               that is executing the security event.
> +
> +                       euid=NN
> +                               The ASCII base 10 representation of
> +                               the numeric value of the effective
> +                               discretionary user id of the process
> +                               that is executing the security event.
> +
> +                       suid=NN
> +                               The ASCII base 10 representation of
> +                               the numeric value of the saved user id
> +                               of the process that is executing the
> +                               security event.
> +
> +                       gid=NN
> +                               The ASCII base 10 representation of
> +                               the numeric value of the discretionary
> +                               group id of the process that is
> +                               executing the security event.
> +
> +                       egid=NN
> +                               The ASCII base 10 representation of
> +                               the numeric value of the discretionary
> +                               effective group id of the process that
> +                               is executing the security event.
> +
> +                       egid=NN
> +                               The ASCII base 10 representation of
> +                               the numeric value of the discretionary
> +                               effective group id of the process that
> +                               is executing the security event.
> +
> +                       sgid=NN
> +                               The base 10 ASCII representation of
> +                               the numeric value of the saved
> +                               discretionary group id of the process
> +                               that is executing the security event.
> +
> +                       fsuid=NN
> +                               The base 10 ASCII representation of
> +                               the numeric value of the discretionary
> +                               filesystem user id of the process that
> +                               is executing the security event.
> +
> +                       fsgid=NN
> +                               The ASCII base 10 representation of
> +                               the numeric value of the discretionary
> +                               filesystem group id of the process
> +                               that is executing the security event.
> +
> +                       cap=0xNNN
> +                               The ASCII base 16 representation of
> +                               the numeric value of effective
> +                               capabilities of the process that is
> +                               executing the security event.
> +
> +               If the CELL value for a security event includes the
> +               definition of a file a file{} event field will be
> +               included.  The following characteristics will be
> +               encoded in this field:
> +
> +                       flags=NN
> +                               The ASCII base 10 representation of
> +                               the flags value of the 'struct file'
> +                               structure that is the source of the
> +                               file description.
> +
> +                       uid=NN
> +                               The ASCII base 10 representation of
> +                               the discretionary user id of the file.
> +
> +                       gid=NN
> +                               The base 10 ASCII representation of
> +                               the discretionary group id of the
> +                               file.

Similar to the task UID/GID mapping questions above, there are
mechanisms which map the file user/group IDs, which will be used in
the CELL definition and how will that be resolved between the kernel
and an external modeler?

> +What:          /sys/fs/tsem/ExternalTMA
> +Date:          November 2022
> +Contact:       Greg Wettstein <greg@enjellic.com>
> +Description:
> +               The ExternalTMA directory is a container directory
> +               that hold files that will be used to export the
> +               security events, and their associated parameters, for
> +               externally modeled security domains/namespaces.
> +
> +               The files created in this directory will be named by
> +               the base 10 ASCII representation of the id value
> +               assigned to the modeling domain/namespace.  See the
> +               documentation for the /sys/fs/tsem/id file in this
> +               documentation for more details on this value.
> +
> +               This file will is a read-only file that can be polled
> +               by a userspace trust orchestration implementation to
> +               process security events that are to be modeled by
> +               an external Trusted Modeling Agent.
> +
> +               The type of the exported event is the first keyword of
> +               the line that is output and have the following
> +               values and arguments:
> +
> +               aggregate HEXID:
> +                       Where HEXID is the ASCII base 16
> +                       representation of the 256 bit hardware
> +                       platform aggregate value.
> +
> +               export pid{NNN} COE{} CELL_DEFINITION
> +                       Where the NNN in the pid field is the ASCII
> +                       base 10 value of the id of the process that is
> +                       executing the security event that will be
> +                       modeled.

I worry whenever I see a PID used as an identifier shared across the
kernel/userspace boundary as it is inherently racy.  Given the
somewhat coarse COE definition where one can expect multiple
processes/PIDs to share the same COE value, and the ability of
untrusted users/processes to manipulate the PID table, what do you
expect to use the pid{NNN} field for in this event?

Similar to the other namespace/mapping issues discussed previously,
there is also the PID namespace issue to worry about.  How is that
handled here?

> +                       The COE field has the same format as the field
> +                       emitted for a trajectory or forensics event.
> +
> +                       The CELL_DEFINITION are the same field
> +                       definitions that are emitted for a trajectory
> +                       or forensics event.
> +
> +               log process{name} event{type} action{type}
> +                       The log event is emitted when an untrusted
> +                       task attempts to execute a security event.
> +
> +                       The name value of the COE field is the name of
> +                       the process (comm value) that is executing the
> +                       security event.
> +
> +                       The type value of the event field is the name
> +                       of the security event being executed as
> +                       defined in the tsem_names array in the
> +                       security/tsem/tsem.c file.
> +
> +                       The type value of the action field is the type
> +                       of action the LSM enforced in response to
> +                       encountering the untrusted process.  This
> +                       value will be either LOG or EPERM to represent
> +                       whether or not the trust violation is being
> +                       logged or enforced.
> +
> +What:          /sys/fs/tsem/control
> +Date:          November 2022
> +Contact:       Greg Wettstein <greg@enjellic.com>
> +Description:
> +               The control file is the only writable file in the
> +               filesystem and is used by the trust orchestrators to
> +               configure and control the behavior of the TSEM
> +               implementation.
> +
> +               The following keyword and arguments are recognized:
> +
> +               internal:
> +                       The internal keyword causes an internally
> +                       modeled domain to be created for the calling
> +                       process.
> +
> +               external:
> +                       The external keyword causes an externally
> +                       modeled domain to be created for the calling
> +                       process.
> +
> +               enforce:
> +                       The enforce keyword causes the modeling
> +                       domain/namespace of the process to enter
> +                       enforcing mode.  In this mode a value of
> +                       -EPERM will be returned for a security event
> +                       that does not map into the current set of
> +                       allowed state points for the security model
> +                       being implemented for the domain/namespace.
> +
> +               seal:
> +                       The seal keyword causes the security model
> +                       being implemented for the model to be placed
> +                       in sealed state.  In this state the current
> +                       set of security event points is considered to
> +                       be the only set of valid points for the
> +                       domain/model.  Any subsequent events that map
> +                       to a point not in the current model will be
> +                       considered a violation of the model.
> +
> +               trusted PID:
> +                       The trusted keyword is used by a trust
> +                       orchestrator to indicate that the process
> +                       identified by the PID argument should be
> +                       allowed to run in trusted status.
> +
> +               untrusted PID:
> +                       The untrusted keyword is used by a trust
> +                       orchestrator to indicate that the process
> +                       identified by the PID argument should be
> +                       allowed to run but designated as an untrusted
> +                       process.

The 'trusted PID:' and 'untrusted PID:' commands are concerning for
the reasons described above about PIDs being racy and generally an
unreliable way of identifying processes across the kernel/userspace
boundary.  I suspect it would not be too difficult for a malicious
user to trick an external modeler into marking the wrong process as
trusted/untrusted.

> +               state HEXID:
> +                       The state keyword is used to indicate that the
> +                       security state point identified by the ASCII
> +                       base 16 encoded value should be loaded into
> +                       the current security model as a valid security
> +                       event state.
> +
> +               pseudonym HEXID
> +                       The pseudonym keyword is used to indicate that
> +                       the pathname, identified by the 256 bit ASCII
> +                       base 16 encoded value HEXID, should be
> +                       designated to return a constant digest value
> +                       for the contents of the file.
> +
> +                       The HEXID value is computed with the following
> +                       function:
> +
> +                       HEXID = SHA256(PATHNAME_LENGTH || PATHNAME)

This seems like an unusual design choice, and perhaps one born from
necessity ... ?  It's nice that it is opt-in, but I would be curious
to hear what problems this solved.

> +               base HEXID
> +                       The base keyword is used to indicate that the
> +                       256 bit ASCII base 16 encoded value HEXID
> +                       should be registered as the value used to
> +                       generate model specific security event points.
> +
> +                       A model specific base value is designed to be
> +                       used as a 'freshness' nonce, similar to an
> +                       attestation nonce, to prove that a model state
> +                       value or measurement is current and not being
> +                       replayed.
> diff --git a/Documentation/admin-guide/LSM/tsem.rst b/Documentation/admin-guide/LSM/tsem.rst
> new file mode 100644
> index 000000000000..f03e5269cd25
> --- /dev/null
> +++ b/Documentation/admin-guide/LSM/tsem.rst
> @@ -0,0 +1,1240 @@
> +====
> +TSEM
> +====

...

> +Process and Platform Trust Status
> +=================================
> +
> +A fundamental concept in TSEM is the notion of providing a precise
> +definition for what it means for a platform or workload to be trusted.
> +A trusted platform or workload is one where there has not been an
> +attempt by a process to execute a security relevant event that does
> +not map into a known security state point.
> +
> +The process trust status is a characteristic of the process that is
> +passed to any subordinate processes that are descendants of that
> +process.  Once a process is tagged as untrusted, that characteristic
> +cannot be removed from the process.  In a 'fruit from the poisoned
> +vine' paradigm, all subordinate processes created by an untrusted
> +process are untrusted as well.
> +
> +On entry into each TSEM security event handler, the trust status of a
> +process is checked before an attempt to model the event is made.  An
> +attempt to execute a security event by an untrusted process will cause
> +the event, and its characteristics, to be logged.  The return status
> +of the hook will be determined by the enforcement state of the model.
> +A permission denial is only returned if the TMA is running in
> +enforcing mode.
> +
> +If the platform running the TSEM LSM has a TPM, the hardware aggregate
> +value is computed at the time that TSEM is initialized.  This hardware
> +aggregate value is the linear extension sum over Platform
> +Configuration Registers (PCR's) 0 through 7.  This is the same
> +aggregate value that is computed by the Integrity Measurement
> +Architecture (IMA) and is the industry standard method of providing an
> +evaluation measurement of the hardware platform state.
> +
> +Internally model domains have the hardware aggregate measurement
> +included as the first state point in the security model.  Externally
> +modeled domains export the hardware aggregate value to the TMA for
> +inclusion as the first state point of the model maintained by the TMA.
> +
> +The root modeling domain extends each security state point into PCR
> +11.  This allows hardware based TSEM measurements to coexist with IMA
> +measurement values.  This hardware measurement value can be used to
> +attest to the security execution trajectory that the root model
> +maintains.

It seems like making the target PCR configurable would be a good idea,
at the very least make it a Kconfig option.

Also, can you elaborate on how the security state points are extended
into the PCR?  I imagine for it to be useful at an arbitrary point in
time this would require the PCR to be extended as the security points
were generated, which would imply that the PCR value would be
dependent on execution order, and in most cases, scheduling order as
well.  How useful do you expect this to be for most users?

> +Internal vs external modeling
> +-----------------------------
> +
> +When a TSEM modeling domain is created, a designation is made as to
> +whether the domain is to be internally or externally modeled.
> +
> +In an internally modeled domain, the security event handlers pass the
> +event type and its characteristics to the designated internal trusted
> +modeling agent.  The agent provides the permission value for the
> +security event handler to return as the result of the event and sets
> +the trust status of the process executing the event.
> +
> +In an externally modeled domain, the event type and parameters are
> +exported to userspace for processing by a trust orchestrator with an
> +associated TMA.  The trust orchestrator communicates the result of the
> +modeling back to the kernel to support the setting of the process
> +trust status.
> +
> +This model poses a limitation to the ability of TSEM to model some
> +security events.  This is secondary to the fact that some event
> +handlers (LSM hooks) are called from a non-sleeping context, as a
> +result the process cannot be scheduled.  This is particularly the case
> +with the task based hooks, since they are typically called with the
> +tasklist lock held.
> +
> +This limitation is also inherent to the root model that extends the
> +security state points into TPM PCR 11, secondary to the fact that the
> +process invoking the security event hook will be scheduled away while
> +the TPM transaction completes.
> +
> +Addressing this problem directly requires a consideration of the
> +context from which the security event handlers are being called.
> +Subsequent implementations of TSEM will include a mechanism for
> +asynchronous deferral of model processing, until when and if, a review
> +of the call context would be considered worthwhile by the LSM
> +community.

This is a pretty big limitation, and in conjunction with the some of
the other issues brought up earlier (the PID issue seems the most
concerning), I'm having a difficult time believeing that an external
modeler could operate safely given the design presented here.

Unfortunately, there will always be LSM hooks which need to operate in
a non-blocking context, meaning this challenge is here to stay.  Help
me understand how you could safely do asynchronous policy enforcement
with an external modeler, I'm not sure it's possible.

Frankly, I also wonder how a system would perform with an external
modeler, indepdent of the issues with non-blocking hooks.  How does
the system perform with every blockable LSM hook invocation
potentially blocking on a response from userspace?  Or with the COE
being somewhat coarse, does the trajectory/policy populate itself
quickly?

> +Event handlers that cannot be directly modeled, still consider, on
> +entry, whether or not they are being called by an trusted or untrusted
> +process.  As a result, an untrusted process will cause a non-modeled
> +event to return a permissions violation in enforcing mode, even if the
> +security event cannot be directly modeled.
> +
> +Security event modeling typically traps violations of trust by a COE
> +with unmodeled characteristics that is attempting to access/execute a
> +file or map memory as executable; or by a COE with known
> +characteristics attempting to access or execute a CELL not prescribed
> +by a model.  As a result, the impact of the ability to not directly
> +model these events is lessened.

...

> +Event modeling
> +--------------
> +
> +TSEM security event modeling is based on the following functional
> +definition for a security state point:
> +
> +Sp = SHA256(SHA256(EVENT_ID) || TASK_ID || SHA256(COE) || SHA256(CELL))

It appears that all of the hasing in TSEM is SHA256 based, you might
want to consider making that a Kconfig option at the very least.

> +       Where:
> +               ||       = Concatenation operator.
> +
> +               EVENT_ID = ASCII name of event.
> +
> +               TASK_ID  = 256 bit identity of the process executing
> +                          the security event.
> +
> +               COE      = Characteristics of the context of execution
> +                          of the event.
> +
> +               CELL     = Characteristics of the object that the
> +                          security event is acting on.
> +

-- 
paul-moore.com

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 04/14] Implement CAP_TRUST capability.
       [not found]   ` <a12483d1-9d57-d429-789b-9e47ff575546@schaufler-ca.com>
@ 2023-02-13 11:43     ` Dr. Greg
  2023-02-13 18:02       ` Casey Schaufler
  0 siblings, 1 reply; 42+ messages in thread
From: Dr. Greg @ 2023-02-13 11:43 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: linux-security-module, linux-integrity, linux-kernel, shallyn, corbet

On Sat, Feb 04, 2023 at 06:54:20PM -0800, Casey Schaufler wrote:

Looping in some others, given that this issue is fundamental to
influencing how Linux can do security, also Sergey who raised a
similar issue to Casey.

Apologies for the delay in responding to this, catching up on issues
after a week of travel.

> On 2/3/2023 9:09 PM, Dr. Greg wrote:
> > TSEM was designed to support a Trust Orchestration System (TOS)
> > security architecture.  A TOS based system uses the concept of a
> > minimum Trusted Computing Base of utilities, referred to as trust
> > orchestrators, that maintain workloads in a trusted execution
> > state.  The trust orchestrators are thus, from a security
> > perspective, the most privileged assets on the platform.
> >
> > Introduce the CAP_TRUST capability that is defined as a
> > capability that allows a process to alter the trust status of the
> > platform.  In a fully trust orchestrated system only the
> > orchestrators carry this capability bit.

> How is this distinguishable from CAP_MAC_ADMIN?

CAP_TRUST is being introduced to enable Linux security architects to
ontologically differentiate processes that are allowed to modify
security guarantees based on deontological (rule-based) predicates
from processes allowed to modify security guarantees that are based on
narratival (event-based) predicates.

More generally, but less accurately, it allows security architectures
to be shaped by both Kantian and Hegelian logic perspectives. [0]

Given that the above will probably not be seen as an overly compelling
argument, in and of itself .... :-), some technical observations in
support of CAP_TRUST

Dictating to the choir here, but a brief background for those
following this discussion with an interest in security issues.

In general, classic mandatory access controls (MAC) are policy based.
For example, the standard bearers, SMACK and SeLinux, use classic
subject/object philosophies.  A process (subject) has a role/label
attached to it and objects acted on by the processes have a label
associated with them.  Policies, that can be viewed as rules, usually
quite elaborate and detailed for a whole system security policy, are
developed that define how subject labels may or may not interact with
object labels.

TSEM introduces an alternate notion of a security policy, defined as a
security model in TSEM parlance, that is created by unit testing of a
platform or workload.  Precise descriptions of the security events
generated by the testing are captured and used to maintain subsequent
executions of the workload in a known security or trust state.

Both approaches are considered 'mandatory' in nature, since userspace
cannot modify, in the case of policy based systems the labeling, or in
event based systems the security model being enforced.  Unless of
course a process has been assigned the capability to do so, hence this
discussion.

We are proposing CAP_TRUST as the privilege that is required by
processes to maintain the security state of a workload based on a set
of known valid security events.  In theory, and practice, it is
orthogonal to the actions permitted by CAP_MAC_ADMIN.  Although,
obviously, the intent of all these systems is to maintain a known
security state, however different those schemes may be from a
methodological perspective.

In security architectures, the concept of 'trust' has connotated the
notion of having a cryptographic guarantee of the state of a system.
As the cover letter and documentation discuss, TSEM is about blending
integrity measurement and mandatory access controls.

Trust orchestrators are designed to provide an attestation that a
workload has not deviated in any way from a previously defined
security model, CAP_TRUST is the privilege required to influence this
guarantee.  Once again, we view this as a different concept and
objective than the ability to modify a security policy.

Perhaps most importantly, TSEM shouldn't be viewed as an either/or
proposition when it comes to classic subject/object MAC
implementations.  A differentiation between CAP_TRUST and
CAP_MAC_ADMIN is needed in order to allow both architectures to work
together in a collaborative fashion.

It would be perfectly reasonable to believe that a TSEM modeled
workload would implement MAC (rules based) security controls.  In
order to achieve event based security guarantees, a trust orchestrator
drops CAP_TRUST for the workload process chain.  If CAP_MAC_ADMIN were
used, it would potentially impair the ability of the workload to
implement MAC policies, hence the desire to keep the privileges
orthogonal.

A quick example as to why this may be relevant.

Since TSEM is a generic security modeling architecture, with full
access to all security events, it can model the integrity of the
security meta-data needed by MAC based policies, similar to what
IMA/EVM does now, but entirely in the context of the LSM architecture
itself.  It would therefore be reasonable to operate both security
architectures in unison, with the event based TSEM protecting the
rules based MAC implementation.

Hopefully all of this helps clarify our thinking on this.

After reviewing the TSEM ABI and documentation, Paul Moore had some
questions and requests for clarification.  I am composing a response
to that e-mail that may also assist in understanding the role for
CAP_TRUST.

As always,
Dr. Greg

The Quixote Project - Flailing at the Travails of Cybersecurity

[0]: In the interest of full disclosure, I need to officially
attribute the notion of the philosophical differences between the two
security architectures to a brilliant young cybersecurity engineer
that I was privileged to mentor in the field of security modeling.  We
struggled for a long time to explain why and how TSEM was different
until he offered this inspired reasoning.  I recognize him, but will
leave him anonymous due to his current roles and responsibilities.

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 04/14] Implement CAP_TRUST capability.
  2023-02-13 11:43     ` Dr. Greg
@ 2023-02-13 18:02       ` Casey Schaufler
  2023-02-16 21:47         ` Dr. Greg
  0 siblings, 1 reply; 42+ messages in thread
From: Casey Schaufler @ 2023-02-13 18:02 UTC (permalink / raw)
  To: Dr. Greg
  Cc: linux-security-module, linux-integrity, linux-kernel, shallyn,
	corbet, casey

On 2/13/2023 3:43 AM, Dr. Greg wrote:
> On Sat, Feb 04, 2023 at 06:54:20PM -0800, Casey Schaufler wrote:
>
> Looping in some others, given that this issue is fundamental to
> influencing how Linux can do security, also Sergey who raised a
> similar issue to Casey.
>
> Apologies for the delay in responding to this, catching up on issues
> after a week of travel.
>
>> On 2/3/2023 9:09 PM, Dr. Greg wrote:
>>> TSEM was designed to support a Trust Orchestration System (TOS)
>>> security architecture.  A TOS based system uses the concept of a
>>> minimum Trusted Computing Base of utilities, referred to as trust
>>> orchestrators, that maintain workloads in a trusted execution
>>> state.  The trust orchestrators are thus, from a security
>>> perspective, the most privileged assets on the platform.
>>>
>>> Introduce the CAP_TRUST capability that is defined as a
>>> capability that allows a process to alter the trust status of the
>>> platform.  In a fully trust orchestrated system only the
>>> orchestrators carry this capability bit.
>> How is this distinguishable from CAP_MAC_ADMIN?
> CAP_TRUST is being introduced to enable Linux security architects to
> ontologically differentiate processes that are allowed to modify
> security guarantees based on deontological (rule-based) predicates
> from processes allowed to modify security guarantees that are based on
> narratival (event-based) predicates.
>
> More generally, but less accurately, it allows security architectures
> to be shaped by both Kantian and Hegelian logic perspectives. [0]
>
> Given that the above will probably not be seen as an overly compelling
> argument, in and of itself .... :-), some technical observations in
> support of CAP_TRUST
>
> Dictating to the choir here, but a brief background for those
> following this discussion with an interest in security issues.
>
> In general, classic mandatory access controls (MAC) are policy based.
> For example, the standard bearers, SMACK and SeLinux, use classic
> subject/object philosophies.  A process (subject) has a role/label
> attached to it and objects acted on by the processes have a label
> associated with them.  Policies, that can be viewed as rules, usually
> quite elaborate and detailed for a whole system security policy, are
> developed that define how subject labels may or may not interact with
> object labels.
>
> TSEM introduces an alternate notion of a security policy, defined as a
> security model in TSEM parlance, that is created by unit testing of a
> platform or workload.  Precise descriptions of the security events
> generated by the testing are captured and used to maintain subsequent
> executions of the workload in a known security or trust state.

There's nothing fundamentally new here. You are claiming the common
practice of looking at the audit trail to develop "policy" is a new
"alternative notion" for security. You are familiar with SELinux's
audit2allow I assume.

> Both approaches are considered 'mandatory' in nature, since userspace
> cannot modify, in the case of policy based systems the labeling, or in
> event based systems the security model being enforced.  Unless of
> course a process has been assigned the capability to do so, hence this
> discussion.
>
> We are proposing CAP_TRUST as the privilege that is required by
> processes to maintain the security state of a workload based on a set
> of known valid security events.  In theory, and practice, it is
> orthogonal to the actions permitted by CAP_MAC_ADMIN.  Although,
> obviously, the intent of all these systems is to maintain a known
> security state, however different those schemes may be from a
> methodological perspective.

I read this as an argument for using CAP_MAC_ADMIN.

> In security architectures, the concept of 'trust' has connotated the
> notion of having a cryptographic guarantee of the state of a system.
> As the cover letter and documentation discuss, TSEM is about blending
> integrity measurement and mandatory access controls.
>
> Trust orchestrators are designed to provide an attestation that a
> workload has not deviated in any way from a previously defined
> security model, CAP_TRUST is the privilege required to influence this
> guarantee.  Once again, we view this as a different concept and
> objective than the ability to modify a security policy.

This is (to my simple mind) indistinguishable from the way SELinux is
used in distributions. SELinux does not require a CAP_TRUST, and only
uses CAP_MAC_ADMIN in certain unlikely error conditions which I believe
you don't encounter.

> Perhaps most importantly, TSEM shouldn't be viewed as an either/or
> proposition when it comes to classic subject/object MAC
> implementations.  A differentiation between CAP_TRUST and
> CAP_MAC_ADMIN is needed in order to allow both architectures to work
> together in a collaborative fashion.
>
> It would be perfectly reasonable to believe that a TSEM modeled
> workload would implement MAC (rules based) security controls.  In
> order to achieve event based security guarantees, a trust orchestrator
> drops CAP_TRUST for the workload process chain.  If CAP_MAC_ADMIN were
> used, it would potentially impair the ability of the workload to
> implement MAC policies, hence the desire to keep the privileges
> orthogonal.

If you're giving the workload process chain the ability to modify the
configuration of another LSM you are already on marshy ground.

> A quick example as to why this may be relevant.
>
> Since TSEM is a generic security modeling architecture, with full
> access to all security events, it can model the integrity of the
> security meta-data needed by MAC based policies, similar to what
> IMA/EVM does now, but entirely in the context of the LSM architecture
> itself.  It would therefore be reasonable to operate both security
> architectures in unison, with the event based TSEM protecting the
> rules based MAC implementation.
>
> Hopefully all of this helps clarify our thinking on this.
>
> After reviewing the TSEM ABI and documentation, Paul Moore had some
> questions and requests for clarification.  I am composing a response
> to that e-mail that may also assist in understanding the role for
> CAP_TRUST.
>
> As always,
> Dr. Greg
>
> The Quixote Project - Flailing at the Travails of Cybersecurity
>
> [0]: In the interest of full disclosure, I need to officially
> attribute the notion of the philosophical differences between the two
> security architectures to a brilliant young cybersecurity engineer
> that I was privileged to mentor in the field of security modeling.  We
> struggled for a long time to explain why and how TSEM was different
> until he offered this inspired reasoning.  I recognize him, but will
> leave him anonymous due to his current roles and responsibilities.

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 02/14] Add TSEM specific documentation.
  2023-02-13  4:33   ` Paul Moore
@ 2023-02-14 11:58     ` Dr. Greg
  2023-02-14 12:18       ` Roberto Sassu
  2023-03-03  4:15       ` Paul Moore
  0 siblings, 2 replies; 42+ messages in thread
From: Dr. Greg @ 2023-02-14 11:58 UTC (permalink / raw)
  To: Paul Moore; +Cc: linux-security-module

On Sun, Feb 12, 2023 at 11:33:26PM -0500, Paul Moore wrote:
> On Sat, Feb 4, 2023 at 12:33 AM Dr. Greg <greg@enjellic.com> wrote:
> >
> > An entry was added to the ABI testing documentation to document
> > the files in the TSEM management filesystem.
> >
> > The file documenting the kernel command-line parameters was
> > updated to document the tsem_mode command-line parameter.
> >
> > The primary TSEM documentation file was added to the LSM
> > administration guide and the file was linked to the index of LSM
> > documentation.
> >
> > Signed-off-by: Greg Wettstein <greg@enjellic.com>
> > ---
> >  Documentation/ABI/testing/tsemfs              |  576 ++++++++
> >  Documentation/admin-guide/LSM/index.rst       |    1 +
> >  Documentation/admin-guide/LSM/tsem.rst        | 1240 +++++++++++++++++
> >  .../admin-guide/kernel-parameters.txt         |    5 +
> >  4 files changed, 1822 insertions(+)
> >  create mode 100644 Documentation/ABI/testing/tsemfs
> >  create mode 100644 Documentation/admin-guide/LSM/tsem.rst

> One of the more important requirements for any new LSM is that it
> documents a clear, understandable, and reasonable security model along
> with an implementation that faithfully implements that model.  Before
> I looked at your code I wanted to try and understand the TSEM security
> model and a few things jumped out at me rather quickly, I imagine
> there would be others as I start to look a bit closer but I wanted to
> send these questions/comments along now to get your take on them ...

Hi Paul, thanks for taking time to review the documentation and raise
questions, responses below.

> > diff --git a/Documentation/ABI/testing/tsemfs b/Documentation/ABI/testing/tsemfs
> > new file mode 100644
> > index 000000000000..3d326934624c
> > --- /dev/null
> > +++ b/Documentation/ABI/testing/tsemfs
> > @@ -0,0 +1,576 @@
> 
> ...
> 
> > +What:          /sys/fs/tsem/aggregate
> > +Date:          November 2022
> > +Contact:       Greg Wettstein <greg@enjellic.com>
> > +Description:
> > +               The aggregate file contains the ASCII base 16
> > +               representation of the 256 bit hardware platform
> > +               aggregate that TSEM is modeling under.  The platform
> > +               aggregate is the extension measurement of the Trusted
> > +               Platform Module PCR registers 0 through 8.

> I'm guessing the above is a typo and you mean PCRs 0 through 7 (not
> 8)?  If not, you need to provide an explanation somewhere as to what
> you are using PCR 8 for in TSEM and how it is extended, etc.

You are correct, it was a typo, it is registers 0 through 7, classic
zero counted array error.... :-)

We verified that the implementation is indeed aggregating registers 0
through 7.

> > +What:          /sys/fs/tsem/measurement
> > +Date:          November 2022
> > +Contact:       Greg Wettstein <greg@enjellic.com>
> > +Description:
> > +               The measurement file contains the ASCII base 16
> > +               hexadecimal representation of the 256 bit measurement
> > +               value of the security model that the process is
> > +               operating in.
> > +
> > +               The measurement value is the classic linear extension
> > +               measurement of the model.  An updated measurement
> > +               value is created by extending the current measurement
> > +               value with the state coefficient computed for a
> > +               security event.
> > +
> > +               This measurement value represents a time dependent
> > +               measurement of a model and is susceptible to
> > +               deviations caused by scheduling differences between
> > +               subsequent invocations of a workload.

> Given the very volatile nature of this value, what is it used for in
> userspace?  My apologies if I missed it in the docs.

It serves the same role as PCR register 10 in IMA, or any other
register in a TPM based architecture using a classic linear extension
mechanism strategy, it can be used to validate a list of time or
sequence ordered measurement values.

Our personal prejudice is that these types of measurements are of
limited value, which is why we introduce in TSEM, the notion of the
'state' value for a model, discussed below.

I would have to go looking on lore for a reference to the exact thread
but Roberto Sassu had offered up a patch set for IMA that addressed
the deficiency of these types of measurements.

> > +What:          /sys/fs/tsem/points
> > +Date:          November 2022
> > +Contact:       Greg Wettstein <greg@enjellic.com>
> > +Description:
> > +               The points file contains the ASCII base 16
> > +               representation of the 256 bit security state points of
> > +               a security domain/model.  The number of entries in
> > +               this file represent the number of security events that
> > +               are represented by the model.

> A similar questions to the tsem/measurement file.  If I understand
> you correctly, this is basically a series of SHA256 digests without
> any additional annotations, and without any ordering guarantees,
> yes?  What is it used for in userspace?

The values in the points file represent the current state of a model,
they are the coefficients that describe the security events that have
been modeled.

The output of this file can be captured and written to the
/sys/fs/tsem/map file in order to define a security model that is to
be subsequently enforced.

> > +What:          /sys/fs/tsem/state
> > +Date:          November 2022
> > +Contact:       Greg Wettstein <greg@enjellic.com>
> > +Description:
> > +               The state file contains the ASCII base 16
> > +               representation of the 256 bit value of the functional
> > +               state of a security domain/model.
> > +
> > +               The state value is a time independent representation
> > +               of the measurement of a model/domain, and unlike the
> > +               measurement value, is a time independent
> > +               representation of the security state of a workload.
> > +
> > +               This value is designed to be a single value that can
> > +               be attested to represent whether or not a workload has
> > +               deviated from a defined security behavior.

> It might be nice to explain how this value is calculated here in
> this file to remove any time or ordering dependencies.  Once again
> my apologies if I missed it in the rest of the docs.

The TSEM LSM documentation covers the issues surrounding the
measurement and state values.  See the section entitled 'Security
model functional definitions'.

Put succinctly, the state value is computed by generating a standard
linear extension sum over a list of security state points that have
been sorted in big-endian, ie. natural hash order.

It is designed to provide a time and scheduling independent value that
can be used to attest that a security model has not violated its
definition.

Don't apologize, there is a lot there to read, our loquaciousness
knows no bounds.... :-)

> > +What:          /sys/fs/tsem/trajectory
> > +Date:          November 2022
> > +Contact:       Greg Wettstein <greg@enjellic.com>
> > +Description:
> > +               The trajectory file contains a description of the
> > +               security events that have occurred in a security
> > +               domain/model.
> > +
> > +               Each entry in this file represents a single security
> > +               event and consists of brace {} delimited fields that
> > +               describe the characteristics of a security event.
> > +               Each field has key=value pairs that define
> > +               characteristics of the field.
> > +
> > +               Each line in a trajectory, or forensics, file will
> > +               always have the event{} and COE{} fields.  The event
> > +               field describes the characteristics of a security
> > +               event while the COE field describes the Context Of
> > +               Execution that is executing the security event.

> I think it would be good to provide a concrete definition of
> CELL_DEFINITION field as other areas of the documentation make
> reference to it within the tsem/trajectory file documentation.  We can
> somewhat infer it's format, fields, etc. but it's much better to be
> explicit about these things.

Valid point, we will incorporate a broad definition of what the 'CELL'
represents.

Conceptually, it is equivalent to the 'object' in mandatory access
controls.  In an events based architecture like TSEM, it is
essentially the 'bucket' of values that describe the parameters of a
security event that a COE/process is requesting permission for.

The name is actually in deference to Turing theory, which all of this
relates back to, but no need to go there now.

> > +               The event{} field consists of the following
> > +               characteristic definitions:

> I'm unclear as to the purpose of the event{} field as it is neither
> part of the COE or the CELL, is it here simply to make the event
> easier to read?  Or am I misunderstanding things and the event{}
> field is part of the COE?

It actually serves two roles, one of which, as you note, is to make
the event description easier to read and understand.

It probably comes as no surprise, but the trust orchestration system
that this is all designed to support, has a security console that can
be used to review the status of all the trust orchestrators that are
supervising security workloads.  Either in the cloud, or perhaps, a
large body of edge devices protecting critical infrastructure, if that
doesn't give away too much.... :-)

Having the process name and executable easily visualized is fairly
useful.

The second role is to allow the event description records to be
self-describing.  The value for the type= key is used by the Trusted
Modeling Agent (TMA) to determine what to look for in the remainder of
the event description record in order to compute the CELL value.

It also contains the TASK_ID value that ties the security state points
to the integrity of the executable.  Since that value is a synthetic
value it was deemed most appropriate to be placed in the event{}
field.

> > +                       process=COMM
> > +                               Where COMM is the ASCII representation
> > +                               of the name of the process executing
> > +                               the event.
> > +
> > +                       filename=PATH
> > +                               If the CELL definition for an event
> > +                               references a file the filename
> > +                               characteristic contains a definition
> > +                               of the path to the file.
> > +
> > +                               In the case where an event does not
> > +                               have a file the PATH value is set to a
> > +                               value of none.

> What happens in cases where multiple file paths are present in an
> event?  Also, given this is visible to userspace, and multiple
> things can affect the path to a file (e.g. namespaces), how is the
> file path determined?

Unless we have missed something, which is no doubt possible, all of
the security event hooks that we have implemented, which number about
87 now, that act on a 'file', receive only a single 'struct file *'
pointer as a parameter to the event.

So we haven't encountered a situation where there would be multiple
files for a single event description.

There is certainly the case where multiple security state points
involve the same file.  This can easily be seen, for example, in a
trust orchestrator running a workload in a runc container, where
multiple state points are generated by different executable mappings
of the runc binary at startup

The file path is the absolute pathname in the mount namespace that the
modeled workload is running in.

See the following for details:

security/tsem/event.c:get_path()

> > +                       type=EVENT_TYPE
> > +                               The value field for a type key is the
> > +                               name of the security event that is
> > +                               being modeled.  The list of value
> > +                               EVENT_TYPE names is defined in the
> > +                               following source file:
> > +
> > +                               security/tsem/tsem.c
> > +
> > +                               If the security event is a generically
> > +                               modeled event the EVENT_TYPE will be
> > +                               generic_event.  In this case the CELL
> > +                               characteristics for the event will be
> > +                               described by a generic_event{} field.
> > +
> > +                       task_id=TASK_ID
> > +                               The value of the task_id key will the
> > +                               ASCII base 16 representation of the
> > +                               model identity of the task that is
> > +                               executing the security event.
> > +
> > +                               The following documentation file:
> > +
> > +                               Documentation/admin-guide/LSM/TSEM.rst
> > +
> > +                               Describes how the TASK_ID value is
> > +                               generated.
> > +
> > +               The COE{} field consists of the following
> > +               characteristic definitions:
> > +
> > +                       uid=NN
> > +                               The ASCII base 10 representation of
> > +                               the numeric value of the discretionary
> > +                               user id of the process that is
> > +                               executing the security event.

> Given the ability to map UID/GID values in the kernel, what will be
> used as the basis for the COE?  What happens when the basis used in
> the kernel's COE generation does not match the basis used by the
> external modeler?

The UID/GID values used are the values defined in the initial
user namespace, see security/tsem/event.c:get_COE().

The basis set state that the trust orchestrator is running in has no
effect on the generation of the security state point.  The modeling
engine only operates on the values presented to it and determines if
the state point generated from the state description matches the model
it has been requested to enforce.

If it doesn't, the event is considered to violate the trust model.

> > +                       euid=NN
> > +                               The ASCII base 10 representation of
> > +                               the numeric value of the effective
> > +                               discretionary user id of the process
> > +                               that is executing the security event.
> > +
> > +                       euid=NN
> > +                               The ASCII base 10 representation of
> > +                               the numeric value of the effective
> > +                               discretionary user id of the process
> > +                               that is executing the security event.
> > +
> > +                       suid=NN
> > +                               The ASCII base 10 representation of
> > +                               the numeric value of the saved user id
> > +                               of the process that is executing the
> > +                               security event.
> > +
> > +                       gid=NN
> > +                               The ASCII base 10 representation of
> > +                               the numeric value of the discretionary
> > +                               group id of the process that is
> > +                               executing the security event.
> > +
> > +                       egid=NN
> > +                               The ASCII base 10 representation of
> > +                               the numeric value of the discretionary
> > +                               effective group id of the process that
> > +                               is executing the security event.
> > +
> > +                       egid=NN
> > +                               The ASCII base 10 representation of
> > +                               the numeric value of the discretionary
> > +                               effective group id of the process that
> > +                               is executing the security event.
> > +
> > +                       sgid=NN
> > +                               The base 10 ASCII representation of
> > +                               the numeric value of the saved
> > +                               discretionary group id of the process
> > +                               that is executing the security event.
> > +
> > +                       fsuid=NN
> > +                               The base 10 ASCII representation of
> > +                               the numeric value of the discretionary
> > +                               filesystem user id of the process that
> > +                               is executing the security event.
> > +
> > +                       fsgid=NN
> > +                               The ASCII base 10 representation of
> > +                               the numeric value of the discretionary
> > +                               filesystem group id of the process
> > +                               that is executing the security event.
> > +
> > +                       cap=0xNNN
> > +                               The ASCII base 16 representation of
> > +                               the numeric value of effective
> > +                               capabilities of the process that is
> > +                               executing the security event.
> > +
> > +               If the CELL value for a security event includes the
> > +               definition of a file a file{} event field will be
> > +               included.  The following characteristics will be
> > +               encoded in this field:
> > +
> > +                       flags=NN
> > +                               The ASCII base 10 representation of
> > +                               the flags value of the 'struct file'
> > +                               structure that is the source of the
> > +                               file description.
> > +
> > +                       uid=NN
> > +                               The ASCII base 10 representation of
> > +                               the discretionary user id of the file.
> > +
> > +                       gid=NN
> > +                               The base 10 ASCII representation of
> > +                               the discretionary group id of the
> > +                               file.

> Similar to the task UID/GID mapping questions above, there are
> mechanisms which map the file user/group IDs, which will be used in
> the CELL definition and how will that be resolved between the kernel
> and an external modeler?

The answer is the same as with the COE, see the following function:

security/tsem/event.c:get_file_cell()

Once again, the TMA only operates on the event description presented
to it and is not influenced by its own namespace.

> > +What:          /sys/fs/tsem/ExternalTMA
> > +Date:          November 2022
> > +Contact:       Greg Wettstein <greg@enjellic.com>
> > +Description:
> > +               The ExternalTMA directory is a container directory
> > +               that hold files that will be used to export the
> > +               security events, and their associated parameters, for
> > +               externally modeled security domains/namespaces.
> > +
> > +               The files created in this directory will be named by
> > +               the base 10 ASCII representation of the id value
> > +               assigned to the modeling domain/namespace.  See the
> > +               documentation for the /sys/fs/tsem/id file in this
> > +               documentation for more details on this value.
> > +
> > +               This file will is a read-only file that can be polled
> > +               by a userspace trust orchestration implementation to
> > +               process security events that are to be modeled by
> > +               an external Trusted Modeling Agent.
> > +
> > +               The type of the exported event is the first keyword of
> > +               the line that is output and have the following
> > +               values and arguments:
> > +
> > +               aggregate HEXID:
> > +                       Where HEXID is the ASCII base 16
> > +                       representation of the 256 bit hardware
> > +                       platform aggregate value.
> > +
> > +               export pid{NNN} COE{} CELL_DEFINITION
> > +                       Where the NNN in the pid field is the ASCII
> > +                       base 10 value of the id of the process that is
> > +                       executing the security event that will be
> > +                       modeled.

> I worry whenever I see a PID used as an identifier shared across the
> kernel/userspace boundary as it is inherently racy.  Given the
> somewhat coarse COE definition where one can expect multiple
> processes/PIDs to share the same COE value, and the ability of
> untrusted users/processes to manipulate the PID table, what do you
> expect to use the pid{NNN} field for in this event?
> 
> Similar to the other namespace/mapping issues discussed previously,
> there is also the PID namespace issue to worry about.  How is that
> handled here?

The concern over the PID issue is understandable, I will treat the
reasoning behind its use below.

The PID value is the 'native' value managed by the kernel, not a
mapped value.

> > +                       The COE field has the same format as the field
> > +                       emitted for a trajectory or forensics event.
> > +
> > +                       The CELL_DEFINITION are the same field
> > +                       definitions that are emitted for a trajectory
> > +                       or forensics event.
> > +
> > +               log process{name} event{type} action{type}
> > +                       The log event is emitted when an untrusted
> > +                       task attempts to execute a security event.
> > +
> > +                       The name value of the COE field is the name of
> > +                       the process (comm value) that is executing the
> > +                       security event.
> > +
> > +                       The type value of the event field is the name
> > +                       of the security event being executed as
> > +                       defined in the tsem_names array in the
> > +                       security/tsem/tsem.c file.
> > +
> > +                       The type value of the action field is the type
> > +                       of action the LSM enforced in response to
> > +                       encountering the untrusted process.  This
> > +                       value will be either LOG or EPERM to represent
> > +                       whether or not the trust violation is being
> > +                       logged or enforced.
> > +
> > +What:          /sys/fs/tsem/control
> > +Date:          November 2022
> > +Contact:       Greg Wettstein <greg@enjellic.com>
> > +Description:
> > +               The control file is the only writable file in the
> > +               filesystem and is used by the trust orchestrators to
> > +               configure and control the behavior of the TSEM
> > +               implementation.
> > +
> > +               The following keyword and arguments are recognized:
> > +
> > +               internal:
> > +                       The internal keyword causes an internally
> > +                       modeled domain to be created for the calling
> > +                       process.
> > +
> > +               external:
> > +                       The external keyword causes an externally
> > +                       modeled domain to be created for the calling
> > +                       process.
> > +
> > +               enforce:
> > +                       The enforce keyword causes the modeling
> > +                       domain/namespace of the process to enter
> > +                       enforcing mode.  In this mode a value of
> > +                       -EPERM will be returned for a security event
> > +                       that does not map into the current set of
> > +                       allowed state points for the security model
> > +                       being implemented for the domain/namespace.
> > +
> > +               seal:
> > +                       The seal keyword causes the security model
> > +                       being implemented for the model to be placed
> > +                       in sealed state.  In this state the current
> > +                       set of security event points is considered to
> > +                       be the only set of valid points for the
> > +                       domain/model.  Any subsequent events that map
> > +                       to a point not in the current model will be
> > +                       considered a violation of the model.
> > +
> > +               trusted PID:
> > +                       The trusted keyword is used by a trust
> > +                       orchestrator to indicate that the process
> > +                       identified by the PID argument should be
> > +                       allowed to run in trusted status.
> > +
> > +               untrusted PID:
> > +                       The untrusted keyword is used by a trust
> > +                       orchestrator to indicate that the process
> > +                       identified by the PID argument should be
> > +                       allowed to run but designated as an untrusted
> > +                       process.

> The 'trusted PID:' and 'untrusted PID:' commands are concerning for
> the reasons described above about PIDs being racy and generally an
> unreliable way of identifying processes across the kernel/userspace
> boundary.  I suspect it would not be too difficult for a malicious
> user to trick an external modeler into marking the wrong process as
> trusted/untrusted.

An external TMA needs the PID value to determine which process to wake
up and set the trust status value on in the task control structure,
after the event is modeled.  As was noted above, the PID value is the
unmapped value maintained by the OS.

Lets see if we can reason through why the PID can be used safely.

CAP_TRUST, or whatever ends up getting used, is required by the trust
orchestrator to create a security/modeling namespace for the workload
being modeled.  This results in the creation of the following
pseudo-file for surfacing the security event descriptions for the
namespace/workload:

/sys/fs/tsem/ExternalTMA/N

Where N is the id number of the modeling domain.

CAP_TRUST, caveats applied, is required to open the pseudo-file.  The
trust orchestrator only receives and acts on PID values through this
conduit from the kernel.

When an event description is exported, the trust status of the task is
set to 'pending' and the process is placed in interruptible sleep and
scheduled away, with the 'wakeup' criteria being the trust status
being changed from pending to either trusted or untrusted.

The only path to change the trust status value in the LSM task control
structure and wake up the process is by the trust orchestrator that
created the namespace, by writing the appropriate value to the
/sys/fs/tsem/control file.  Access to that file is gated by CAP_TRUST
or its equivalent.

See the following code locations for further details:

security/tsem/export.c:tsem_export_event()

security/tsem/fs.c:control_COE()

As long as the process 'exists', albeit sleeping, the PID slot is
occupied and an adversary, regardless of namespace, cannot substitute
a task with the same PID value.

This leaves an adversary with the need to terminate the task being
modeled in order to capture its PID slot.

Precautions are implemented in the following function to protect the
process from being terminated by an adversary:

security/tsem/tsem.c:tsem_task_kill()

The following is a summary of the criteria that is implemented:

- Signal privileges are granted to any process with CAP_TRUST.

- A process without CAP_TRUST cannot signal a process with CAP_TRUST.

- Cross-model signaling is denied by a process without CAP_TRUST.

So that leaves us in a scenario where, outside of the modeling
namespace, CAP_TRUST would be required to kill the process waiting to
be modeled.  If CAP_TRUST has been lost to an adversary, the platform
is owned and the game is over.

So that leaves us with the threat of an adversary attempting to
implement a PID race within the modeling domain itself.

As I've noted previously in these threads, and in the LSM
documentation proper, TSEM is about prospective generation of a
security model, rather than retrospective correction of a MAC policy
that has been demonstrated to have undesired effects.  The distinction
is important in this case.

For an adversary to mount a PID race attack from within the modeled
workload, one of three conditions must be met:

- A shell script is read.

- A malicious binary would have to be executed.

- Memory would have had to have been mapped executable.

Since TSEM captures the security events needed to implement these
actions, the events would have had to have been incorporated into the
security unit test for the workload or the actions would be denied.

Hopefully this analysis is complete and correct with respect to this
threat, comments and observations are obviously welcome.

There is an opportunity to strengthen this model that I will touch on
below.

> > +               state HEXID:
> > +                       The state keyword is used to indicate that the
> > +                       security state point identified by the ASCII
> > +                       base 16 encoded value should be loaded into
> > +                       the current security model as a valid security
> > +                       event state.
> > +
> > +               pseudonym HEXID
> > +                       The pseudonym keyword is used to indicate that
> > +                       the pathname, identified by the 256 bit ASCII
> > +                       base 16 encoded value HEXID, should be
> > +                       designated to return a constant digest value
> > +                       for the contents of the file.
> > +
> > +                       The HEXID value is computed with the following
> > +                       function:
> > +
> > +                       HEXID = SHA256(PATHNAME_LENGTH || PATHNAME)

> This seems like an unusual design choice, and perhaps one born from
> necessity ... ?  It's nice that it is opt-in, but I would be curious
> to hear what problems this solved.

It is an approximation method that allows things like log files and
.bash_history files to be effectively modeled.

Once again, TSEM is a blending of integrity measurement and mandatory
access controls.  In a security event that has a file as a component
of its CELL, the SHA256 digest value of the file is included in the
computation of the CELL identity.

These types of files have no known 'good' value, by definition.  So
'pseudonym' declarations implement a model approximation to provide a
fixed digest value for a file, regardless of its contents.

The effect of this can easily be seen if one of the Quixote trust
orchestrators is used to run a container based shell workload.  If the
.bash_history file in the container is not zeroed before execution, or
treated as a pseudonym, the bash shell will be tagged and 'poisoned'
as untrusted when it reads the file.

It is a pretty solid understanding in modeling theory that
approximations are almost universally required when dealing with
physical phenomenon.  As a quantum chemist by training, I spent a fair
amount of time dealing with complete, intermediate and modified
neglect of diatomic overlap as a result of this.... :-)

> > +               base HEXID
> > +                       The base keyword is used to indicate that the
> > +                       256 bit ASCII base 16 encoded value HEXID
> > +                       should be registered as the value used to
> > +                       generate model specific security event points.
> > +
> > +                       A model specific base value is designed to be
> > +                       used as a 'freshness' nonce, similar to an
> > +                       attestation nonce, to prove that a model state
> > +                       value or measurement is current and not being
> > +                       replayed.
> > diff --git a/Documentation/admin-guide/LSM/tsem.rst b/Documentation/admin-guide/LSM/tsem.rst
> > new file mode 100644
> > index 000000000000..f03e5269cd25
> > --- /dev/null
> > +++ b/Documentation/admin-guide/LSM/tsem.rst
> > @@ -0,0 +1,1240 @@
> > +====
> > +TSEM
> > +====
> 
> ...
> 
> > +Process and Platform Trust Status
> > +=================================
> > +
> > +A fundamental concept in TSEM is the notion of providing a precise
> > +definition for what it means for a platform or workload to be trusted.
> > +A trusted platform or workload is one where there has not been an
> > +attempt by a process to execute a security relevant event that does
> > +not map into a known security state point.
> > +
> > +The process trust status is a characteristic of the process that is
> > +passed to any subordinate processes that are descendants of that
> > +process.  Once a process is tagged as untrusted, that characteristic
> > +cannot be removed from the process.  In a 'fruit from the poisoned
> > +vine' paradigm, all subordinate processes created by an untrusted
> > +process are untrusted as well.
> > +
> > +On entry into each TSEM security event handler, the trust status of a
> > +process is checked before an attempt to model the event is made.  An
> > +attempt to execute a security event by an untrusted process will cause
> > +the event, and its characteristics, to be logged.  The return status
> > +of the hook will be determined by the enforcement state of the model.
> > +A permission denial is only returned if the TMA is running in
> > +enforcing mode.
> > +
> > +If the platform running the TSEM LSM has a TPM, the hardware aggregate
> > +value is computed at the time that TSEM is initialized.  This hardware
> > +aggregate value is the linear extension sum over Platform
> > +Configuration Registers (PCR's) 0 through 7.  This is the same
> > +aggregate value that is computed by the Integrity Measurement
> > +Architecture (IMA) and is the industry standard method of providing an
> > +evaluation measurement of the hardware platform state.
> > +
> > +Internally model domains have the hardware aggregate measurement
> > +included as the first state point in the security model.  Externally
> > +modeled domains export the hardware aggregate value to the TMA for
> > +inclusion as the first state point of the model maintained by the TMA.
> > +
> > +The root modeling domain extends each security state point into PCR
> > +11.  This allows hardware based TSEM measurements to coexist with IMA
> > +measurement values.  This hardware measurement value can be used to
> > +attest to the security execution trajectory that the root model
> > +maintains.

> It seems like making the target PCR configurable would be a good
> idea, at the very least make it a Kconfig option.

That was something that we have thought about, it probably needs a
Kconfig option.

Contrary to all appearances, as a team we are really minimalists at
heart and tend to not make things more complex or configurable than
needed.... :-)

> Also, can you elaborate on how the security state points are
> extended into the PCR?  I imagine for it to be useful at an
> arbitrary point in time this would require the PCR to be extended as
> the security points were generated, which would imply that the PCR
> value would be dependent on execution order, and in most cases,
> scheduling order as well.  How useful do you expect this to be for
> most users?

Your assessment is correct, the state points are extended into the PCR
whenever a unique security state point is generated.

In a 'free-running' model, the value in the register will be fungible
due to scheduling dependencies.

If the model is pre-defined, the security state points will be
extended into the register as they are loaded through the
/sys/fs/tsem/map pseudo-file interface.  In this case, the value will
be fixed and any departure from the value would signal that the
modeling domain has departed from its specification.

With respect to the utility of the value, in a 'free-running' model it
is about as useful as the value that IMA maintains in PCR 10, which in
our opinion is not very useful and is why we implemented the notion of
the 'state' value of a model.

The primary utility of the value is that it is a hardware maintained
reference value that can be used to confirm the set of measurements
committed to the register.

So our 'state' value gives us a constant 'good' value for the security
model.  The PCR 11 value provides a hardware root of trust for the set
of points that lead to the state value.

> > +Internal vs external modeling
> > +-----------------------------
> > +
> > +When a TSEM modeling domain is created, a designation is made as to
> > +whether the domain is to be internally or externally modeled.
> > +
> > +In an internally modeled domain, the security event handlers pass the
> > +event type and its characteristics to the designated internal trusted
> > +modeling agent.  The agent provides the permission value for the
> > +security event handler to return as the result of the event and sets
> > +the trust status of the process executing the event.
> > +
> > +In an externally modeled domain, the event type and parameters are
> > +exported to userspace for processing by a trust orchestrator with an
> > +associated TMA.  The trust orchestrator communicates the result of the
> > +modeling back to the kernel to support the setting of the process
> > +trust status.
> > +
> > +This model poses a limitation to the ability of TSEM to model some
> > +security events.  This is secondary to the fact that some event
> > +handlers (LSM hooks) are called from a non-sleeping context, as a
> > +result the process cannot be scheduled.  This is particularly the case
> > +with the task based hooks, since they are typically called with the
> > +tasklist lock held.
> > +
> > +This limitation is also inherent to the root model that extends the
> > +security state points into TPM PCR 11, secondary to the fact that the
> > +process invoking the security event hook will be scheduled away while
> > +the TPM transaction completes.
> > +
> > +Addressing this problem directly requires a consideration of the
> > +context from which the security event handlers are being called.
> > +Subsequent implementations of TSEM will include a mechanism for
> > +asynchronous deferral of model processing, until when and if, a review
> > +of the call context would be considered worthwhile by the LSM
> > +community.

> This is a pretty big limitation, and in conjunction with the some of
> the other issues brought up earlier (the PID issue seems the most
> concerning), I'm having a difficult time believeing that an external
> modeler could operate safely given the design presented here.

With respect to the PID issue, we would welcome any comments on the
analysis that we provided above as to its design safety.

If the PID issue remains a concern, we have an extension to the export
descriptions that would include a random nonce that would be emitted
with the PID.  The nonce would be placed in the LSM task control
'blob' for the sleeping task and used to confirm that the task release
directive was acting on the correct process.

> Unfortunately, there will always be LSM hooks which need to operate
> in a non-blocking context, meaning this challenge is here to stay.
> Help me understand how you could safely do asynchronous policy
> enforcement with an external modeler, I'm not sure it's possible.

Electing to implement asynchronous enforcement would require further
thought.  We were operating in the context of full disclosure in our
documentation and wanted to be up front about limitations and options.

To be clear, at this time, we are not advocating for or bringing
forward an asynchronous update architecture.

So, at this time, there is a well understood modeling limitation with
respect to the LSM hook implementations.  That limitation is not
limited to external TMA's, since the event state points cannot be
extended into a TPM in a non-blocking context.

So far we have only run into a handful of these events, almost
exclusively due to the LSM hooks being called with the tasklist lock
held.  I see that Linus commented a couple of weeks ago that the
tasklist lock is our last big lock that may need to be looked at.

With respect to the need for external modeling, as is the case with
all security designs, this is a cost/benefit decision.

In some cases, for example SGX, using external modeling is the only
option, since executing in the context of an SGX enclave is not
possible from the kernel.  Quixote/TSEM is actually one of the unsung
'killer' applications for SGX, at least from our long involvement with
the technology.

Having an external modeling option also means that you don't need to
get code into the kernel proper in order to implement a security model
that may be useful.  I think we all can appreciate the utility and
importance of that.

We believe that the ability to do dedicated hardware security
co-processors is important.  External modeling opens the door to
democratize how that can be done.

The binary Quixote distribution includes firmware for an
NRF52840-DONGLE implementation of a TMA.  So you have a clear
demonstration of the opportunity to create 'Yubikey' type devices to
enforce kernel security.

A reasonably interesting option for entities distributing dedicated
Linux based devices, where for a few dollars you can include a USB
based co-processor that would provide hardware based protections to
prevent an embedded Linux implementation from being diverted from its
design intent.

Truth be told, after having looked at countless execution
trajectories, processes are typically locked into untrusted status
before they get to any of the non-blocking hooks.

> Frankly, I also wonder how a system would perform with an external
> modeler, indepdent of the issues with non-blocking hooks.  How does
> the system perform with every blockable LSM hook invocation
> potentially blocking on a response from userspace?  Or with the COE
> being somewhat coarse, does the trajectory/policy populate itself
> quickly?

One obviously experiences a latency hit in going to userspace, by
definition, implementing security always has an associated resource
cost.  So, once again, this comes down to a cost/benefit analysis.

As a Gedanken exercise, consider the value proposition of a Linux
based RTU, or other device, controlling infrastructure that can only
execute security relevant events that are guaranteed to be known good
by an external co-processor that is only accessible as a security
oracle.

Given that frame of reference.

Time for a userspace or SGX based TMA transaction is running around
890 micro-seconds.

Going to a TMA based in a Xen stubdomain implementation runs a bit
longer, probably around 940 micro-seconds or so.

The micro-controller implementations are decidedly slower, with the
NRF52840-DONGLE clocking in at around 40 micro-seconds, but that is
strictly a CPU horsepower issue.

All of this with the caveat that we have been focusing almost
exclusively on correctness and not optimizing performance.

We've thought a bit, mainly on long walks with our Golden Retriever
Izzy, about the issue of building a kernel based policy cache with
externally modeled domains.  Given that the kernel does not, a-priori,
know what modeling algorithm a TMA might be using, we would need to
come up with a method of deterministically mapping a security event
description to a known good state point value.

The other issue with all this is that with containerized workloads,
particularly micro-services, the rate of security event generation can
be surprisingly low.  Obviously this is also the case with embedded
implementations.

Once again, what are you willing to pay to be safe?

> > +Event handlers that cannot be directly modeled, still consider, on
> > +entry, whether or not they are being called by an trusted or untrusted
> > +process.  As a result, an untrusted process will cause a non-modeled
> > +event to return a permissions violation in enforcing mode, even if the
> > +security event cannot be directly modeled.
> > +
> > +Security event modeling typically traps violations of trust by a COE
> > +with unmodeled characteristics that is attempting to access/execute a
> > +file or map memory as executable; or by a COE with known
> > +characteristics attempting to access or execute a CELL not prescribed
> > +by a model.  As a result, the impact of the ability to not directly
> > +model these events is lessened.
> 
> ...
> 
> > +Event modeling
> > +--------------
> > +
> > +TSEM security event modeling is based on the following functional
> > +definition for a security state point:
> > +
> > +Sp = SHA256(SHA256(EVENT_ID) || TASK_ID || SHA256(COE) || SHA256(CELL))

> It appears that all of the hasing in TSEM is SHA256 based, you might
> want to consider making that a Kconfig option at the very least.

That has been something that we have talked about as well.

As I indicated previously, we really are minimalists, particularly
after watching IMA fight with issues surrounding algorithmic agility.

It would be easy enough to make this configurable but does anyone see
SHA256 as not being useful in in this role anywhere in the next 10
years?

> paul-moore.com

Hopefully all of this is useful moving forward.

Have a good day.

As always,
Dr. Greg

The Quixote Project - Flailing at the Travails of Cybersecurity

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 02/14] Add TSEM specific documentation.
  2023-02-14 11:58     ` Dr. Greg
@ 2023-02-14 12:18       ` Roberto Sassu
  2023-02-15 16:26         ` Dr. Greg
  2023-03-03  4:15       ` Paul Moore
  1 sibling, 1 reply; 42+ messages in thread
From: Roberto Sassu @ 2023-02-14 12:18 UTC (permalink / raw)
  To: Dr. Greg, Paul Moore; +Cc: linux-security-module

On Tue, 2023-02-14 at 05:58 -0600, Dr. Greg wrote:
> On Sun, Feb 12, 2023 at 11:33:26PM -0500, Paul Moore wrote:
> > On Sat, Feb 4, 2023 at 12:33 AM Dr. Greg <greg@enjellic.com> wrote:
> > > An entry was added to the ABI testing documentation to document
> > > the files in the TSEM management filesystem.
> > > 
> > > The file documenting the kernel command-line parameters was
> > > updated to document the tsem_mode command-line parameter.
> > > 
> > > The primary TSEM documentation file was added to the LSM
> > > administration guide and the file was linked to the index of LSM
> > > documentation.
> > > 
> > > Signed-off-by: Greg Wettstein <greg@enjellic.com>
> > > ---
> > >  Documentation/ABI/testing/tsemfs              |  576 ++++++++
> > >  Documentation/admin-guide/LSM/index.rst       |    1 +
> > >  Documentation/admin-guide/LSM/tsem.rst        | 1240 +++++++++++++++++
> > >  .../admin-guide/kernel-parameters.txt         |    5 +
> > >  4 files changed, 1822 insertions(+)
> > >  create mode 100644 Documentation/ABI/testing/tsemfs
> > >  create mode 100644 Documentation/admin-guide/LSM/tsem.rst
> > One of the more important requirements for any new LSM is that it
> > documents a clear, understandable, and reasonable security model along
> > with an implementation that faithfully implements that model.  Before
> > I looked at your code I wanted to try and understand the TSEM security
> > model and a few things jumped out at me rather quickly, I imagine
> > there would be others as I start to look a bit closer but I wanted to
> > send these questions/comments along now to get your take on them ...
> 
> Hi Paul, thanks for taking time to review the documentation and raise
> questions, responses below.
> 
> > > diff --git a/Documentation/ABI/testing/tsemfs b/Documentation/ABI/testing/tsemfs
> > > new file mode 100644
> > > index 000000000000..3d326934624c
> > > --- /dev/null
> > > +++ b/Documentation/ABI/testing/tsemfs
> > > @@ -0,0 +1,576 @@
> > 
> > ...
> > 
> > > +What:          /sys/fs/tsem/aggregate
> > > +Date:          November 2022
> > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > +Description:
> > > +               The aggregate file contains the ASCII base 16
> > > +               representation of the 256 bit hardware platform
> > > +               aggregate that TSEM is modeling under.  The platform
> > > +               aggregate is the extension measurement of the Trusted
> > > +               Platform Module PCR registers 0 through 8.
> > I'm guessing the above is a typo and you mean PCRs 0 through 7 (not
> > 8)?  If not, you need to provide an explanation somewhere as to what
> > you are using PCR 8 for in TSEM and how it is extended, etc.
> 
> You are correct, it was a typo, it is registers 0 through 7, classic
> zero counted array error.... :-)
> 
> We verified that the implementation is indeed aggregating registers 0
> through 7.
> 
> > > +What:          /sys/fs/tsem/measurement
> > > +Date:          November 2022
> > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > +Description:
> > > +               The measurement file contains the ASCII base 16
> > > +               hexadecimal representation of the 256 bit measurement
> > > +               value of the security model that the process is
> > > +               operating in.
> > > +
> > > +               The measurement value is the classic linear extension
> > > +               measurement of the model.  An updated measurement
> > > +               value is created by extending the current measurement
> > > +               value with the state coefficient computed for a
> > > +               security event.
> > > +
> > > +               This measurement value represents a time dependent
> > > +               measurement of a model and is susceptible to
> > > +               deviations caused by scheduling differences between
> > > +               subsequent invocations of a workload.
> > Given the very volatile nature of this value, what is it used for in
> > userspace?  My apologies if I missed it in the docs.
> 
> It serves the same role as PCR register 10 in IMA, or any other
> register in a TPM based architecture using a classic linear extension
> mechanism strategy, it can be used to validate a list of time or
> sequence ordered measurement values.
> 
> Our personal prejudice is that these types of measurements are of
> limited value, which is why we introduce in TSEM, the notion of the
> 'state' value for a model, discussed below.
> 
> I would have to go looking on lore for a reference to the exact thread
> but Roberto Sassu had offered up a patch set for IMA that addressed
> the deficiency of these types of measurements.

Hi Greg

yes, this:

https://lore.kernel.org/linux-integrity/20210914163401.864635-1-roberto.sassu@huawei.com/

DIGLIM makes the PCR extended with software measurements deterministic,
independent from how processes are scheduled, at the cost of not
knowing if files with matching digests from a list were accessed or
not, and in which order.

But, in exchange, you can seal a TLS key to IMA measurements that is
available for handshakes as long as the system does not execute
something unknown. After that, you have to reboot to use the key again.

(Didn't read your proposal yet.)

Roberto

> > > +What:          /sys/fs/tsem/points
> > > +Date:          November 2022
> > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > +Description:
> > > +               The points file contains the ASCII base 16
> > > +               representation of the 256 bit security state points of
> > > +               a security domain/model.  The number of entries in
> > > +               this file represent the number of security events that
> > > +               are represented by the model.
> > A similar questions to the tsem/measurement file.  If I understand
> > you correctly, this is basically a series of SHA256 digests without
> > any additional annotations, and without any ordering guarantees,
> > yes?  What is it used for in userspace?
> 
> The values in the points file represent the current state of a model,
> they are the coefficients that describe the security events that have
> been modeled.
> 
> The output of this file can be captured and written to the
> /sys/fs/tsem/map file in order to define a security model that is to
> be subsequently enforced.
> 
> > > +What:          /sys/fs/tsem/state
> > > +Date:          November 2022
> > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > +Description:
> > > +               The state file contains the ASCII base 16
> > > +               representation of the 256 bit value of the functional
> > > +               state of a security domain/model.
> > > +
> > > +               The state value is a time independent representation
> > > +               of the measurement of a model/domain, and unlike the
> > > +               measurement value, is a time independent
> > > +               representation of the security state of a workload.
> > > +
> > > +               This value is designed to be a single value that can
> > > +               be attested to represent whether or not a workload has
> > > +               deviated from a defined security behavior.
> > It might be nice to explain how this value is calculated here in
> > this file to remove any time or ordering dependencies.  Once again
> > my apologies if I missed it in the rest of the docs.
> 
> The TSEM LSM documentation covers the issues surrounding the
> measurement and state values.  See the section entitled 'Security
> model functional definitions'.
> 
> Put succinctly, the state value is computed by generating a standard
> linear extension sum over a list of security state points that have
> been sorted in big-endian, ie. natural hash order.
> 
> It is designed to provide a time and scheduling independent value that
> can be used to attest that a security model has not violated its
> definition.
> 
> Don't apologize, there is a lot there to read, our loquaciousness
> knows no bounds.... :-)
> 
> > > +What:          /sys/fs/tsem/trajectory
> > > +Date:          November 2022
> > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > +Description:
> > > +               The trajectory file contains a description of the
> > > +               security events that have occurred in a security
> > > +               domain/model.
> > > +
> > > +               Each entry in this file represents a single security
> > > +               event and consists of brace {} delimited fields that
> > > +               describe the characteristics of a security event.
> > > +               Each field has key=value pairs that define
> > > +               characteristics of the field.
> > > +
> > > +               Each line in a trajectory, or forensics, file will
> > > +               always have the event{} and COE{} fields.  The event
> > > +               field describes the characteristics of a security
> > > +               event while the COE field describes the Context Of
> > > +               Execution that is executing the security event.
> > I think it would be good to provide a concrete definition of
> > CELL_DEFINITION field as other areas of the documentation make
> > reference to it within the tsem/trajectory file documentation.  We can
> > somewhat infer it's format, fields, etc. but it's much better to be
> > explicit about these things.
> 
> Valid point, we will incorporate a broad definition of what the 'CELL'
> represents.
> 
> Conceptually, it is equivalent to the 'object' in mandatory access
> controls.  In an events based architecture like TSEM, it is
> essentially the 'bucket' of values that describe the parameters of a
> security event that a COE/process is requesting permission for.
> 
> The name is actually in deference to Turing theory, which all of this
> relates back to, but no need to go there now.
> 
> > > +               The event{} field consists of the following
> > > +               characteristic definitions:
> > I'm unclear as to the purpose of the event{} field as it is neither
> > part of the COE or the CELL, is it here simply to make the event
> > easier to read?  Or am I misunderstanding things and the event{}
> > field is part of the COE?
> 
> It actually serves two roles, one of which, as you note, is to make
> the event description easier to read and understand.
> 
> It probably comes as no surprise, but the trust orchestration system
> that this is all designed to support, has a security console that can
> be used to review the status of all the trust orchestrators that are
> supervising security workloads.  Either in the cloud, or perhaps, a
> large body of edge devices protecting critical infrastructure, if that
> doesn't give away too much.... :-)
> 
> Having the process name and executable easily visualized is fairly
> useful.
> 
> The second role is to allow the event description records to be
> self-describing.  The value for the type= key is used by the Trusted
> Modeling Agent (TMA) to determine what to look for in the remainder of
> the event description record in order to compute the CELL value.
> 
> It also contains the TASK_ID value that ties the security state points
> to the integrity of the executable.  Since that value is a synthetic
> value it was deemed most appropriate to be placed in the event{}
> field.
> 
> > > +                       process=COMM
> > > +                               Where COMM is the ASCII representation
> > > +                               of the name of the process executing
> > > +                               the event.
> > > +
> > > +                       filename=PATH
> > > +                               If the CELL definition for an event
> > > +                               references a file the filename
> > > +                               characteristic contains a definition
> > > +                               of the path to the file.
> > > +
> > > +                               In the case where an event does not
> > > +                               have a file the PATH value is set to a
> > > +                               value of none.
> > What happens in cases where multiple file paths are present in an
> > event?  Also, given this is visible to userspace, and multiple
> > things can affect the path to a file (e.g. namespaces), how is the
> > file path determined?
> 
> Unless we have missed something, which is no doubt possible, all of
> the security event hooks that we have implemented, which number about
> 87 now, that act on a 'file', receive only a single 'struct file *'
> pointer as a parameter to the event.
> 
> So we haven't encountered a situation where there would be multiple
> files for a single event description.
> 
> There is certainly the case where multiple security state points
> involve the same file.  This can easily be seen, for example, in a
> trust orchestrator running a workload in a runc container, where
> multiple state points are generated by different executable mappings
> of the runc binary at startup
> 
> The file path is the absolute pathname in the mount namespace that the
> modeled workload is running in.
> 
> See the following for details:
> 
> security/tsem/event.c:get_path()
> 
> > > +                       type=EVENT_TYPE
> > > +                               The value field for a type key is the
> > > +                               name of the security event that is
> > > +                               being modeled.  The list of value
> > > +                               EVENT_TYPE names is defined in the
> > > +                               following source file:
> > > +
> > > +                               security/tsem/tsem.c
> > > +
> > > +                               If the security event is a generically
> > > +                               modeled event the EVENT_TYPE will be
> > > +                               generic_event.  In this case the CELL
> > > +                               characteristics for the event will be
> > > +                               described by a generic_event{} field.
> > > +
> > > +                       task_id=TASK_ID
> > > +                               The value of the task_id key will the
> > > +                               ASCII base 16 representation of the
> > > +                               model identity of the task that is
> > > +                               executing the security event.
> > > +
> > > +                               The following documentation file:
> > > +
> > > +                               Documentation/admin-guide/LSM/TSEM.rst
> > > +
> > > +                               Describes how the TASK_ID value is
> > > +                               generated.
> > > +
> > > +               The COE{} field consists of the following
> > > +               characteristic definitions:
> > > +
> > > +                       uid=NN
> > > +                               The ASCII base 10 representation of
> > > +                               the numeric value of the discretionary
> > > +                               user id of the process that is
> > > +                               executing the security event.
> > Given the ability to map UID/GID values in the kernel, what will be
> > used as the basis for the COE?  What happens when the basis used in
> > the kernel's COE generation does not match the basis used by the
> > external modeler?
> 
> The UID/GID values used are the values defined in the initial
> user namespace, see security/tsem/event.c:get_COE().
> 
> The basis set state that the trust orchestrator is running in has no
> effect on the generation of the security state point.  The modeling
> engine only operates on the values presented to it and determines if
> the state point generated from the state description matches the model
> it has been requested to enforce.
> 
> If it doesn't, the event is considered to violate the trust model.
> 
> > > +                       euid=NN
> > > +                               The ASCII base 10 representation of
> > > +                               the numeric value of the effective
> > > +                               discretionary user id of the process
> > > +                               that is executing the security event.
> > > +
> > > +                       euid=NN
> > > +                               The ASCII base 10 representation of
> > > +                               the numeric value of the effective
> > > +                               discretionary user id of the process
> > > +                               that is executing the security event.
> > > +
> > > +                       suid=NN
> > > +                               The ASCII base 10 representation of
> > > +                               the numeric value of the saved user id
> > > +                               of the process that is executing the
> > > +                               security event.
> > > +
> > > +                       gid=NN
> > > +                               The ASCII base 10 representation of
> > > +                               the numeric value of the discretionary
> > > +                               group id of the process that is
> > > +                               executing the security event.
> > > +
> > > +                       egid=NN
> > > +                               The ASCII base 10 representation of
> > > +                               the numeric value of the discretionary
> > > +                               effective group id of the process that
> > > +                               is executing the security event.
> > > +
> > > +                       egid=NN
> > > +                               The ASCII base 10 representation of
> > > +                               the numeric value of the discretionary
> > > +                               effective group id of the process that
> > > +                               is executing the security event.
> > > +
> > > +                       sgid=NN
> > > +                               The base 10 ASCII representation of
> > > +                               the numeric value of the saved
> > > +                               discretionary group id of the process
> > > +                               that is executing the security event.
> > > +
> > > +                       fsuid=NN
> > > +                               The base 10 ASCII representation of
> > > +                               the numeric value of the discretionary
> > > +                               filesystem user id of the process that
> > > +                               is executing the security event.
> > > +
> > > +                       fsgid=NN
> > > +                               The ASCII base 10 representation of
> > > +                               the numeric value of the discretionary
> > > +                               filesystem group id of the process
> > > +                               that is executing the security event.
> > > +
> > > +                       cap=0xNNN
> > > +                               The ASCII base 16 representation of
> > > +                               the numeric value of effective
> > > +                               capabilities of the process that is
> > > +                               executing the security event.
> > > +
> > > +               If the CELL value for a security event includes the
> > > +               definition of a file a file{} event field will be
> > > +               included.  The following characteristics will be
> > > +               encoded in this field:
> > > +
> > > +                       flags=NN
> > > +                               The ASCII base 10 representation of
> > > +                               the flags value of the 'struct file'
> > > +                               structure that is the source of the
> > > +                               file description.
> > > +
> > > +                       uid=NN
> > > +                               The ASCII base 10 representation of
> > > +                               the discretionary user id of the file.
> > > +
> > > +                       gid=NN
> > > +                               The base 10 ASCII representation of
> > > +                               the discretionary group id of the
> > > +                               file.
> > Similar to the task UID/GID mapping questions above, there are
> > mechanisms which map the file user/group IDs, which will be used in
> > the CELL definition and how will that be resolved between the kernel
> > and an external modeler?
> 
> The answer is the same as with the COE, see the following function:
> 
> security/tsem/event.c:get_file_cell()
> 
> Once again, the TMA only operates on the event description presented
> to it and is not influenced by its own namespace.
> 
> > > +What:          /sys/fs/tsem/ExternalTMA
> > > +Date:          November 2022
> > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > +Description:
> > > +               The ExternalTMA directory is a container directory
> > > +               that hold files that will be used to export the
> > > +               security events, and their associated parameters, for
> > > +               externally modeled security domains/namespaces.
> > > +
> > > +               The files created in this directory will be named by
> > > +               the base 10 ASCII representation of the id value
> > > +               assigned to the modeling domain/namespace.  See the
> > > +               documentation for the /sys/fs/tsem/id file in this
> > > +               documentation for more details on this value.
> > > +
> > > +               This file will is a read-only file that can be polled
> > > +               by a userspace trust orchestration implementation to
> > > +               process security events that are to be modeled by
> > > +               an external Trusted Modeling Agent.
> > > +
> > > +               The type of the exported event is the first keyword of
> > > +               the line that is output and have the following
> > > +               values and arguments:
> > > +
> > > +               aggregate HEXID:
> > > +                       Where HEXID is the ASCII base 16
> > > +                       representation of the 256 bit hardware
> > > +                       platform aggregate value.
> > > +
> > > +               export pid{NNN} COE{} CELL_DEFINITION
> > > +                       Where the NNN in the pid field is the ASCII
> > > +                       base 10 value of the id of the process that is
> > > +                       executing the security event that will be
> > > +                       modeled.
> > I worry whenever I see a PID used as an identifier shared across the
> > kernel/userspace boundary as it is inherently racy.  Given the
> > somewhat coarse COE definition where one can expect multiple
> > processes/PIDs to share the same COE value, and the ability of
> > untrusted users/processes to manipulate the PID table, what do you
> > expect to use the pid{NNN} field for in this event?
> > 
> > Similar to the other namespace/mapping issues discussed previously,
> > there is also the PID namespace issue to worry about.  How is that
> > handled here?
> 
> The concern over the PID issue is understandable, I will treat the
> reasoning behind its use below.
> 
> The PID value is the 'native' value managed by the kernel, not a
> mapped value.
> 
> > > +                       The COE field has the same format as the field
> > > +                       emitted for a trajectory or forensics event.
> > > +
> > > +                       The CELL_DEFINITION are the same field
> > > +                       definitions that are emitted for a trajectory
> > > +                       or forensics event.
> > > +
> > > +               log process{name} event{type} action{type}
> > > +                       The log event is emitted when an untrusted
> > > +                       task attempts to execute a security event.
> > > +
> > > +                       The name value of the COE field is the name of
> > > +                       the process (comm value) that is executing the
> > > +                       security event.
> > > +
> > > +                       The type value of the event field is the name
> > > +                       of the security event being executed as
> > > +                       defined in the tsem_names array in the
> > > +                       security/tsem/tsem.c file.
> > > +
> > > +                       The type value of the action field is the type
> > > +                       of action the LSM enforced in response to
> > > +                       encountering the untrusted process.  This
> > > +                       value will be either LOG or EPERM to represent
> > > +                       whether or not the trust violation is being
> > > +                       logged or enforced.
> > > +
> > > +What:          /sys/fs/tsem/control
> > > +Date:          November 2022
> > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > +Description:
> > > +               The control file is the only writable file in the
> > > +               filesystem and is used by the trust orchestrators to
> > > +               configure and control the behavior of the TSEM
> > > +               implementation.
> > > +
> > > +               The following keyword and arguments are recognized:
> > > +
> > > +               internal:
> > > +                       The internal keyword causes an internally
> > > +                       modeled domain to be created for the calling
> > > +                       process.
> > > +
> > > +               external:
> > > +                       The external keyword causes an externally
> > > +                       modeled domain to be created for the calling
> > > +                       process.
> > > +
> > > +               enforce:
> > > +                       The enforce keyword causes the modeling
> > > +                       domain/namespace of the process to enter
> > > +                       enforcing mode.  In this mode a value of
> > > +                       -EPERM will be returned for a security event
> > > +                       that does not map into the current set of
> > > +                       allowed state points for the security model
> > > +                       being implemented for the domain/namespace.
> > > +
> > > +               seal:
> > > +                       The seal keyword causes the security model
> > > +                       being implemented for the model to be placed
> > > +                       in sealed state.  In this state the current
> > > +                       set of security event points is considered to
> > > +                       be the only set of valid points for the
> > > +                       domain/model.  Any subsequent events that map
> > > +                       to a point not in the current model will be
> > > +                       considered a violation of the model.
> > > +
> > > +               trusted PID:
> > > +                       The trusted keyword is used by a trust
> > > +                       orchestrator to indicate that the process
> > > +                       identified by the PID argument should be
> > > +                       allowed to run in trusted status.
> > > +
> > > +               untrusted PID:
> > > +                       The untrusted keyword is used by a trust
> > > +                       orchestrator to indicate that the process
> > > +                       identified by the PID argument should be
> > > +                       allowed to run but designated as an untrusted
> > > +                       process.
> > The 'trusted PID:' and 'untrusted PID:' commands are concerning for
> > the reasons described above about PIDs being racy and generally an
> > unreliable way of identifying processes across the kernel/userspace
> > boundary.  I suspect it would not be too difficult for a malicious
> > user to trick an external modeler into marking the wrong process as
> > trusted/untrusted.
> 
> An external TMA needs the PID value to determine which process to wake
> up and set the trust status value on in the task control structure,
> after the event is modeled.  As was noted above, the PID value is the
> unmapped value maintained by the OS.
> 
> Lets see if we can reason through why the PID can be used safely.
> 
> CAP_TRUST, or whatever ends up getting used, is required by the trust
> orchestrator to create a security/modeling namespace for the workload
> being modeled.  This results in the creation of the following
> pseudo-file for surfacing the security event descriptions for the
> namespace/workload:
> 
> /sys/fs/tsem/ExternalTMA/N
> 
> Where N is the id number of the modeling domain.
> 
> CAP_TRUST, caveats applied, is required to open the pseudo-file.  The
> trust orchestrator only receives and acts on PID values through this
> conduit from the kernel.
> 
> When an event description is exported, the trust status of the task is
> set to 'pending' and the process is placed in interruptible sleep and
> scheduled away, with the 'wakeup' criteria being the trust status
> being changed from pending to either trusted or untrusted.
> 
> The only path to change the trust status value in the LSM task control
> structure and wake up the process is by the trust orchestrator that
> created the namespace, by writing the appropriate value to the
> /sys/fs/tsem/control file.  Access to that file is gated by CAP_TRUST
> or its equivalent.
> 
> See the following code locations for further details:
> 
> security/tsem/export.c:tsem_export_event()
> 
> security/tsem/fs.c:control_COE()
> 
> As long as the process 'exists', albeit sleeping, the PID slot is
> occupied and an adversary, regardless of namespace, cannot substitute
> a task with the same PID value.
> 
> This leaves an adversary with the need to terminate the task being
> modeled in order to capture its PID slot.
> 
> Precautions are implemented in the following function to protect the
> process from being terminated by an adversary:
> 
> security/tsem/tsem.c:tsem_task_kill()
> 
> The following is a summary of the criteria that is implemented:
> 
> - Signal privileges are granted to any process with CAP_TRUST.
> 
> - A process without CAP_TRUST cannot signal a process with CAP_TRUST.
> 
> - Cross-model signaling is denied by a process without CAP_TRUST.
> 
> So that leaves us in a scenario where, outside of the modeling
> namespace, CAP_TRUST would be required to kill the process waiting to
> be modeled.  If CAP_TRUST has been lost to an adversary, the platform
> is owned and the game is over.
> 
> So that leaves us with the threat of an adversary attempting to
> implement a PID race within the modeling domain itself.
> 
> As I've noted previously in these threads, and in the LSM
> documentation proper, TSEM is about prospective generation of a
> security model, rather than retrospective correction of a MAC policy
> that has been demonstrated to have undesired effects.  The distinction
> is important in this case.
> 
> For an adversary to mount a PID race attack from within the modeled
> workload, one of three conditions must be met:
> 
> - A shell script is read.
> 
> - A malicious binary would have to be executed.
> 
> - Memory would have had to have been mapped executable.
> 
> Since TSEM captures the security events needed to implement these
> actions, the events would have had to have been incorporated into the
> security unit test for the workload or the actions would be denied.
> 
> Hopefully this analysis is complete and correct with respect to this
> threat, comments and observations are obviously welcome.
> 
> There is an opportunity to strengthen this model that I will touch on
> below.
> 
> > > +               state HEXID:
> > > +                       The state keyword is used to indicate that the
> > > +                       security state point identified by the ASCII
> > > +                       base 16 encoded value should be loaded into
> > > +                       the current security model as a valid security
> > > +                       event state.
> > > +
> > > +               pseudonym HEXID
> > > +                       The pseudonym keyword is used to indicate that
> > > +                       the pathname, identified by the 256 bit ASCII
> > > +                       base 16 encoded value HEXID, should be
> > > +                       designated to return a constant digest value
> > > +                       for the contents of the file.
> > > +
> > > +                       The HEXID value is computed with the following
> > > +                       function:
> > > +
> > > +                       HEXID = SHA256(PATHNAME_LENGTH || PATHNAME)
> > This seems like an unusual design choice, and perhaps one born from
> > necessity ... ?  It's nice that it is opt-in, but I would be curious
> > to hear what problems this solved.
> 
> It is an approximation method that allows things like log files and
> .bash_history files to be effectively modeled.
> 
> Once again, TSEM is a blending of integrity measurement and mandatory
> access controls.  In a security event that has a file as a component
> of its CELL, the SHA256 digest value of the file is included in the
> computation of the CELL identity.
> 
> These types of files have no known 'good' value, by definition.  So
> 'pseudonym' declarations implement a model approximation to provide a
> fixed digest value for a file, regardless of its contents.
> 
> The effect of this can easily be seen if one of the Quixote trust
> orchestrators is used to run a container based shell workload.  If the
> .bash_history file in the container is not zeroed before execution, or
> treated as a pseudonym, the bash shell will be tagged and 'poisoned'
> as untrusted when it reads the file.
> 
> It is a pretty solid understanding in modeling theory that
> approximations are almost universally required when dealing with
> physical phenomenon.  As a quantum chemist by training, I spent a fair
> amount of time dealing with complete, intermediate and modified
> neglect of diatomic overlap as a result of this.... :-)
> 
> > > +               base HEXID
> > > +                       The base keyword is used to indicate that the
> > > +                       256 bit ASCII base 16 encoded value HEXID
> > > +                       should be registered as the value used to
> > > +                       generate model specific security event points.
> > > +
> > > +                       A model specific base value is designed to be
> > > +                       used as a 'freshness' nonce, similar to an
> > > +                       attestation nonce, to prove that a model state
> > > +                       value or measurement is current and not being
> > > +                       replayed.
> > > diff --git a/Documentation/admin-guide/LSM/tsem.rst b/Documentation/admin-guide/LSM/tsem.rst
> > > new file mode 100644
> > > index 000000000000..f03e5269cd25
> > > --- /dev/null
> > > +++ b/Documentation/admin-guide/LSM/tsem.rst
> > > @@ -0,0 +1,1240 @@
> > > +====
> > > +TSEM
> > > +====
> > 
> > ...
> > 
> > > +Process and Platform Trust Status
> > > +=================================
> > > +
> > > +A fundamental concept in TSEM is the notion of providing a precise
> > > +definition for what it means for a platform or workload to be trusted.
> > > +A trusted platform or workload is one where there has not been an
> > > +attempt by a process to execute a security relevant event that does
> > > +not map into a known security state point.
> > > +
> > > +The process trust status is a characteristic of the process that is
> > > +passed to any subordinate processes that are descendants of that
> > > +process.  Once a process is tagged as untrusted, that characteristic
> > > +cannot be removed from the process.  In a 'fruit from the poisoned
> > > +vine' paradigm, all subordinate processes created by an untrusted
> > > +process are untrusted as well.
> > > +
> > > +On entry into each TSEM security event handler, the trust status of a
> > > +process is checked before an attempt to model the event is made.  An
> > > +attempt to execute a security event by an untrusted process will cause
> > > +the event, and its characteristics, to be logged.  The return status
> > > +of the hook will be determined by the enforcement state of the model.
> > > +A permission denial is only returned if the TMA is running in
> > > +enforcing mode.
> > > +
> > > +If the platform running the TSEM LSM has a TPM, the hardware aggregate
> > > +value is computed at the time that TSEM is initialized.  This hardware
> > > +aggregate value is the linear extension sum over Platform
> > > +Configuration Registers (PCR's) 0 through 7.  This is the same
> > > +aggregate value that is computed by the Integrity Measurement
> > > +Architecture (IMA) and is the industry standard method of providing an
> > > +evaluation measurement of the hardware platform state.
> > > +
> > > +Internally model domains have the hardware aggregate measurement
> > > +included as the first state point in the security model.  Externally
> > > +modeled domains export the hardware aggregate value to the TMA for
> > > +inclusion as the first state point of the model maintained by the TMA.
> > > +
> > > +The root modeling domain extends each security state point into PCR
> > > +11.  This allows hardware based TSEM measurements to coexist with IMA
> > > +measurement values.  This hardware measurement value can be used to
> > > +attest to the security execution trajectory that the root model
> > > +maintains.
> > It seems like making the target PCR configurable would be a good
> > idea, at the very least make it a Kconfig option.
> 
> That was something that we have thought about, it probably needs a
> Kconfig option.
> 
> Contrary to all appearances, as a team we are really minimalists at
> heart and tend to not make things more complex or configurable than
> needed.... :-)
> 
> > Also, can you elaborate on how the security state points are
> > extended into the PCR?  I imagine for it to be useful at an
> > arbitrary point in time this would require the PCR to be extended as
> > the security points were generated, which would imply that the PCR
> > value would be dependent on execution order, and in most cases,
> > scheduling order as well.  How useful do you expect this to be for
> > most users?
> 
> Your assessment is correct, the state points are extended into the PCR
> whenever a unique security state point is generated.
> 
> In a 'free-running' model, the value in the register will be fungible
> due to scheduling dependencies.
> 
> If the model is pre-defined, the security state points will be
> extended into the register as they are loaded through the
> /sys/fs/tsem/map pseudo-file interface.  In this case, the value will
> be fixed and any departure from the value would signal that the
> modeling domain has departed from its specification.
> 
> With respect to the utility of the value, in a 'free-running' model it
> is about as useful as the value that IMA maintains in PCR 10, which in
> our opinion is not very useful and is why we implemented the notion of
> the 'state' value of a model.
> 
> The primary utility of the value is that it is a hardware maintained
> reference value that can be used to confirm the set of measurements
> committed to the register.
> 
> So our 'state' value gives us a constant 'good' value for the security
> model.  The PCR 11 value provides a hardware root of trust for the set
> of points that lead to the state value.
> 
> > > +Internal vs external modeling
> > > +-----------------------------
> > > +
> > > +When a TSEM modeling domain is created, a designation is made as to
> > > +whether the domain is to be internally or externally modeled.
> > > +
> > > +In an internally modeled domain, the security event handlers pass the
> > > +event type and its characteristics to the designated internal trusted
> > > +modeling agent.  The agent provides the permission value for the
> > > +security event handler to return as the result of the event and sets
> > > +the trust status of the process executing the event.
> > > +
> > > +In an externally modeled domain, the event type and parameters are
> > > +exported to userspace for processing by a trust orchestrator with an
> > > +associated TMA.  The trust orchestrator communicates the result of the
> > > +modeling back to the kernel to support the setting of the process
> > > +trust status.
> > > +
> > > +This model poses a limitation to the ability of TSEM to model some
> > > +security events.  This is secondary to the fact that some event
> > > +handlers (LSM hooks) are called from a non-sleeping context, as a
> > > +result the process cannot be scheduled.  This is particularly the case
> > > +with the task based hooks, since they are typically called with the
> > > +tasklist lock held.
> > > +
> > > +This limitation is also inherent to the root model that extends the
> > > +security state points into TPM PCR 11, secondary to the fact that the
> > > +process invoking the security event hook will be scheduled away while
> > > +the TPM transaction completes.
> > > +
> > > +Addressing this problem directly requires a consideration of the
> > > +context from which the security event handlers are being called.
> > > +Subsequent implementations of TSEM will include a mechanism for
> > > +asynchronous deferral of model processing, until when and if, a review
> > > +of the call context would be considered worthwhile by the LSM
> > > +community.
> > This is a pretty big limitation, and in conjunction with the some of
> > the other issues brought up earlier (the PID issue seems the most
> > concerning), I'm having a difficult time believeing that an external
> > modeler could operate safely given the design presented here.
> 
> With respect to the PID issue, we would welcome any comments on the
> analysis that we provided above as to its design safety.
> 
> If the PID issue remains a concern, we have an extension to the export
> descriptions that would include a random nonce that would be emitted
> with the PID.  The nonce would be placed in the LSM task control
> 'blob' for the sleeping task and used to confirm that the task release
> directive was acting on the correct process.
> 
> > Unfortunately, there will always be LSM hooks which need to operate
> > in a non-blocking context, meaning this challenge is here to stay.
> > Help me understand how you could safely do asynchronous policy
> > enforcement with an external modeler, I'm not sure it's possible.
> 
> Electing to implement asynchronous enforcement would require further
> thought.  We were operating in the context of full disclosure in our
> documentation and wanted to be up front about limitations and options.
> 
> To be clear, at this time, we are not advocating for or bringing
> forward an asynchronous update architecture.
> 
> So, at this time, there is a well understood modeling limitation with
> respect to the LSM hook implementations.  That limitation is not
> limited to external TMA's, since the event state points cannot be
> extended into a TPM in a non-blocking context.
> 
> So far we have only run into a handful of these events, almost
> exclusively due to the LSM hooks being called with the tasklist lock
> held.  I see that Linus commented a couple of weeks ago that the
> tasklist lock is our last big lock that may need to be looked at.
> 
> With respect to the need for external modeling, as is the case with
> all security designs, this is a cost/benefit decision.
> 
> In some cases, for example SGX, using external modeling is the only
> option, since executing in the context of an SGX enclave is not
> possible from the kernel.  Quixote/TSEM is actually one of the unsung
> 'killer' applications for SGX, at least from our long involvement with
> the technology.
> 
> Having an external modeling option also means that you don't need to
> get code into the kernel proper in order to implement a security model
> that may be useful.  I think we all can appreciate the utility and
> importance of that.
> 
> We believe that the ability to do dedicated hardware security
> co-processors is important.  External modeling opens the door to
> democratize how that can be done.
> 
> The binary Quixote distribution includes firmware for an
> NRF52840-DONGLE implementation of a TMA.  So you have a clear
> demonstration of the opportunity to create 'Yubikey' type devices to
> enforce kernel security.
> 
> A reasonably interesting option for entities distributing dedicated
> Linux based devices, where for a few dollars you can include a USB
> based co-processor that would provide hardware based protections to
> prevent an embedded Linux implementation from being diverted from its
> design intent.
> 
> Truth be told, after having looked at countless execution
> trajectories, processes are typically locked into untrusted status
> before they get to any of the non-blocking hooks.
> 
> > Frankly, I also wonder how a system would perform with an external
> > modeler, indepdent of the issues with non-blocking hooks.  How does
> > the system perform with every blockable LSM hook invocation
> > potentially blocking on a response from userspace?  Or with the COE
> > being somewhat coarse, does the trajectory/policy populate itself
> > quickly?
> 
> One obviously experiences a latency hit in going to userspace, by
> definition, implementing security always has an associated resource
> cost.  So, once again, this comes down to a cost/benefit analysis.
> 
> As a Gedanken exercise, consider the value proposition of a Linux
> based RTU, or other device, controlling infrastructure that can only
> execute security relevant events that are guaranteed to be known good
> by an external co-processor that is only accessible as a security
> oracle.
> 
> Given that frame of reference.
> 
> Time for a userspace or SGX based TMA transaction is running around
> 890 micro-seconds.
> 
> Going to a TMA based in a Xen stubdomain implementation runs a bit
> longer, probably around 940 micro-seconds or so.
> 
> The micro-controller implementations are decidedly slower, with the
> NRF52840-DONGLE clocking in at around 40 micro-seconds, but that is
> strictly a CPU horsepower issue.
> 
> All of this with the caveat that we have been focusing almost
> exclusively on correctness and not optimizing performance.
> 
> We've thought a bit, mainly on long walks with our Golden Retriever
> Izzy, about the issue of building a kernel based policy cache with
> externally modeled domains.  Given that the kernel does not, a-priori,
> know what modeling algorithm a TMA might be using, we would need to
> come up with a method of deterministically mapping a security event
> description to a known good state point value.
> 
> The other issue with all this is that with containerized workloads,
> particularly micro-services, the rate of security event generation can
> be surprisingly low.  Obviously this is also the case with embedded
> implementations.
> 
> Once again, what are you willing to pay to be safe?
> 
> > > +Event handlers that cannot be directly modeled, still consider, on
> > > +entry, whether or not they are being called by an trusted or untrusted
> > > +process.  As a result, an untrusted process will cause a non-modeled
> > > +event to return a permissions violation in enforcing mode, even if the
> > > +security event cannot be directly modeled.
> > > +
> > > +Security event modeling typically traps violations of trust by a COE
> > > +with unmodeled characteristics that is attempting to access/execute a
> > > +file or map memory as executable; or by a COE with known
> > > +characteristics attempting to access or execute a CELL not prescribed
> > > +by a model.  As a result, the impact of the ability to not directly
> > > +model these events is lessened.
> > 
> > ...
> > 
> > > +Event modeling
> > > +--------------
> > > +
> > > +TSEM security event modeling is based on the following functional
> > > +definition for a security state point:
> > > +
> > > +Sp = SHA256(SHA256(EVENT_ID) || TASK_ID || SHA256(COE) || SHA256(CELL))
> > It appears that all of the hasing in TSEM is SHA256 based, you might
> > want to consider making that a Kconfig option at the very least.
> 
> That has been something that we have talked about as well.
> 
> As I indicated previously, we really are minimalists, particularly
> after watching IMA fight with issues surrounding algorithmic agility.
> 
> It would be easy enough to make this configurable but does anyone see
> SHA256 as not being useful in in this role anywhere in the next 10
> years?
> 
> > paul-moore.com
> 
> Hopefully all of this is useful moving forward.
> 
> Have a good day.
> 
> As always,
> Dr. Greg
> 
> The Quixote Project - Flailing at the Travails of Cybersecurity


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 02/14] Add TSEM specific documentation.
  2023-02-14 12:18       ` Roberto Sassu
@ 2023-02-15 16:26         ` Dr. Greg
  0 siblings, 0 replies; 42+ messages in thread
From: Dr. Greg @ 2023-02-15 16:26 UTC (permalink / raw)
  To: Roberto Sassu; +Cc: Paul Moore, linux-security-module

On Tue, Feb 14, 2023 at 01:18:45PM +0100, Roberto Sassu wrote:
> On Tue, 2023-02-14 at 05:58 -0600, Dr. Greg wrote:
> > Our personal prejudice is that these types of measurements are of
> > limited value, which is why we introduce in TSEM, the notion of the
> > 'state' value for a model, discussed below.
> > 
> > I would have to go looking on lore for a reference to the exact thread
> > but Roberto Sassu had offered up a patch set for IMA that addressed
> > the deficiency of these types of measurements.

> Hi Greg

Good morning Roberto, thank you for taking the time to follow up,
pleasant to hear from you.

> yes, this:
> 
> https://lore.kernel.org/linux-integrity/20210914163401.864635-1-roberto.sassu@huawei.com/
> 
> DIGLIM makes the PCR extended with software measurements deterministic,
> independent from how processes are scheduled, at the cost of not
> knowing if files with matching digests from a list were accessed or
> not, and in which order.

Yes, DIGLIM, I remember the patch series you sent out but couldn't put
a name to it when I wrote the reply to Paul.

Our efforts and work share the same issues with respect to the
indeterminism of strictly linear extension measurements, particularly
now in the age of ubiquitous SMP.

The 'state' value supported by the Quixote model is designed to
address the same problem and has worked extremely well for us.  Our
implementation only sorts the security state event points that have
been 'touched' by the execution trajectory, so it does provide a
measurement of the events that have occurred.

Like DIGLIM, you lose the the ordering of the events, but we also
provide the linear sequence of security state points, and its classic
measurement value, if one wants to go down the rabbit hole of figuring
out if the integrity of the system has been affected by process
scheduling.

Frankly, I don't see the current state of the art in trusted systems
being in a position to worry about that at this point in time.

> But, in exchange, you can seal a TLS key to IMA measurements that is
> available for handshakes as long as the system does not execute
> something unknown. After that, you have to reboot to use the key
> again.

The same rationale for why we developed the notion of the model
'state' value.

We also look at the 'state' value as a method for a containerized
workload, coming out of a CI/CD development framework, to provide an
attestation of a single value to indicate whether or not the workload
is correct or trusted.

We believe this will become increasingly important as technologies
like TDX, and AMD's equivalent come forward, that will be requiring
attestation as a function of the 'boot' sequence.

> (Didn't read your proposal yet.)

Once you get a chance to look at Quixote/TSEM and things settle down
for us a a bit, we should chat about a common kernel framework for
cacheing digest values as our needs are quite similar.  There would
seem to be no compelling reason to build separate implementations of
the same technology.

Our current digest cache was only driven by the mandates of simplicity
and correctness.  Our plans are to add the equivalent of a Bloom
filter in front of a bucket of lists that key on the MSB of the digest
value.  If I remember correctly, you had expended efforts on
optimizing your implementation.

One ends up with a lot of security event state points when you boot a
modern general purpose Linux administration.

> Roberto

Thanks again, will look forward to chatting about these issues
further.

Have a good remainder of the week.

As always,
Dr. Greg

The Quixote Project - Flailing at the Travails of Cybersecurity

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 08/14] Implement TSEM control plane.
  2023-02-12  6:54         ` Dr. Greg
@ 2023-02-16  6:53           ` Greg KH
  2023-02-18 18:03             ` Dr. Greg
  0 siblings, 1 reply; 42+ messages in thread
From: Greg KH @ 2023-02-16  6:53 UTC (permalink / raw)
  To: Dr. Greg; +Cc: linux-security-module, paul

On Sun, Feb 12, 2023 at 12:54:40AM -0600, Dr. Greg wrote:
> On Sat, Feb 11, 2023 at 11:59:19AM +0100, Greg KH wrote:
> 
> Looping in Paul Moore in order to get his thoughts.
> 
> > On Fri, Feb 10, 2023 at 06:18:06PM -0600, Dr. Greg wrote:
> > > On Thu, Feb 09, 2023 at 12:30:51PM +0100, Greg KH wrote:
> > > 
> > > Good afternoon Greg, thanks for taking the time to review the patches
> > > and pass along comments.
> > > 
> > > > On Fri, Feb 03, 2023 at 11:09:48PM -0600, Dr. Greg wrote:
> > > > > The fs.c file contains the implementation of the TSEM control
> > > > > plane that is in the form of a pseudo-filesystem mounted on the
> > > > > following directory:
> > > > > 
> > > > > /sys/fs/tsem
> > > 
> > > > Why are you using sysfs to mount this?
> 
> > > We followed the lead of the SMACK and SeLinux LSM's, both of which
> > > create the mount points for their control plane filesystems in
> > > /sys/fs.
> > > 
> > > In addition, as a filesystem, we chose to have tsemfs closely follow
> > > their design for continuity across the LSM's.  So they share similar
> > > functionality and design, modulo of course, the event description and
> > > trajectory export files that we will chat about below.
> > > 
> > > We can't use securityfs, secondary to the fact that it doesn't
> > > implement pollable files, which are a requirement for trust
> > > orchestrators based on external Trusted Modeling Agents.
> 
> > Why not fix securityfs to provide pollable files?  Other than that,
> > why can't you just use securityfs?
> 
> Now that we have had some additional bandwidth to look at issues after
> the first round release, it may be more straight forward to implement
> the pollable files in securityfs than we thought.  We will take
> another run at this and see what is possible without having to meddle
> with the internals of securityfs proper.

It's ok to mess around with securityfs to get it to work properly for
your use case, there's no reason to create a whole new filesystem just
because of one missing functionality.

> As the diffstat for the patch series indicates, we spent considerable
> time working to implement TSEM without touching anything outside its
> implementation directory.  I think this is something that anyone who
> has tried to upstream functionality into the mainline kernel would
> understand the merit of.

No, that's not how kernel development works, it's ok to touch other
portions when needed, otherwise you duplicate lots of extra code and
functionality as you are doing here.  Please do not do that.

> > You are creating a new structure-type-api here, why not use a
> > already-designed protocol instead like varlink if you need userspace
> > to parse events in an atomic way?  Or heck even json would be better
> > as there are universal userspace tools for that today.
> 
> As an industry, we are in the middle of a software supply chain
> security crisis.

That has nothing to do with the kernel, sorry.

> In a trust orchestrated architecture, the trust
> orchestrators, and their Sancho TMA implementations, are the most
> security critical components on the system.  Our objective is to keep
> the supply chain footprint for Quixote as small as possible.
> 
> To that point:
> 
> size /usr/local/lib/libyajl.so.2.1.1:
>    text    data     bss     dec     hex filename
>   33333     784      16   34133    8555 /usr/local/lib/libyajl.so.2.1.1
> 
> size /u/usr/sources/quixote-1.4/SecurityModel/EventParser.o
>    text    data     bss     dec     hex filename
>    2520       0       0    2520     9d8 /u/usr/sources/quixote-1.4/SecurityModel/EventParser.o
> 
> If we were to use JSON, we would use yajl, it is probably as light as
> anything out there.  Given that, on face value, this would represent
> over an order of magnitude increase in code size to achieve the same
> objective, plus add an external dependency.

So you require people to trust your custom parser and format just
because you don't want to rely on a trusted tool that the whole world
depends on?

Again, not a valid argument, sorry, please use common parsing tools
otherwise you are guaranteed to make mistakes and everyone will have to
rely on your custom tools only, which is not something that you would
accept from any other kernel change.

And I don't see a link to the userspace tools anywhere, did I miss it?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 04/14] Implement CAP_TRUST capability.
  2023-02-13 18:02       ` Casey Schaufler
@ 2023-02-16 21:47         ` Dr. Greg
  0 siblings, 0 replies; 42+ messages in thread
From: Dr. Greg @ 2023-02-16 21:47 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: linux-security-module, linux-integrity, linux-kernel, shallyn, corbet

On Mon, Feb 13, 2023 at 10:02:16AM -0800, Casey Schaufler wrote:
> On 2/13/2023 3:43 AM, Dr. Greg wrote:
> > On Sat, Feb 04, 2023 at 06:54:20PM -0800, Casey Schaufler wrote:
> >
> > Looping in some others, given that this issue is fundamental to
> > influencing how Linux can do security, also Sergey who raised a
> > similar issue to Casey.
> >
> > Apologies for the delay in responding to this, catching up on issues
> > after a week of travel.
> >
> >> On 2/3/2023 9:09 PM, Dr. Greg wrote:
> >>> TSEM was designed to support a Trust Orchestration System (TOS)
> >>> security architecture.  A TOS based system uses the concept of a
> >>> minimum Trusted Computing Base of utilities, referred to as trust
> >>> orchestrators, that maintain workloads in a trusted execution
> >>> state.  The trust orchestrators are thus, from a security
> >>> perspective, the most privileged assets on the platform.
> >>>
> >>> Introduce the CAP_TRUST capability that is defined as a
> >>> capability that allows a process to alter the trust status of the
> >>> platform.  In a fully trust orchestrated system only the
> >>> orchestrators carry this capability bit.
> >> How is this distinguishable from CAP_MAC_ADMIN?
> > CAP_TRUST is being introduced to enable Linux security architects to
> > ontologically differentiate processes that are allowed to modify
> > security guarantees based on deontological (rule-based) predicates
> > from processes allowed to modify security guarantees that are based on
> > narratival (event-based) predicates.
> >
> > More generally, but less accurately, it allows security architectures
> > to be shaped by both Kantian and Hegelian logic perspectives. [0]
> >
> > Given that the above will probably not be seen as an overly compelling
> > argument, in and of itself .... :-), some technical observations in
> > support of CAP_TRUST
> >
> > Dictating to the choir here, but a brief background for those
> > following this discussion with an interest in security issues.
> >
> > In general, classic mandatory access controls (MAC) are policy based.
> > For example, the standard bearers, SMACK and SeLinux, use classic
> > subject/object philosophies.  A process (subject) has a role/label
> > attached to it and objects acted on by the processes have a label
> > associated with them.  Policies, that can be viewed as rules, usually
> > quite elaborate and detailed for a whole system security policy, are
> > developed that define how subject labels may or may not interact with
> > object labels.
> >
> > TSEM introduces an alternate notion of a security policy, defined as a
> > security model in TSEM parlance, that is created by unit testing of a
> > platform or workload.  Precise descriptions of the security events
> > generated by the testing are captured and used to maintain subsequent
> > executions of the workload in a known security or trust state.

> There's nothing fundamentally new here.  You are claiming the common
> practice of looking at the audit trail to develop "policy" is a new
> "alternative notion" for security.

We do apologize to everyone spending any time on this, for the paucity
of our thought processes and innovation, hopefully people will still
shake hands with us if our paths happen to cross in the future.

Innovation takes many forms, let me see if I can illuminate why we
think there might be at least some kind of a new take on things in all
of this.

For the record, we are not proposing to look at an audit trail of a
policy implementation that is incorrect for its workload, in an
attempt to fix it.

TSEM is about providing infrastructure for bringing CI/CD
methodologies, an accepted standard practice in software quality
programs, to the prospective development of security models that are
very specific, correct and complete for an intended workload.

Good or bad, the world seems to have moved to resource
compartmentalization and containers, TSEM is about acknowledging this
and providing support for these architectures.

A primary objective with all of this is to avoid having to go back to
the well and fix a generic system-wide policy that ends up being
wrong, for whatever reason.  In some of the environments that
Quixote/TSEM is intended for, that potentially involves rolling a
truck to someplace remote.

> You are familiar with SELinux's audit2allow I assume.

Yes, quite so.

For those reading along at home, the following description of the tool
and its usage may be helpful:

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/selinux_users_and_administrators_guide/sect-security-enhanced_linux-troubleshooting-fixing_problems

As the URL itself indicates, it is a tool for troubleshooting and
fixing problems with a policy, after the policy has been diagnosed to
have an error in its security description of a platform.

The documentation states, multiple times and quite explicitly, that if
you have to use the tool, there is a 'bug' in the policy.  It also
recommends reporting this to the policy development team.

Succinctly; Quixote/TSEM is about prospectively developing a correct
security model for a workload, audit trail diagnosis is about
retrospectively fixing an incorrect policy.

We certainly don't indict the tool or the methodologies involved, they
are well understood, we just think there is the possibility of doing
better.

With Quixote/TSEM we are focused on providing alternative security
infrastructure that increases the likelihood of a security model being
correct for a workload, hopefully eliminating the need to fix the
policy after it is found to break a workload.

Which, if history, experience and the search engines are correct;
results in people simply turning off policy enforcement to eliminate
the problems it is producing.

From our perspective, biased of course, it would seem to qualify as
innovation if it were, at once, both simple and reliable, to develop a
policy/model that could lead to correct mandatory enforcement
decisions.  Particularly if it helps avoid people shutting off the
technology because they find it bothersome.

To further the notion of why Quixote/TSEM is being introduced, consider
the document at the following URL:

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/using_selinux/writing-a-custom-selinux-policy_using-selinux

Which carries the following description, with respect to its contents:

"This section guides you on how to write and use a custom policy that
 enables you to run your applications confined by SeLinux."

The document provides guidance to developers so that their
applications can be protected by SeLinux, given that platform
reference policies may not know about the needs of an added
application.

It may be useful for readers to compare those procedures, to the
procedure that we document for building a prospective security model
with Quixote/TSEM.  That procedure can be found in the TBDHTTRAD
section of the TSEM LSM documentation.

What should also be noted, and easy to find since it is
highlighted in red in the RedHat documentation, is the following:

Warning:

"Use only rules provided by Red Hat.  Red Hat does not support
 creating SELinux policy modules with custom rules, because this falls
 outside of the Production Support Scope of Coverage.  If you are not
 an expert, contact your Red Hat sales representative and request
 consulting services."

As the TSEM LSM documentation notes, we are concerned with making
higher levels of security easier to obtain for development teams, as a
natural result of the software development process.

Once again, biased as we may be, that seems like innovation.
Particularly if it allows developers to implement better security
without violating the software license agreement for the operating
system.

I think everyone reading this has been around long enough to know that
if security is hard to do, it doesn't get done, even more so if it
costs extra money.

> > Both approaches are considered 'mandatory' in nature, since userspace
> > cannot modify, in the case of policy based systems the labeling, or in
> > event based systems the security model being enforced.  Unless of
> > course a process has been assigned the capability to do so, hence this
> > discussion.
> >
> > We are proposing CAP_TRUST as the privilege that is required by
> > processes to maintain the security state of a workload based on a set
> > of known valid security events.  In theory, and practice, it is
> > orthogonal to the actions permitted by CAP_MAC_ADMIN.  Although,
> > obviously, the intent of all these systems is to maintain a known
> > security state, however different those schemes may be from a
> > methodological perspective.

> I read this as an argument for using CAP_MAC_ADMIN.

So it appears as if we disagree.

I posted a response to questions that Paul had raised after going
through the documentation.  Perhaps those discussions may provide
additional rational for why CAP_TRUST is being proposed.

> > In security architectures, the concept of 'trust' has connotated the
> > notion of having a cryptographic guarantee of the state of a system.
> > As the cover letter and documentation discuss, TSEM is about blending
> > integrity measurement and mandatory access controls.
> >
> > Trust orchestrators are designed to provide an attestation that a
> > workload has not deviated in any way from a previously defined
> > security model, CAP_TRUST is the privilege required to influence this
> > guarantee.  Once again, we view this as a different concept and
> > objective than the ability to modify a security policy.

> This is (to my simple mind) indistinguishable from the way SELinux
> is used in distributions. SELinux does not require a CAP_TRUST, and
> only uses CAP_MAC_ADMIN in certain unlikely error conditions which I
> believe you don't encounter.

A couple of points to consider.

The classic subject/object based MAC implementations provide a static
rules implementation that govern access rights of a process to
resources.  If they operate correctly, the platform is secure with
respect to the implemented policy.  Unless we have missed something,
the implementations do not offer a cryptographic attestation of the
state of the system to an external entity.

Events based trust orchestration is a dynamic process that evaluates
the characteristics of a security event for correctness with respect
to a previously defined model.  In addition to enforcing conformance
to the security model, the trust orchestrators are designed to provide
an attestation of the correctness of the enforcement.

In order to generate, and simplify the models, TSEM implements the
concept of security domains/namespaces, so the security models can be
scoped specifically to the workload.  This obviously needs to be a
privileged operation, we believe different from CAP_MAC_ADMIN, in
order to avoid having an adversary create a modeling domain under
their own security controls that could be used to avoid attestation of
its existence.

I know Casey has indicated in that past that he has no little or no
interest in TPM's, and I assume by extension, things like attestation.
Confidential computing, whether you believe in it or not, is going to
make attestation important, since a workload can't boot without it.
Quixote/TSEM, again, is about reducing barriers to developers being
able to implement it.

This debate seems to have come down to the fact that since both policy
and event based methodologies result in a mandatory access control
decision, the ability to control the implementation of both strategies
should come under CAP_MAC_ADMIN.

While they both end up providing mandatory access control decisions,
they do so by significantly different processes with different
security requirements, hence the introduction of CAP_TRUST.

As we have also noted previously, CAP_TRUST would seem more
appropriate to Stefan's IMA namespace work than CAP_MAC_ADMIN, given
that IMA is also about establishing a proclamation of trust to an
external entity.

> > Perhaps most importantly, TSEM shouldn't be viewed as an either/or
> > proposition when it comes to classic subject/object MAC
> > implementations.  A differentiation between CAP_TRUST and
> > CAP_MAC_ADMIN is needed in order to allow both architectures to work
> > together in a collaborative fashion.
> >
> > It would be perfectly reasonable to believe that a TSEM modeled
> > workload would implement MAC (rules based) security controls.  In
> > order to achieve event based security guarantees, a trust orchestrator
> > drops CAP_TRUST for the workload process chain.  If CAP_MAC_ADMIN were
> > used, it would potentially impair the ability of the workload to
> > implement MAC policies, hence the desire to keep the privileges
> > orthogonal.

> If you're giving the workload process chain the ability to modify
> the configuration of another LSM you are already on marshy ground.

I'm a simple guy too, didn't grow up on Long Island though, grew up in
the bog country of northeastern Minnesota, where people were referred
to as 'swamp-stompers'.  I know marshy ground really well, worked the
bog country with a chainsaw at -25 in the winter, cutting wood to heat
our house, since it was the only time you could walk on that ground,
let alone get trucks in to haul wood.

Your comment about being on marshy ground would seem to represent a
misunderstanding that I want to clarify so there are no further
misunderstandings about this moving forward.  TSEM does not modify, in
any way, the configuration of other LSM's in the stack, nor are we
proposing that, we are leaving that can of worms to BPF... :-)

Let me, again, clarify the point I was making.  Since it seems to have
been misunderstood and is relevant to larger conversations that Paul
is having with respect to integrating IMA into the LSM architecture.

TSEM is generic security modeling architecture that provides the
infrastructure needed for implementing integrity measurement functions,
strictly in the context of the LSM architecture itself.
Simplistically, all that is needed is a model implementation that only
handles the file_open and mmap_file hooks and treats the digest value
as the only characteristic in the CELL identity.

Label based MAC's need to have protection against offline 'Evil
{Maid,Butler}' attacks to be fully robust.  For those reading along at
home, the IMA implementation of those protections is in the following
directory in the kernel source tree:

security/integrity/evm

This isn't an issue that we are conjuring up, IBM wrote that code 18
years ago to address this issue.

If one were to implement an extended attribute security model, TSEM
would return -EPERM if the attributes being accessed were inconsistent
with the security model that the workload had been unit tested to.
The current LSM model is that the first denial 'wins'.  If TSEM were
in the call stack, before a label based MAC, access to an attribute
modified by an adversary would be denied before it could influence the
subject/object policy decision.

If an LSM returning a permission denial is somehow 'meddling' with
another LSM's configuration, than it would seem like the whole LSM
stacking architecture is on 'marshy' ground.  It would also seem to
call into question Paul's vision for bringing IMA into full communion
with the LSM architecture.

I would have to check lore, but I believe I saw an e-mail from Mimi go
by not too long ago commenting that when/if IMA/EVM were to become an
LSM, it would have to go 'early', in order for it to work.

So, if the trust orchestrators use and drop CAP_MAC_ADMIN, the
processes in the modeled workload would not have access to the
privileges needed to do whatever might need to be done via that
capability to manage a MAC policy being used in the workload.

Hopefully all of this helps further frame the conversation.

Have a good remainder of the week.

As always,
Dr. Greg

The Quixote Project - Flailing at the Travails of Cybersecurity

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 08/14] Implement TSEM control plane.
  2023-02-16  6:53           ` Greg KH
@ 2023-02-18 18:03             ` Dr. Greg
  0 siblings, 0 replies; 42+ messages in thread
From: Dr. Greg @ 2023-02-18 18:03 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-security-module, paul

On Thu, Feb 16, 2023 at 07:53:28AM +0100, Greg KH wrote:
> On Sun, Feb 12, 2023 at 12:54:40AM -0600, Dr. Greg wrote:
> > On Sat, Feb 11, 2023 at 11:59:19AM +0100, Greg KH wrote:
> > 
> > Looping in Paul Moore in order to get his thoughts.
> > 
> > > On Fri, Feb 10, 2023 at 06:18:06PM -0600, Dr. Greg wrote:
> > > > On Thu, Feb 09, 2023 at 12:30:51PM +0100, Greg KH wrote:
> > > > 
> > > > Good afternoon Greg, thanks for taking the time to review the patches
> > > > and pass along comments.
> > > > 
> > > > > On Fri, Feb 03, 2023 at 11:09:48PM -0600, Dr. Greg wrote:
> > > > > > The fs.c file contains the implementation of the TSEM control
> > > > > > plane that is in the form of a pseudo-filesystem mounted on the
> > > > > > following directory:
> > > > > > 
> > > > > > /sys/fs/tsem
> > > > 
> > > > > Why are you using sysfs to mount this?
> > 
> > > > We followed the lead of the SMACK and SeLinux LSM's, both of which
> > > > create the mount points for their control plane filesystems in
> > > > /sys/fs.
> > > > 
> > > > In addition, as a filesystem, we chose to have tsemfs closely follow
> > > > their design for continuity across the LSM's.  So they share similar
> > > > functionality and design, modulo of course, the event description and
> > > > trajectory export files that we will chat about below.
> > > > 
> > > > We can't use securityfs, secondary to the fact that it doesn't
> > > > implement pollable files, which are a requirement for trust
> > > > orchestrators based on external Trusted Modeling Agents.
> > 
> > > Why not fix securityfs to provide pollable files?  Other than that,
> > > why can't you just use securityfs?
> > 
> > Now that we have had some additional bandwidth to look at issues after
> > the first round release, it may be more straight forward to implement
> > the pollable files in securityfs than we thought.  We will take
> > another run at this and see what is possible without having to meddle
> > with the internals of securityfs proper.

> It's ok to mess around with securityfs to get it to work properly
> for your use case, there's no reason to create a whole new
> filesystem just because of one missing functionality.

As I noted before, we followed the lead of SMACK and SeLinux, both of
which have their filesystems planted in /sys/fs.

Paul, FWIW, it may be worthwhile to add something to the LSM authors
guidance indicating that, moving forward, any control plane filesystem
functionality should be placed in securityfs, in order to avoid
wasting both developer and reviewer bandwidth.

> > As the diffstat for the patch series indicates, we spent considerable
> > time working to implement TSEM without touching anything outside its
> > implementation directory.  I think this is something that anyone who
> > has tried to upstream functionality into the mainline kernel would
> > understand the merit of.

> No, that's not how kernel development works, it's ok to touch other
> portions when needed, otherwise you duplicate lots of extra code and
> functionality as you are doing here.  Please do not do that.

Not the place for it here, but there is an interesting conversation
regarding Linux kernel development to be had, regarding the economic
barriers to mainstreaming code, that is posed by the 'Serving multiple
masters dilemma'.

> > > You are creating a new structure-type-api here, why not use a
> > > already-designed protocol instead like varlink if you need userspace
> > > to parse events in an atomic way?  Or heck even json would be better
> > > as there are universal userspace tools for that today.
> > 
> > As an industry, we are in the middle of a software supply chain
> > security crisis.

> That has nothing to do with the kernel, sorry.

A quick response to that, just for the historical record.

In a trust orchestrated system, the most security critical code
running are the TMA's, much more so than a TPM, since the TMA's
determine the security state of the kernel.  It has thus far seemed
wise to us to minimize the security scope and range of the
implementations as much as possible.

> > In a trust orchestrated architecture, the trust
> > orchestrators, and their Sancho TMA implementations, are the most
> > security critical components on the system.  Our objective is to keep
> > the supply chain footprint for Quixote as small as possible.
> > 
> > To that point:
> > 
> > size /usr/local/lib/libyajl.so.2.1.1:
> >    text    data     bss     dec     hex filename
> >   33333     784      16   34133    8555 /usr/local/lib/libyajl.so.2.1.1
> > 
> > size /u/usr/sources/quixote-1.4/SecurityModel/EventParser.o
> >    text    data     bss     dec     hex filename
> >    2520       0       0    2520     9d8 /u/usr/sources/quixote-1.4/SecurityModel/EventParser.o
> > 
> > If we were to use JSON, we would use yajl, it is probably as light as
> > anything out there.  Given that, on face value, this would represent
> > over an order of magnitude increase in code size to achieve the same
> > objective, plus add an external dependency.

> So you require people to trust your custom parser and format just
> because you don't want to rely on a trusted tool that the whole
> world depends on?

We are actually not advocating making the world use our format.

In my last reply we had suggested making the output format an option,
selected by the trust orchestrator at the time a modeling domain was
setup, given that by definition, the only thing that is going to be
reading that file is the trust orchestrator that sets it up.

That puts the compatibility onus on userspace and would provide a
mechanism for the kernel to deprecate formats.  Given the history of
this industry, JSON may be the rage now for the world's trusted
parsing tool, but who knows what the rage is going to be in five
years.  It wasn't too long ago that XML was thought to be all the
rage... :-)

> Again, not a valid argument, sorry, please use common parsing tools
> otherwise you are guaranteed to make mistakes and everyone will have to
> rely on your custom tools only, which is not something that you would
> accept from any other kernel change.

JSON it will be than, unless the community wants the userspace
selection option.

Paul, since securityfs is officially something that is in your
approval domain, do you have any issues with having pseudo-files in
that filesystem urping out JSON?

In addition, Paul or anyone else reading this; does anyone have any
recommendations or preferences with respect to how the data is
marshalled?

Unless we hear otherwise we will proceed with the following
implementation:

- All of the JSON encoded information will be output as a single
linefeed delimited record.

- The record will be a JSON array with named structures that use the
same names as the field description names in the current event
description format.

- All of the existing key=value pairs will be used in their current
documented form but in 'key : value' format.

- JSON encoding will be applied only to the trajectory, forensics and
event description pseudo-files.  All other pseudo-files will continue
outputting a single ASCII value.

> And I don't see a link to the userspace tools anywhere, did I miss it?

The links were in the second to the last paragraph in the cover letter
for the patch series and in the TBDHTTRAD section of the TSEM LSM
documentation file: Documentation/admin-guide/LSM/tsem.rst

The project download directory is as follows:

ftp://ftp.enjellic.com/pub/Quixote

At the current time, the URL for the source is as follows:

ftp://ftp.enjellic.com/pub/Quixote/Quixote-1.4.tar.gz

Pre-compiled binaries, that should run on any x86_64 platform, with no
dependencies, are available in the following forms:

ftp://ftp.enjellic.com/pub/Quixote/Quixote-1.4-1.x86_64.rpm

ftp://ftp.enjellic.com/pub/Quixote/quixote_1.4-2_amd64.deb

The -1 and -2 differences are meaningless, we missed the -k argument
to alien.

The code will compile on Ubuntu 22.04 with GCC plus the Cortex R/M
ARM-GCC compiler.  The trust orchestrators will build with MUSL but
will probably require the presence of some MUSL compiled libraries.

> thanks,
> 
> greg k-h

Have a good weekend.

As always,
Dr. Greg

The Quixote Project - Flailing at the Travails of Cybersecurity

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 09/14] Add namespace implementation.
       [not found] ` <20230204115917.1015-1-hdanton@sina.com>
@ 2023-02-23 18:41   ` Dr. Greg
  0 siblings, 0 replies; 42+ messages in thread
From: Dr. Greg @ 2023-02-23 18:41 UTC (permalink / raw)
  To: Hillf Danton; +Cc: linux-security-module, linux-kernel

On Sat, Feb 04, 2023 at 07:59:17PM +0800, Hillf Danton wrote:

Good afternoon Hillf, I hope this note finds your week going well.

Sorry for the delay in getting back to you on this, had some travel
and we are now in the process of readying the second spin of the
patches.

Thank you, up front, for taking the time to comment on the series.

> [with lkml Cced]

Noted.

> On Fri, 3 Feb 2023 23:09:49 -0600 Dr. Greg <greg@enjellic.com>
> > +/**
> > + * tsem_ns_free() - Releases the namespace model infrastructure.
> > + * @kref: A pointer to the reference counting structure for the namespace.
> > + *
> > + * This function is called when the last reference to a kernel
> > + * based TMA model structure is released.
> > + */
> > +void tsem_ns_free(struct kref *kref)
> > +{
> > +	struct tsem_TMA_context *ctx;
> > +
> > +	ctx = container_of(kref, struct tsem_TMA_context, kref);
> > +
> > +	if (ctx->external) {
> > +		tsem_fs_remove_external(ctx->external->dentry);
> > +		kfree(ctx->external);
> > +	} else
> > +		tsem_model_free(ctx);
> > +
> > +	kfree(ctx);
> > +}
> > +
> > +static void wq_put(struct work_struct *work)
> > +{
> > +	struct tsem_TMA_work *tsem_work;
> > +	struct tsem_TMA_context *ctx;
> > +
> > +	tsem_work = container_of(work, struct tsem_TMA_work, work);
> > +	ctx = tsem_work->ctx;
> > +	kref_put(&ctx->kref, tsem_ns_free);
> > +}
> > +
> > +/**
> > + * tsem_ns_get() - Obtain a reference on a TSEM TMA namespace.
> > + * @ctx: A pointer to the TMA modeling context for which a reference is
> > + *	 to be released.
> > + *
> > + * This function is called to release a reference to a TMA modeling
> > + * domain.
> > + */
> > +void tsem_ns_put(struct tsem_TMA_context *ctx)
> > +{
> > +	if (kref_read(&ctx->kref) > 1) {
> > +		kref_put(&ctx->kref, tsem_ns_free);
> > +		return;
> > +	}

> Given ctx->kref is 2, in the below scenario
> 
> 	cpu 0		cpu 2
> 	---		---
> 	ctx->kref > 1
> 			ctx->kref > 1
> 			kref_put
> 	kref_put
> 
> no work will be scheduled, so it makes sense to move scheduling work to
> tsem_ns_free() by making tsem_ns_put() only a wrapper of kref_put(), if
> ctx has to be released in workqueue.
> 
> void tsem_ns_put(struct tsem_TMA_context *ctx)
> {
> 	kref_put(&ctx->kref, tsem_ns_free);
> }

Missed this issue, thank you for pointing it out.

Based on your observations we re-worked the handling of the modeling
context reference handling and release and we should have the issue
addressed.

In the process we managed to clean up and simplify the implementation
as well, always good.

The changes will be in the second version of the patch series.

> > +
> > +	INIT_WORK(&ctx->work.work, wq_put);
> > +	ctx->work.ctx = ctx;
> > +	if (!queue_work(release_wq, &ctx->work.work))
> > +		WARN_ON_ONCE(1);
> > +}

> PS given system_unbound_wq and system_wq for instance, release_wq looks
> not mandatory if kfree is the major job.

Based on this observation, we also dropped the TSEM specific workqueue
and the code is now scheduling the modeling domain release work onto
the system_wq queue, given that there is nothing sophisticated about
the work that is being scheduled.

This work includes the freeing of the memory for the structure that
defines the external modeling context, or in the case of an internally
modeled domain, the internal model description state.

In addition, in the case of an externally modeled domain, the
workqueue also handles the removal of the securityfs based pseudo-file
that surfaces the event descriptions to the trust orchestrator.

The use of the workqueue silences a series of lock debugging
complaints about the release of the modeling domain/namespace
infrastructure.

Thanks again for your comments, have a good day.

As always,
Dr. Greg

The Quixote Project - Flailing at the Travails of Cybersecurity

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 02/14] Add TSEM specific documentation.
  2023-02-14 11:58     ` Dr. Greg
  2023-02-14 12:18       ` Roberto Sassu
@ 2023-03-03  4:15       ` Paul Moore
  2023-03-13 22:52         ` Dr. Greg
  1 sibling, 1 reply; 42+ messages in thread
From: Paul Moore @ 2023-03-03  4:15 UTC (permalink / raw)
  To: Dr. Greg; +Cc: linux-security-module

On Tue, Feb 14, 2023 at 6:58 AM Dr. Greg <greg@enjellic.com> wrote:
> On Sun, Feb 12, 2023 at 11:33:26PM -0500, Paul Moore wrote:
> > On Sat, Feb 4, 2023 at 12:33 AM Dr. Greg <greg@enjellic.com> wrote:
> > >
> > > An entry was added to the ABI testing documentation to document
> > > the files in the TSEM management filesystem.
> > >
> > > The file documenting the kernel command-line parameters was
> > > updated to document the tsem_mode command-line parameter.
> > >
> > > The primary TSEM documentation file was added to the LSM
> > > administration guide and the file was linked to the index of LSM
> > > documentation.
> > >
> > > Signed-off-by: Greg Wettstein <greg@enjellic.com>
> > > ---
> > >  Documentation/ABI/testing/tsemfs              |  576 ++++++++
> > >  Documentation/admin-guide/LSM/index.rst       |    1 +
> > >  Documentation/admin-guide/LSM/tsem.rst        | 1240 +++++++++++++++++
> > >  .../admin-guide/kernel-parameters.txt         |    5 +
> > >  4 files changed, 1822 insertions(+)
> > >  create mode 100644 Documentation/ABI/testing/tsemfs
> > >  create mode 100644 Documentation/admin-guide/LSM/tsem.rst
>
> > One of the more important requirements for any new LSM is that it
> > documents a clear, understandable, and reasonable security model along
> > with an implementation that faithfully implements that model.  Before
> > I looked at your code I wanted to try and understand the TSEM security
> > model and a few things jumped out at me rather quickly, I imagine
> > there would be others as I start to look a bit closer but I wanted to
> > send these questions/comments along now to get your take on them ...
>
> Hi Paul, thanks for taking time to review the documentation and raise
> questions, responses below.
>
> > > diff --git a/Documentation/ABI/testing/tsemfs b/Documentation/ABI/testing/tsemfs
> > > new file mode 100644
> > > index 000000000000..3d326934624c
> > > --- /dev/null
> > > +++ b/Documentation/ABI/testing/tsemfs

...

> > > +What:          /sys/fs/tsem/measurement
> > > +Date:          November 2022
> > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > +Description:
> > > +               The measurement file contains the ASCII base 16
> > > +               hexadecimal representation of the 256 bit measurement
> > > +               value of the security model that the process is
> > > +               operating in.
> > > +
> > > +               The measurement value is the classic linear extension
> > > +               measurement of the model.  An updated measurement
> > > +               value is created by extending the current measurement
> > > +               value with the state coefficient computed for a
> > > +               security event.
> > > +
> > > +               This measurement value represents a time dependent
> > > +               measurement of a model and is susceptible to
> > > +               deviations caused by scheduling differences between
> > > +               subsequent invocations of a workload.
>
> > Given the very volatile nature of this value, what is it used for in
> > userspace?  My apologies if I missed it in the docs.
>
> It serves the same role as PCR register 10 in IMA, or any other
> register in a TPM based architecture using a classic linear extension
> mechanism strategy, it can be used to validate a list of time or
> sequence ordered measurement values.
>
> Our personal prejudice is that these types of measurements are of
> limited value, which is why we introduce in TSEM, the notion of the
> 'state' value for a model, discussed below.
>
> I would have to go looking on lore for a reference to the exact thread
> but Roberto Sassu had offered up a patch set for IMA that addressed
> the deficiency of these types of measurements.

If we all agree that this measurement isn't very useful, and you have
implemented an alternative which is intended to address these
usability shortcomings, why bother including this measurement in TSEM?

It's relatively easy to add features to the Linux Kernel as time goes
on, it is *very* difficult to remove them.  For this initial
submission I would encourage you to implement the bare minimum
functionality you need to do something useful and meet your goals.

> > > +What:          /sys/fs/tsem/points
> > > +Date:          November 2022
> > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > +Description:
> > > +               The points file contains the ASCII base 16
> > > +               representation of the 256 bit security state points of
> > > +               a security domain/model.  The number of entries in
> > > +               this file represent the number of security events that
> > > +               are represented by the model.
>
> > A similar questions to the tsem/measurement file.  If I understand
> > you correctly, this is basically a series of SHA256 digests without
> > any additional annotations, and without any ordering guarantees,
> > yes?  What is it used for in userspace?
>
> The values in the points file represent the current state of a model,
> they are the coefficients that describe the security events that have
> been modeled.
>
> The output of this file can be captured and written to the
> /sys/fs/tsem/map file in order to define a security model that is to
> be subsequently enforced.

Okay, I was under the assumption that this file was dependent on the
order in which execution takes place on the system, it sounds like
that is not the case and the output of this file is repeatable with a
fairly standard system configuration (e.g. multi-core, multi-user,
etc.).

> > > +What:          /sys/fs/tsem/state
> > > +Date:          November 2022
> > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > +Description:
> > > +               The state file contains the ASCII base 16
> > > +               representation of the 256 bit value of the functional
> > > +               state of a security domain/model.
> > > +
> > > +               The state value is a time independent representation
> > > +               of the measurement of a model/domain, and unlike the
> > > +               measurement value, is a time independent
> > > +               representation of the security state of a workload.
> > > +
> > > +               This value is designed to be a single value that can
> > > +               be attested to represent whether or not a workload has
> > > +               deviated from a defined security behavior.
>
> > It might be nice to explain how this value is calculated here in
> > this file to remove any time or ordering dependencies.  Once again
> > my apologies if I missed it in the rest of the docs.
>
> The TSEM LSM documentation covers the issues surrounding the
> measurement and state values.  See the section entitled 'Security
> model functional definitions'.

Thanks.  A reference to the related section in the TSEM docs would be
nice to see here.

> Put succinctly, the state value is computed by generating a standard
> linear extension sum over a list of security state points that have
> been sorted in big-endian, ie. natural hash order.
>
> It is designed to provide a time and scheduling independent value that
> can be used to attest that a security model has not violated its
> definition.

Understood.

> Don't apologize, there is a lot there to read, our loquaciousness
> knows no bounds.... :-)
>
> > > +What:          /sys/fs/tsem/trajectory
> > > +Date:          November 2022
> > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > +Description:
> > > +               The trajectory file contains a description of the
> > > +               security events that have occurred in a security
> > > +               domain/model.
> > > +
> > > +               Each entry in this file represents a single security
> > > +               event and consists of brace {} delimited fields that
> > > +               describe the characteristics of a security event.
> > > +               Each field has key=value pairs that define
> > > +               characteristics of the field.
> > > +
> > > +               Each line in a trajectory, or forensics, file will
> > > +               always have the event{} and COE{} fields.  The event
> > > +               field describes the characteristics of a security
> > > +               event while the COE field describes the Context Of
> > > +               Execution that is executing the security event.
>
> > I think it would be good to provide a concrete definition of
> > CELL_DEFINITION field as other areas of the documentation make
> > reference to it within the tsem/trajectory file documentation.  We can
> > somewhat infer it's format, fields, etc. but it's much better to be
> > explicit about these things.
>
> Valid point, we will incorporate a broad definition of what the 'CELL'
> represents.
>
> Conceptually, it is equivalent to the 'object' in mandatory access
> controls.  In an events based architecture like TSEM, it is
> essentially the 'bucket' of values that describe the parameters of a
> security event that a COE/process is requesting permission for.

Yes, I understood conceptually what it represents and what data might
be present given a specific operation/rule, but it wasn't clear to me
how that data would be represented in the CELL_DEFINITION.

> > > +               The event{} field consists of the following
> > > +               characteristic definitions:
>
> > I'm unclear as to the purpose of the event{} field as it is neither
> > part of the COE or the CELL, is it here simply to make the event
> > easier to read?  Or am I misunderstanding things and the event{}
> > field is part of the COE?
>
> It actually serves two roles, one of which, as you note, is to make
> the event description easier to read and understand.
>
> It probably comes as no surprise, but the trust orchestration system
> that this is all designed to support, has a security console that can
> be used to review the status of all the trust orchestrators that are
> supervising security workloads.  Either in the cloud, or perhaps, a
> large body of edge devices protecting critical infrastructure, if that
> doesn't give away too much.... :-)
>
> Having the process name and executable easily visualized is fairly
> useful.
>
> The second role is to allow the event description records to be
> self-describing.  The value for the type= key is used by the Trusted
> Modeling Agent (TMA) to determine what to look for in the remainder of
> the event description record in order to compute the CELL value.
>
> It also contains the TASK_ID value that ties the security state points
> to the integrity of the executable.  Since that value is a synthetic
> value it was deemed most appropriate to be placed in the event{}
> field.

I think it would be good to provide a more succinct version of the
above in the documentation.

> > > +                       process=COMM
> > > +                               Where COMM is the ASCII representation
> > > +                               of the name of the process executing
> > > +                               the event.
> > > +
> > > +                       filename=PATH
> > > +                               If the CELL definition for an event
> > > +                               references a file the filename
> > > +                               characteristic contains a definition
> > > +                               of the path to the file.
> > > +
> > > +                               In the case where an event does not
> > > +                               have a file the PATH value is set to a
> > > +                               value of none.
>
> > What happens in cases where multiple file paths are present in an
> > event?  Also, given this is visible to userspace, and multiple
> > things can affect the path to a file (e.g. namespaces), how is the
> > file path determined?
>
> Unless we have missed something, which is no doubt possible, all of
> the security event hooks that we have implemented, which number about
> 87 now, that act on a 'file', receive only a single 'struct file *'
> pointer as a parameter to the event.
>
> So we haven't encountered a situation where there would be multiple
> files for a single event description.

I haven't seriously looked at the TSEM sources yet, I'm trying to make
sure that I first understand the security model while also ensuring
that it is well documented and reasonable.  While I can't speak to
what LSM hooks TSEM implements, it seems like there are at least a few
operations, rename and link come immediately to mind, which would have
multiple filenames as part of the operation.  How are those operations
handled in TSEM, or are they outside the scope of TSEM?

> There is certainly the case where multiple security state points
> involve the same file.  This can easily be seen, for example, in a
> trust orchestrator running a workload in a runc container, where
> multiple state points are generated by different executable mappings
> of the runc binary at startup
>
> The file path is the absolute pathname in the mount namespace that the
> modeled workload is running in.

I think it is important to specify that the path recorded here is in
the context of the mount namespace of the task generating the event.
Yes, one could reasonably assume that, given the disjoint nature of
mount namespaces, but with several other fields being recorded in the
context of the initial namespace I think it is important to note these
differences.

> > > +                       type=EVENT_TYPE
> > > +                               The value field for a type key is the
> > > +                               name of the security event that is
> > > +                               being modeled.  The list of value
> > > +                               EVENT_TYPE names is defined in the
> > > +                               following source file:
> > > +
> > > +                               security/tsem/tsem.c
> > > +
> > > +                               If the security event is a generically
> > > +                               modeled event the EVENT_TYPE will be
> > > +                               generic_event.  In this case the CELL
> > > +                               characteristics for the event will be
> > > +                               described by a generic_event{} field.
> > > +
> > > +                       task_id=TASK_ID
> > > +                               The value of the task_id key will the
> > > +                               ASCII base 16 representation of the
> > > +                               model identity of the task that is
> > > +                               executing the security event.
> > > +
> > > +                               The following documentation file:
> > > +
> > > +                               Documentation/admin-guide/LSM/TSEM.rst
> > > +
> > > +                               Describes how the TASK_ID value is
> > > +                               generated.
> > > +
> > > +               The COE{} field consists of the following
> > > +               characteristic definitions:
> > > +
> > > +                       uid=NN
> > > +                               The ASCII base 10 representation of
> > > +                               the numeric value of the discretionary
> > > +                               user id of the process that is
> > > +                               executing the security event.
>
> > Given the ability to map UID/GID values in the kernel, what will be
> > used as the basis for the COE?  What happens when the basis used in
> > the kernel's COE generation does not match the basis used by the
> > external modeler?
>
> The UID/GID values used are the values defined in the initial
> user namespace, see security/tsem/event.c:get_COE().

Once again, please note that in the documents.

> The basis set state that the trust orchestrator is running in has no
> effect on the generation of the security state point.  The modeling
> engine only operates on the values presented to it and determines if
> the state point generated from the state description matches the model
> it has been requested to enforce.
>
> If it doesn't, the event is considered to violate the trust model.
>
> > > +                       euid=NN
> > > +                               The ASCII base 10 representation of
> > > +                               the numeric value of the effective
> > > +                               discretionary user id of the process
> > > +                               that is executing the security event.
> > > +
> > > +                       euid=NN
> > > +                               The ASCII base 10 representation of
> > > +                               the numeric value of the effective
> > > +                               discretionary user id of the process
> > > +                               that is executing the security event.
> > > +
> > > +                       suid=NN
> > > +                               The ASCII base 10 representation of
> > > +                               the numeric value of the saved user id
> > > +                               of the process that is executing the
> > > +                               security event.
> > > +
> > > +                       gid=NN
> > > +                               The ASCII base 10 representation of
> > > +                               the numeric value of the discretionary
> > > +                               group id of the process that is
> > > +                               executing the security event.
> > > +
> > > +                       egid=NN
> > > +                               The ASCII base 10 representation of
> > > +                               the numeric value of the discretionary
> > > +                               effective group id of the process that
> > > +                               is executing the security event.
> > > +
> > > +                       egid=NN
> > > +                               The ASCII base 10 representation of
> > > +                               the numeric value of the discretionary
> > > +                               effective group id of the process that
> > > +                               is executing the security event.
> > > +
> > > +                       sgid=NN
> > > +                               The base 10 ASCII representation of
> > > +                               the numeric value of the saved
> > > +                               discretionary group id of the process
> > > +                               that is executing the security event.
> > > +
> > > +                       fsuid=NN
> > > +                               The base 10 ASCII representation of
> > > +                               the numeric value of the discretionary
> > > +                               filesystem user id of the process that
> > > +                               is executing the security event.
> > > +
> > > +                       fsgid=NN
> > > +                               The ASCII base 10 representation of
> > > +                               the numeric value of the discretionary
> > > +                               filesystem group id of the process
> > > +                               that is executing the security event.
> > > +
> > > +                       cap=0xNNN
> > > +                               The ASCII base 16 representation of
> > > +                               the numeric value of effective
> > > +                               capabilities of the process that is
> > > +                               executing the security event.
> > > +
> > > +               If the CELL value for a security event includes the
> > > +               definition of a file a file{} event field will be
> > > +               included.  The following characteristics will be
> > > +               encoded in this field:
> > > +
> > > +                       flags=NN
> > > +                               The ASCII base 10 representation of
> > > +                               the flags value of the 'struct file'
> > > +                               structure that is the source of the
> > > +                               file description.
> > > +
> > > +                       uid=NN
> > > +                               The ASCII base 10 representation of
> > > +                               the discretionary user id of the file.
> > > +
> > > +                       gid=NN
> > > +                               The base 10 ASCII representation of
> > > +                               the discretionary group id of the
> > > +                               file.
>
> > Similar to the task UID/GID mapping questions above, there are
> > mechanisms which map the file user/group IDs, which will be used in
> > the CELL definition and how will that be resolved between the kernel
> > and an external modeler?
>
> The answer is the same as with the COE, see the following function:
>
> security/tsem/event.c:get_file_cell()
>
> Once again, the TMA only operates on the event description presented
> to it and is not influenced by its own namespace.

For this particular point, my concern isn't what policy the TMA
implements, or what it uses as input, it's about understanding how
this event information is collected.  For fields which can be
namespaced (I'm referring to "normal" Linux Kernel namespaces and not
any TSEM namespaces), the TSEM documentation should make it clear
which namespace is used as a basis for the value.

> > > +What:          /sys/fs/tsem/ExternalTMA
> > > +Date:          November 2022
> > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > +Description:
> > > +               The ExternalTMA directory is a container directory
> > > +               that hold files that will be used to export the
> > > +               security events, and their associated parameters, for
> > > +               externally modeled security domains/namespaces.
> > > +
> > > +               The files created in this directory will be named by
> > > +               the base 10 ASCII representation of the id value
> > > +               assigned to the modeling domain/namespace.  See the
> > > +               documentation for the /sys/fs/tsem/id file in this
> > > +               documentation for more details on this value.
> > > +
> > > +               This file will is a read-only file that can be polled
> > > +               by a userspace trust orchestration implementation to
> > > +               process security events that are to be modeled by
> > > +               an external Trusted Modeling Agent.
> > > +
> > > +               The type of the exported event is the first keyword of
> > > +               the line that is output and have the following
> > > +               values and arguments:
> > > +
> > > +               aggregate HEXID:
> > > +                       Where HEXID is the ASCII base 16
> > > +                       representation of the 256 bit hardware
> > > +                       platform aggregate value.
> > > +
> > > +               export pid{NNN} COE{} CELL_DEFINITION
> > > +                       Where the NNN in the pid field is the ASCII
> > > +                       base 10 value of the id of the process that is
> > > +                       executing the security event that will be
> > > +                       modeled.
>
> > I worry whenever I see a PID used as an identifier shared across the
> > kernel/userspace boundary as it is inherently racy.  Given the
> > somewhat coarse COE definition where one can expect multiple
> > processes/PIDs to share the same COE value, and the ability of
> > untrusted users/processes to manipulate the PID table, what do you
> > expect to use the pid{NNN} field for in this event?
> >
> > Similar to the other namespace/mapping issues discussed previously,
> > there is also the PID namespace issue to worry about.  How is that
> > handled here?
>
> The concern over the PID issue is understandable, I will treat the
> reasoning behind its use below.
>
> The PID value is the 'native' value managed by the kernel, not a
> mapped value.

Regardless of if the PID is rooted in the initial namespace or a
different PID namespace, the issue of PIDs being inherently racy is a
real problem.  Can you help me understand how TSEM avoids the common
pitfalls associated with using PIDs to identify processes on the
system?

> > > +                       The COE field has the same format as the field
> > > +                       emitted for a trajectory or forensics event.
> > > +
> > > +                       The CELL_DEFINITION are the same field
> > > +                       definitions that are emitted for a trajectory
> > > +                       or forensics event.
> > > +
> > > +               log process{name} event{type} action{type}
> > > +                       The log event is emitted when an untrusted
> > > +                       task attempts to execute a security event.
> > > +
> > > +                       The name value of the COE field is the name of
> > > +                       the process (comm value) that is executing the
> > > +                       security event.
> > > +
> > > +                       The type value of the event field is the name
> > > +                       of the security event being executed as
> > > +                       defined in the tsem_names array in the
> > > +                       security/tsem/tsem.c file.
> > > +
> > > +                       The type value of the action field is the type
> > > +                       of action the LSM enforced in response to
> > > +                       encountering the untrusted process.  This
> > > +                       value will be either LOG or EPERM to represent
> > > +                       whether or not the trust violation is being
> > > +                       logged or enforced.
> > > +
> > > +What:          /sys/fs/tsem/control
> > > +Date:          November 2022
> > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > +Description:
> > > +               The control file is the only writable file in the
> > > +               filesystem and is used by the trust orchestrators to
> > > +               configure and control the behavior of the TSEM
> > > +               implementation.
> > > +
> > > +               The following keyword and arguments are recognized:
> > > +
> > > +               internal:
> > > +                       The internal keyword causes an internally
> > > +                       modeled domain to be created for the calling
> > > +                       process.
> > > +
> > > +               external:
> > > +                       The external keyword causes an externally
> > > +                       modeled domain to be created for the calling
> > > +                       process.
> > > +
> > > +               enforce:
> > > +                       The enforce keyword causes the modeling
> > > +                       domain/namespace of the process to enter
> > > +                       enforcing mode.  In this mode a value of
> > > +                       -EPERM will be returned for a security event
> > > +                       that does not map into the current set of
> > > +                       allowed state points for the security model
> > > +                       being implemented for the domain/namespace.
> > > +
> > > +               seal:
> > > +                       The seal keyword causes the security model
> > > +                       being implemented for the model to be placed
> > > +                       in sealed state.  In this state the current
> > > +                       set of security event points is considered to
> > > +                       be the only set of valid points for the
> > > +                       domain/model.  Any subsequent events that map
> > > +                       to a point not in the current model will be
> > > +                       considered a violation of the model.
> > > +
> > > +               trusted PID:
> > > +                       The trusted keyword is used by a trust
> > > +                       orchestrator to indicate that the process
> > > +                       identified by the PID argument should be
> > > +                       allowed to run in trusted status.
> > > +
> > > +               untrusted PID:
> > > +                       The untrusted keyword is used by a trust
> > > +                       orchestrator to indicate that the process
> > > +                       identified by the PID argument should be
> > > +                       allowed to run but designated as an untrusted
> > > +                       process.
>
> > The 'trusted PID:' and 'untrusted PID:' commands are concerning for
> > the reasons described above about PIDs being racy and generally an
> > unreliable way of identifying processes across the kernel/userspace
> > boundary.  I suspect it would not be too difficult for a malicious
> > user to trick an external modeler into marking the wrong process as
> > trusted/untrusted.
>
> An external TMA needs the PID value to determine which process to wake
> up and set the trust status value on in the task control structure,
> after the event is modeled.  As was noted above, the PID value is the
> unmapped value maintained by the OS.
>
> Lets see if we can reason through why the PID can be used safely.
>
> CAP_TRUST, or whatever ends up getting used, is required by the trust
> orchestrator to create a security/modeling namespace for the workload
> being modeled.  This results in the creation of the following
> pseudo-file for surfacing the security event descriptions for the
> namespace/workload:
>
> /sys/fs/tsem/ExternalTMA/N
>
> Where N is the id number of the modeling domain.
>
> CAP_TRUST, caveats applied, is required to open the pseudo-file.  The
> trust orchestrator only receives and acts on PID values through this
> conduit from the kernel.
>
> When an event description is exported, the trust status of the task is
> set to 'pending' and the process is placed in interruptible sleep and
> scheduled away, with the 'wakeup' criteria being the trust status
> being changed from pending to either trusted or untrusted.
>
> The only path to change the trust status value in the LSM task control
> structure and wake up the process is by the trust orchestrator that
> created the namespace, by writing the appropriate value to the
> /sys/fs/tsem/control file.  Access to that file is gated by CAP_TRUST
> or its equivalent.
>
> See the following code locations for further details:
>
> security/tsem/export.c:tsem_export_event()
>
> security/tsem/fs.c:control_COE()
>
> As long as the process 'exists', albeit sleeping, the PID slot is
> occupied and an adversary, regardless of namespace, cannot substitute
> a task with the same PID value.
>
> This leaves an adversary with the need to terminate the task being
> modeled in order to capture its PID slot.
>
> Precautions are implemented in the following function to protect the
> process from being terminated by an adversary:
>
> security/tsem/tsem.c:tsem_task_kill()

What about the OOM killer?

The security_task_kill() LSM hook only offers an access control point
for one process sending another process a signal, it doesn't gate a
process being killed for other reasons.  The OOM killer is the first
thing that comes to mind, but I'm reasonably certain there are other
similar scenarios.

> > > +               state HEXID:
> > > +                       The state keyword is used to indicate that the
> > > +                       security state point identified by the ASCII
> > > +                       base 16 encoded value should be loaded into
> > > +                       the current security model as a valid security
> > > +                       event state.
> > > +
> > > +               pseudonym HEXID
> > > +                       The pseudonym keyword is used to indicate that
> > > +                       the pathname, identified by the 256 bit ASCII
> > > +                       base 16 encoded value HEXID, should be
> > > +                       designated to return a constant digest value
> > > +                       for the contents of the file.
> > > +
> > > +                       The HEXID value is computed with the following
> > > +                       function:
> > > +
> > > +                       HEXID = SHA256(PATHNAME_LENGTH || PATHNAME)
>
> > This seems like an unusual design choice, and perhaps one born from
> > necessity ... ?  It's nice that it is opt-in, but I would be curious
> > to hear what problems this solved.
>
> It is an approximation method that allows things like log files and
> .bash_history files to be effectively modeled.

Okay, that's what I suspected, I just wanted to make sure there wasn't
something else I was missing.

> > > +               base HEXID
> > > +                       The base keyword is used to indicate that the
> > > +                       256 bit ASCII base 16 encoded value HEXID
> > > +                       should be registered as the value used to
> > > +                       generate model specific security event points.
> > > +
> > > +                       A model specific base value is designed to be
> > > +                       used as a 'freshness' nonce, similar to an
> > > +                       attestation nonce, to prove that a model state
> > > +                       value or measurement is current and not being
> > > +                       replayed.
> > > diff --git a/Documentation/admin-guide/LSM/tsem.rst b/Documentation/admin-guide/LSM/tsem.rst
> > > new file mode 100644
> > > index 000000000000..f03e5269cd25
> > > --- /dev/null
> > > +++ b/Documentation/admin-guide/LSM/tsem.rst
> > > @@ -0,0 +1,1240 @@
> > > +====
> > > +TSEM
> > > +====
> >
> > ...
> >
> > > +Process and Platform Trust Status
> > > +=================================
> > > +
> > > +A fundamental concept in TSEM is the notion of providing a precise
> > > +definition for what it means for a platform or workload to be trusted.
> > > +A trusted platform or workload is one where there has not been an
> > > +attempt by a process to execute a security relevant event that does
> > > +not map into a known security state point.
> > > +
> > > +The process trust status is a characteristic of the process that is
> > > +passed to any subordinate processes that are descendants of that
> > > +process.  Once a process is tagged as untrusted, that characteristic
> > > +cannot be removed from the process.  In a 'fruit from the poisoned
> > > +vine' paradigm, all subordinate processes created by an untrusted
> > > +process are untrusted as well.
> > > +
> > > +On entry into each TSEM security event handler, the trust status of a
> > > +process is checked before an attempt to model the event is made.  An
> > > +attempt to execute a security event by an untrusted process will cause
> > > +the event, and its characteristics, to be logged.  The return status
> > > +of the hook will be determined by the enforcement state of the model.
> > > +A permission denial is only returned if the TMA is running in
> > > +enforcing mode.
> > > +
> > > +If the platform running the TSEM LSM has a TPM, the hardware aggregate
> > > +value is computed at the time that TSEM is initialized.  This hardware
> > > +aggregate value is the linear extension sum over Platform
> > > +Configuration Registers (PCR's) 0 through 7.  This is the same
> > > +aggregate value that is computed by the Integrity Measurement
> > > +Architecture (IMA) and is the industry standard method of providing an
> > > +evaluation measurement of the hardware platform state.
> > > +
> > > +Internally model domains have the hardware aggregate measurement
> > > +included as the first state point in the security model.  Externally
> > > +modeled domains export the hardware aggregate value to the TMA for
> > > +inclusion as the first state point of the model maintained by the TMA.
> > > +
> > > +The root modeling domain extends each security state point into PCR
> > > +11.  This allows hardware based TSEM measurements to coexist with IMA
> > > +measurement values.  This hardware measurement value can be used to
> > > +attest to the security execution trajectory that the root model
> > > +maintains.
>
> > It seems like making the target PCR configurable would be a good
> > idea, at the very least make it a Kconfig option.
>
> That was something that we have thought about, it probably needs a
> Kconfig option.
>
> Contrary to all appearances, as a team we are really minimalists at
> heart and tend to not make things more complex or configurable than
> needed.... :-)
>
> > Also, can you elaborate on how the security state points are
> > extended into the PCR?  I imagine for it to be useful at an
> > arbitrary point in time this would require the PCR to be extended as
> > the security points were generated, which would imply that the PCR
> > value would be dependent on execution order, and in most cases,
> > scheduling order as well.  How useful do you expect this to be for
> > most users?
>
> Your assessment is correct, the state points are extended into the PCR
> whenever a unique security state point is generated.
>
> In a 'free-running' model, the value in the register will be fungible
> due to scheduling dependencies.

In other words, garbage ;)

> If the model is pre-defined, the security state points will be
> extended into the register as they are loaded through the
> /sys/fs/tsem/map pseudo-file interface.  In this case, the value will
> be fixed and any departure from the value would signal that the
> modeling domain has departed from its specification.
>
> With respect to the utility of the value, in a 'free-running' model it
> is about as useful as the value that IMA maintains in PCR 10, which in
> our opinion is not very useful and is why we implemented the notion of
> the 'state' value of a model.

For a variety of reasons, and mostly to help keep things civil, let's
refrain from comparing one LSM to another.  Each LSM makes its own
choices, and needs to stand on its own; just because LSM did X doesn't
mean TSEM can do X if it is silly in the context of TSEM.

> The primary utility of the value is that it is a hardware maintained
> reference value that can be used to confirm the set of measurements
> committed to the register.

Given that the PCR value is only deterministic in the case of a
predefined policy/model, it seems like it would be worth stating that
a bit more clearly in the docs.

> So our 'state' value gives us a constant 'good' value for the security
> model.  The PCR 11 value provides a hardware root of trust for the set
> of points that lead to the state value.

Just to make sure I understand you, in the predefined case PCR 11 is
extended with the SRTM PCRs as well as a measurement of the TSEM
policy at load time, yes?

> > > +Internal vs external modeling
> > > +-----------------------------
> > > +
> > > +When a TSEM modeling domain is created, a designation is made as to
> > > +whether the domain is to be internally or externally modeled.
> > > +
> > > +In an internally modeled domain, the security event handlers pass the
> > > +event type and its characteristics to the designated internal trusted
> > > +modeling agent.  The agent provides the permission value for the
> > > +security event handler to return as the result of the event and sets
> > > +the trust status of the process executing the event.
> > > +
> > > +In an externally modeled domain, the event type and parameters are
> > > +exported to userspace for processing by a trust orchestrator with an
> > > +associated TMA.  The trust orchestrator communicates the result of the
> > > +modeling back to the kernel to support the setting of the process
> > > +trust status.
> > > +
> > > +This model poses a limitation to the ability of TSEM to model some
> > > +security events.  This is secondary to the fact that some event
> > > +handlers (LSM hooks) are called from a non-sleeping context, as a
> > > +result the process cannot be scheduled.  This is particularly the case
> > > +with the task based hooks, since they are typically called with the
> > > +tasklist lock held.
> > > +
> > > +This limitation is also inherent to the root model that extends the
> > > +security state points into TPM PCR 11, secondary to the fact that the
> > > +process invoking the security event hook will be scheduled away while
> > > +the TPM transaction completes.
> > > +
> > > +Addressing this problem directly requires a consideration of the
> > > +context from which the security event handlers are being called.
> > > +Subsequent implementations of TSEM will include a mechanism for
> > > +asynchronous deferral of model processing, until when and if, a review
> > > +of the call context would be considered worthwhile by the LSM
> > > +community.
>
> > This is a pretty big limitation, and in conjunction with the some of
> > the other issues brought up earlier (the PID issue seems the most
> > concerning), I'm having a difficult time believeing that an external
> > modeler could operate safely given the design presented here.
>
> With respect to the PID issue, we would welcome any comments on the
> analysis that we provided above as to its design safety.

From what I can tell from the documentation and our discussion thus
far is that TSEM relies on a security_task_kill() hook implementation
to ensure that a process is not killed, and the PID released, without
explicit TSEM approval.  Unfortunately, I believe that relying solely
on security_task_kill() will not fully cover all of the cases where a
process can be killed, mostly because security_task_kill() does not
control process destruction, it controls the ability of one process to
signal another.

You might be able to do something with security_task_free(), but I
haven't given that much thought.

> If the PID issue remains a concern, we have an extension to the export
> descriptions that would include a random nonce that would be emitted
> with the PID.  The nonce would be placed in the LSM task control
> 'blob' for the sleeping task and used to confirm that the task release
> directive was acting on the correct process.

That should help, but ultimately a nonce is still a bounded resource
and subject to recycling just like the PID.  I'm open to hearing other
ways in which you believe you can resolve this issue, but I remain
skeptical.

> > Unfortunately, there will always be LSM hooks which need to operate
> > in a non-blocking context, meaning this challenge is here to stay.
> > Help me understand how you could safely do asynchronous policy
> > enforcement with an external modeler, I'm not sure it's possible.
>
> Electing to implement asynchronous enforcement would require further
> thought.  We were operating in the context of full disclosure in our
> documentation and wanted to be up front about limitations and options.
>
> To be clear, at this time, we are not advocating for or bringing
> forward an asynchronous update architecture.
>
> So, at this time, there is a well understood modeling limitation with
> respect to the LSM hook implementations.  That limitation is not
> limited to external TMA's, since the event state points cannot be
> extended into a TPM in a non-blocking context.

I think these limitations need to be made explicit in the
documentation.  If the TSEM security model can not be faithfully
implemented, the documented security model may need to change.

> > Frankly, I also wonder how a system would perform with an external
> > modeler, indepdent of the issues with non-blocking hooks.  How does
> > the system perform with every blockable LSM hook invocation
> > potentially blocking on a response from userspace?  Or with the COE
> > being somewhat coarse, does the trajectory/policy populate itself
> > quickly?
>
> One obviously experiences a latency hit in going to userspace, by
> definition, implementing security always has an associated resource
> cost.  So, once again, this comes down to a cost/benefit analysis.
>
> As a Gedanken exercise, consider the value proposition of a Linux
> based RTU, or other device, controlling infrastructure that can only
> execute security relevant events that are guaranteed to be known good
> by an external co-processor that is only accessible as a security
> oracle.
>
> Given that frame of reference.
>
> Time for a userspace or SGX based TMA transaction is running around
> 890 micro-seconds.
>
> Going to a TMA based in a Xen stubdomain implementation runs a bit
> longer, probably around 940 micro-seconds or so.
>
> The micro-controller implementations are decidedly slower, with the
> NRF52840-DONGLE clocking in at around 40 micro-seconds, but that is
> strictly a CPU horsepower issue.
>
> All of this with the caveat that we have been focusing almost
> exclusively on correctness and not optimizing performance.
>
> We've thought a bit, mainly on long walks with our Golden Retriever
> Izzy, about the issue of building a kernel based policy cache with
> externally modeled domains.  Given that the kernel does not, a-priori,
> know what modeling algorithm a TMA might be using, we would need to
> come up with a method of deterministically mapping a security event
> description to a known good state point value.
>
> The other issue with all this is that with containerized workloads,
> particularly micro-services, the rate of security event generation can
> be surprisingly low.  Obviously this is also the case with embedded
> implementations.
>
> Once again, what are you willing to pay to be safe?

For better or worse, when code is proposed for the upstream Linux
Kernel it is subject to scrutiny from all manner of developers and
users, with most being focused on their own pet projects/subsystems,
not whatever new security promises you are providing.

There have been patch(sets) and discussions relating to performance
gains/losses on the other of tens of nanoseconds per operation.

I think most of us in the security community are sympathetic to the
question of "what are you willing to pay to be safe", but please
understand that while we are understanding, there are others who will
disagree not only with the performance cost tradeoff, but the very
idea of safety you are promising.  My only suggestion is to be
prepared, and be honest with the performance assessments of TSEM.

> > > +Event handlers that cannot be directly modeled, still consider, on
> > > +entry, whether or not they are being called by an trusted or untrusted
> > > +process.  As a result, an untrusted process will cause a non-modeled
> > > +event to return a permissions violation in enforcing mode, even if the
> > > +security event cannot be directly modeled.
> > > +
> > > +Security event modeling typically traps violations of trust by a COE
> > > +with unmodeled characteristics that is attempting to access/execute a
> > > +file or map memory as executable; or by a COE with known
> > > +characteristics attempting to access or execute a CELL not prescribed
> > > +by a model.  As a result, the impact of the ability to not directly
> > > +model these events is lessened.
> >
> > ...
> >
> > > +Event modeling
> > > +--------------
> > > +
> > > +TSEM security event modeling is based on the following functional
> > > +definition for a security state point:
> > > +
> > > +Sp = SHA256(SHA256(EVENT_ID) || TASK_ID || SHA256(COE) || SHA256(CELL))
>
> > It appears that all of the hasing in TSEM is SHA256 based, you might
> > want to consider making that a Kconfig option at the very least.
>
> That has been something that we have talked about as well.
>
> As I indicated previously, we really are minimalists, particularly
> after watching IMA fight with issues surrounding algorithmic agility.
>
> It would be easy enough to make this configurable but does anyone see
> SHA256 as not being useful in in this role anywhere in the next 10
> years?

There are any number of reasons why one might need to select a
different hash algorithm: legal constraints, security certifications,
corporate policy.  I would strongly suggest making this configurable.

-- 
paul-moore.com

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 02/14] Add TSEM specific documentation.
  2023-03-03  4:15       ` Paul Moore
@ 2023-03-13 22:52         ` Dr. Greg
  2023-03-22 23:45           ` Paul Moore
  0 siblings, 1 reply; 42+ messages in thread
From: Dr. Greg @ 2023-03-13 22:52 UTC (permalink / raw)
  To: Paul Moore; +Cc: linux-security-module

On Thu, Mar 02, 2023 at 11:15:56PM -0500, Paul Moore wrote:

Hi Paul, thanks for sending along further comments.

You note below that you haven't had time to look at the code since you
wanted to confirm the TSEM security model before moving forward.

From a development perspective we are now three weeks into what will
become version 2 of the patch series.  So at this point I wouldn't
advocate spending a lot of time on the current patchset.

That being said, if you some have time, we would appreciate a quick
look at the code on your part, with respect to style changes and the
like we can enforce in the second series, ie. ordering of local
variable declarations by length and the like.

Everything has to, and does, pass checkpatch but I don't believe that
utility judgement on issues such as ordering of variable declarations
and the like.

That being said, specific comments follow below on issues you raised.

> On Tue, Feb 14, 2023 at 6:58???AM Dr. Greg <greg@enjellic.com> wrote:
> > On Sun, Feb 12, 2023 at 11:33:26PM -0500, Paul Moore wrote:
> > > On Sat, Feb 4, 2023 at 12:33 AM Dr. Greg <greg@enjellic.com> wrote:
> > > >
> > > > An entry was added to the ABI testing documentation to document
> > > > the files in the TSEM management filesystem.
> > > >
> > > > The file documenting the kernel command-line parameters was
> > > > updated to document the tsem_mode command-line parameter.
> > > >
> > > > The primary TSEM documentation file was added to the LSM
> > > > administration guide and the file was linked to the index of LSM
> > > > documentation.
> > > >
> > > > Signed-off-by: Greg Wettstein <greg@enjellic.com>
> > > > ---
> > > >  Documentation/ABI/testing/tsemfs              |  576 ++++++++
> > > >  Documentation/admin-guide/LSM/index.rst       |    1 +
> > > >  Documentation/admin-guide/LSM/tsem.rst        | 1240 +++++++++++++++++
> > > >  .../admin-guide/kernel-parameters.txt         |    5 +
> > > >  4 files changed, 1822 insertions(+)
> > > >  create mode 100644 Documentation/ABI/testing/tsemfs
> > > >  create mode 100644 Documentation/admin-guide/LSM/tsem.rst
> >
> > > One of the more important requirements for any new LSM is that it
> > > documents a clear, understandable, and reasonable security model along
> > > with an implementation that faithfully implements that model.  Before
> > > I looked at your code I wanted to try and understand the TSEM security
> > > model and a few things jumped out at me rather quickly, I imagine
> > > there would be others as I start to look a bit closer but I wanted to
> > > send these questions/comments along now to get your take on them ...
> >
> > Hi Paul, thanks for taking time to review the documentation and raise
> > questions, responses below.
> >
> > > > diff --git a/Documentation/ABI/testing/tsemfs b/Documentation/ABI/testing/tsemfs
> > > > new file mode 100644
> > > > index 000000000000..3d326934624c
> > > > --- /dev/null
> > > > +++ b/Documentation/ABI/testing/tsemfs
> 
> ...
> 
> > > > +What:          /sys/fs/tsem/measurement
> > > > +Date:          November 2022
> > > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > > +Description:
> > > > +               The measurement file contains the ASCII base 16
> > > > +               hexadecimal representation of the 256 bit measurement
> > > > +               value of the security model that the process is
> > > > +               operating in.
> > > > +
> > > > +               The measurement value is the classic linear extension
> > > > +               measurement of the model.  An updated measurement
> > > > +               value is created by extending the current measurement
> > > > +               value with the state coefficient computed for a
> > > > +               security event.
> > > > +
> > > > +               This measurement value represents a time dependent
> > > > +               measurement of a model and is susceptible to
> > > > +               deviations caused by scheduling differences between
> > > > +               subsequent invocations of a workload.
> >
> > > Given the very volatile nature of this value, what is it used for in
> > > userspace?  My apologies if I missed it in the docs.
> >
> > It serves the same role as PCR register 10 in IMA, or any other
> > register in a TPM based architecture using a classic linear extension
> > mechanism strategy, it can be used to validate a list of time or
> > sequence ordered measurement values.
> >
> > Our personal prejudice is that these types of measurements are of
> > limited value, which is why we introduce in TSEM, the notion of the
> > 'state' value for a model, discussed below.
> >
> > I would have to go looking on lore for a reference to the exact thread
> > but Roberto Sassu had offered up a patch set for IMA that addressed
> > the deficiency of these types of measurements.

> If we all agree that this measurement isn't very useful, and you
> have implemented an alternative which is intended to address these
> usability shortcomings, why bother including this measurement in
> TSEM?

To provide comparable functionality to TPM based security
architectures, that are currently, considered state of the art for the
security industry.

As our documentation calls out, TSEM's concept of Trusted Modeling
Agent's (TMA's), are being proposed to both explore and implement next
generation hardware assisted security technologies.

Currently, the only measurements that TPM based systems support are
classic linear extension summing, which I believe we all consider to
be problematic.

That being said, the 'measurement' value can be used to validate the
order of the security event execution trajectory.  In that role it
provides the same value that PCR register 10 plays for IMA.

We believe there is a legitimate discussion that can occur, as to
whether or not this classic attestation architecture is relevant, but
it seemed appropriate to support it.

> It's relatively easy to add features to the Linux Kernel as time
> goes on, it is *very* difficult to remove them.  For this initial
> submission I would encourage you to implement the bare minimum
> functionality you need to do something useful and meet your goals.

We can certainly pull the export of the measurement value.  In that
case, would you recommend that we also pull the code that extends the
security coefficients from the root modeling domain, if a TPM is
available, into PCR register 11?

> > > > +What:          /sys/fs/tsem/points
> > > > +Date:          November 2022
> > > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > > +Description:
> > > > +               The points file contains the ASCII base 16
> > > > +               representation of the 256 bit security state points of
> > > > +               a security domain/model.  The number of entries in
> > > > +               this file represent the number of security events that
> > > > +               are represented by the model.
> >
> > > A similar questions to the tsem/measurement file.  If I understand
> > > you correctly, this is basically a series of SHA256 digests without
> > > any additional annotations, and without any ordering guarantees,
> > > yes?  What is it used for in userspace?
> >
> > The values in the points file represent the current state of a model,
> > they are the coefficients that describe the security events that have
> > been modeled.
> >
> > The output of this file can be captured and written to the
> > /sys/fs/tsem/map file in order to define a security model that is to
> > be subsequently enforced.

> Okay, I was under the assumption that this file was dependent on the
> order in which execution takes place on the system, it sounds like
> that is not the case and the output of this file is repeatable with
> a fairly standard system configuration (e.g. multi-core, multi-user,
> etc.).

Correct.

It represents the set of allowed coefficients in the description of
the functional security state of a workload.

> > > > +What:          /sys/fs/tsem/state
> > > > +Date:          November 2022
> > > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > > +Description:
> > > > +               The state file contains the ASCII base 16
> > > > +               representation of the 256 bit value of the functional
> > > > +               state of a security domain/model.
> > > > +
> > > > +               The state value is a time independent representation
> > > > +               of the measurement of a model/domain, and unlike the
> > > > +               measurement value, is a time independent
> > > > +               representation of the security state of a workload.
> > > > +
> > > > +               This value is designed to be a single value that can
> > > > +               be attested to represent whether or not a workload has
> > > > +               deviated from a defined security behavior.
> >
> > > It might be nice to explain how this value is calculated here in
> > > this file to remove any time or ordering dependencies.  Once again
> > > my apologies if I missed it in the rest of the docs.
> >
> > The TSEM LSM documentation covers the issues surrounding the
> > measurement and state values.  See the section entitled 'Security
> > model functional definitions'.

> Thanks.  A reference to the related section in the TSEM docs would
> be nice to see here.

We will add it.

> > Put succinctly, the state value is computed by generating a standard
> > linear extension sum over a list of security state points that have
> > been sorted in big-endian, ie. natural hash order.
> >
> > It is designed to provide a time and scheduling independent value that
> > can be used to attest that a security model has not violated its
> > definition.
> 
> Understood.
> 
> > Don't apologize, there is a lot there to read, our loquaciousness
> > knows no bounds.... :-)
> >
> > > > +What:          /sys/fs/tsem/trajectory
> > > > +Date:          November 2022
> > > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > > +Description:
> > > > +               The trajectory file contains a description of the
> > > > +               security events that have occurred in a security
> > > > +               domain/model.
> > > > +
> > > > +               Each entry in this file represents a single security
> > > > +               event and consists of brace {} delimited fields that
> > > > +               describe the characteristics of a security event.
> > > > +               Each field has key=value pairs that define
> > > > +               characteristics of the field.
> > > > +
> > > > +               Each line in a trajectory, or forensics, file will
> > > > +               always have the event{} and COE{} fields.  The event
> > > > +               field describes the characteristics of a security
> > > > +               event while the COE field describes the Context Of
> > > > +               Execution that is executing the security event.
> >
> > > I think it would be good to provide a concrete definition of
> > > CELL_DEFINITION field as other areas of the documentation make
> > > reference to it within the tsem/trajectory file documentation.  We can
> > > somewhat infer it's format, fields, etc. but it's much better to be
> > > explicit about these things.
> >
> > Valid point, we will incorporate a broad definition of what the 'CELL'
> > represents.
> >
> > Conceptually, it is equivalent to the 'object' in mandatory access
> > controls.  In an events based architecture like TSEM, it is
> > essentially the 'bucket' of values that describe the parameters of a
> > security event that a COE/process is requesting permission for.

> Yes, I understood conceptually what it represents and what data
> might be present given a specific operation/rule, but it wasn't
> clear to me how that data would be represented in the
> CELL_DEFINITION.

As a bit of further clarification, regarding the security model that
TSEM is based on.

A TMA extracts the event description parameters, now encoded in
JSON.. :-), into a structure and then computes a digest value,
referred to as the 'CELL identity value', over those elements, in
whatever order the TMA elects to do so in.

Further, a TMA implementation may elect to only include certain
characteristics in the computation of the CELL identity, depending on
the model being implemented.

> > > > +               The event{} field consists of the following
> > > > +               characteristic definitions:
> >
> > > I'm unclear as to the purpose of the event{} field as it is neither
> > > part of the COE or the CELL, is it here simply to make the event
> > > easier to read?  Or am I misunderstanding things and the event{}
> > > field is part of the COE?
> >
> > It actually serves two roles, one of which, as you note, is to make
> > the event description easier to read and understand.
> >
> > It probably comes as no surprise, but the trust orchestration system
> > that this is all designed to support, has a security console that can
> > be used to review the status of all the trust orchestrators that are
> > supervising security workloads.  Either in the cloud, or perhaps, a
> > large body of edge devices protecting critical infrastructure, if that
> > doesn't give away too much.... :-)
> >
> > Having the process name and executable easily visualized is fairly
> > useful.
> >
> > The second role is to allow the event description records to be
> > self-describing.  The value for the type= key is used by the Trusted
> > Modeling Agent (TMA) to determine what to look for in the remainder of
> > the event description record in order to compute the CELL value.
> >
> > It also contains the TASK_ID value that ties the security state points
> > to the integrity of the executable.  Since that value is a synthetic
> > value it was deemed most appropriate to be placed in the event{}
> > field.

> I think it would be good to provide a more succinct version of the
> above in the documentation.

We will clarify that.

> > > > +                       process=COMM
> > > > +                               Where COMM is the ASCII representation
> > > > +                               of the name of the process executing
> > > > +                               the event.
> > > > +
> > > > +                       filename=PATH
> > > > +                               If the CELL definition for an event
> > > > +                               references a file the filename
> > > > +                               characteristic contains a definition
> > > > +                               of the path to the file.
> > > > +
> > > > +                               In the case where an event does not
> > > > +                               have a file the PATH value is set to a
> > > > +                               value of none.
> >
> > > What happens in cases where multiple file paths are present in an
> > > event?  Also, given this is visible to userspace, and multiple
> > > things can affect the path to a file (e.g. namespaces), how is the
> > > file path determined?
> >
> > Unless we have missed something, which is no doubt possible, all of
> > the security event hooks that we have implemented, which number about
> > 87 now, that act on a 'file', receive only a single 'struct file *'
> > pointer as a parameter to the event.
> >
> > So we haven't encountered a situation where there would be multiple
> > files for a single event description.

> I haven't seriously looked at the TSEM sources yet, I'm trying to
> make sure that I first understand the security model while also
> ensuring that it is well documented and reasonable.  While I can't
> speak to what LSM hooks TSEM implements, it seems like there are at
> least a few operations, rename and link come immediately to mind,
> which would have multiple filenames as part of the operation.  How
> are those operations handled in TSEM, or are they outside the scope
> of TSEM?

We are currently handling them as generically modeled events so the
current model treats them as whether or not they occurred.

When they get promoted to explicitly modeled events, the current
presumption would be to include the involved filenames in the
description of the event.

> > There is certainly the case where multiple security state points
> > involve the same file.  This can easily be seen, for example, in a
> > trust orchestrator running a workload in a runc container, where
> > multiple state points are generated by different executable mappings
> > of the runc binary at startup
> >
> > The file path is the absolute pathname in the mount namespace that the
> > modeled workload is running in.

> I think it is important to specify that the path recorded here is in
> the context of the mount namespace of the task generating the event.
> Yes, one could reasonably assume that, given the disjoint nature of
> mount namespaces, but with several other fields being recorded in
> the context of the initial namespace I think it is important to note
> these differences.

We will clarify that.

> > > > +                       type=EVENT_TYPE
> > > > +                               The value field for a type key is the
> > > > +                               name of the security event that is
> > > > +                               being modeled.  The list of value
> > > > +                               EVENT_TYPE names is defined in the
> > > > +                               following source file:
> > > > +
> > > > +                               security/tsem/tsem.c
> > > > +
> > > > +                               If the security event is a generically
> > > > +                               modeled event the EVENT_TYPE will be
> > > > +                               generic_event.  In this case the CELL
> > > > +                               characteristics for the event will be
> > > > +                               described by a generic_event{} field.
> > > > +
> > > > +                       task_id=TASK_ID
> > > > +                               The value of the task_id key will the
> > > > +                               ASCII base 16 representation of the
> > > > +                               model identity of the task that is
> > > > +                               executing the security event.
> > > > +
> > > > +                               The following documentation file:
> > > > +
> > > > +                               Documentation/admin-guide/LSM/TSEM.rst
> > > > +
> > > > +                               Describes how the TASK_ID value is
> > > > +                               generated.
> > > > +
> > > > +               The COE{} field consists of the following
> > > > +               characteristic definitions:
> > > > +
> > > > +                       uid=NN
> > > > +                               The ASCII base 10 representation of
> > > > +                               the numeric value of the discretionary
> > > > +                               user id of the process that is
> > > > +                               executing the security event.
> >
> > > Given the ability to map UID/GID values in the kernel, what will be
> > > used as the basis for the COE?  What happens when the basis used in
> > > the kernel's COE generation does not match the basis used by the
> > > external modeler?
> >
> > The UID/GID values used are the values defined in the initial
> > user namespace, see security/tsem/event.c:get_COE().

> Once again, please note that in the documents.

Noted.

> > The basis set state that the trust orchestrator is running in has no
> > effect on the generation of the security state point.  The modeling
> > engine only operates on the values presented to it and determines if
> > the state point generated from the state description matches the model
> > it has been requested to enforce.
> >
> > If it doesn't, the event is considered to violate the trust model.
> >
> > > > +                       euid=NN
> > > > +                               The ASCII base 10 representation of
> > > > +                               the numeric value of the effective
> > > > +                               discretionary user id of the process
> > > > +                               that is executing the security event.
> > > > +
> > > > +                       euid=NN
> > > > +                               The ASCII base 10 representation of
> > > > +                               the numeric value of the effective
> > > > +                               discretionary user id of the process
> > > > +                               that is executing the security event.
> > > > +
> > > > +                       suid=NN
> > > > +                               The ASCII base 10 representation of
> > > > +                               the numeric value of the saved user id
> > > > +                               of the process that is executing the
> > > > +                               security event.
> > > > +
> > > > +                       gid=NN
> > > > +                               The ASCII base 10 representation of
> > > > +                               the numeric value of the discretionary
> > > > +                               group id of the process that is
> > > > +                               executing the security event.
> > > > +
> > > > +                       egid=NN
> > > > +                               The ASCII base 10 representation of
> > > > +                               the numeric value of the discretionary
> > > > +                               effective group id of the process that
> > > > +                               is executing the security event.
> > > > +
> > > > +                       egid=NN
> > > > +                               The ASCII base 10 representation of
> > > > +                               the numeric value of the discretionary
> > > > +                               effective group id of the process that
> > > > +                               is executing the security event.
> > > > +
> > > > +                       sgid=NN
> > > > +                               The base 10 ASCII representation of
> > > > +                               the numeric value of the saved
> > > > +                               discretionary group id of the process
> > > > +                               that is executing the security event.
> > > > +
> > > > +                       fsuid=NN
> > > > +                               The base 10 ASCII representation of
> > > > +                               the numeric value of the discretionary
> > > > +                               filesystem user id of the process that
> > > > +                               is executing the security event.
> > > > +
> > > > +                       fsgid=NN
> > > > +                               The ASCII base 10 representation of
> > > > +                               the numeric value of the discretionary
> > > > +                               filesystem group id of the process
> > > > +                               that is executing the security event.
> > > > +
> > > > +                       cap=0xNNN
> > > > +                               The ASCII base 16 representation of
> > > > +                               the numeric value of effective
> > > > +                               capabilities of the process that is
> > > > +                               executing the security event.
> > > > +
> > > > +               If the CELL value for a security event includes the
> > > > +               definition of a file a file{} event field will be
> > > > +               included.  The following characteristics will be
> > > > +               encoded in this field:
> > > > +
> > > > +                       flags=NN
> > > > +                               The ASCII base 10 representation of
> > > > +                               the flags value of the 'struct file'
> > > > +                               structure that is the source of the
> > > > +                               file description.
> > > > +
> > > > +                       uid=NN
> > > > +                               The ASCII base 10 representation of
> > > > +                               the discretionary user id of the file.
> > > > +
> > > > +                       gid=NN
> > > > +                               The base 10 ASCII representation of
> > > > +                               the discretionary group id of the
> > > > +                               file.
> >
> > > Similar to the task UID/GID mapping questions above, there are
> > > mechanisms which map the file user/group IDs, which will be used in
> > > the CELL definition and how will that be resolved between the kernel
> > > and an external modeler?
> >
> > The answer is the same as with the COE, see the following function:
> >
> > security/tsem/event.c:get_file_cell()
> >
> > Once again, the TMA only operates on the event description presented
> > to it and is not influenced by its own namespace.

> For this particular point, my concern isn't what policy the TMA
> implements, or what it uses as input, it's about understanding how
> this event information is collected.  For fields which can be
> namespaced (I'm referring to "normal" Linux Kernel namespaces and
> not any TSEM namespaces), the TSEM documentation should make it
> clear which namespace is used as a basis for the value.

FWIW, based on feedback we have received, there may be a modeling
domain/namspace setup option forthcoming that allows a trust
orchestrator to request that the uid/gid et.al characteristics be
exported in the context of the current user namespace.

> > > > +What:          /sys/fs/tsem/ExternalTMA
> > > > +Date:          November 2022
> > > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > > +Description:
> > > > +               The ExternalTMA directory is a container directory
> > > > +               that hold files that will be used to export the
> > > > +               security events, and their associated parameters, for
> > > > +               externally modeled security domains/namespaces.
> > > > +
> > > > +               The files created in this directory will be named by
> > > > +               the base 10 ASCII representation of the id value
> > > > +               assigned to the modeling domain/namespace.  See the
> > > > +               documentation for the /sys/fs/tsem/id file in this
> > > > +               documentation for more details on this value.
> > > > +
> > > > +               This file will is a read-only file that can be polled
> > > > +               by a userspace trust orchestration implementation to
> > > > +               process security events that are to be modeled by
> > > > +               an external Trusted Modeling Agent.
> > > > +
> > > > +               The type of the exported event is the first keyword of
> > > > +               the line that is output and have the following
> > > > +               values and arguments:
> > > > +
> > > > +               aggregate HEXID:
> > > > +                       Where HEXID is the ASCII base 16
> > > > +                       representation of the 256 bit hardware
> > > > +                       platform aggregate value.
> > > > +
> > > > +               export pid{NNN} COE{} CELL_DEFINITION
> > > > +                       Where the NNN in the pid field is the ASCII
> > > > +                       base 10 value of the id of the process that is
> > > > +                       executing the security event that will be
> > > > +                       modeled.
> >
> > > I worry whenever I see a PID used as an identifier shared across the
> > > kernel/userspace boundary as it is inherently racy.  Given the
> > > somewhat coarse COE definition where one can expect multiple
> > > processes/PIDs to share the same COE value, and the ability of
> > > untrusted users/processes to manipulate the PID table, what do you
> > > expect to use the pid{NNN} field for in this event?
> > >
> > > Similar to the other namespace/mapping issues discussed previously,
> > > there is also the PID namespace issue to worry about.  How is that
> > > handled here?
> >
> > The concern over the PID issue is understandable, I will treat the
> > reasoning behind its use below.
> >
> > The PID value is the 'native' value managed by the kernel, not a
> > mapped value.

> Regardless of if the PID is rooted in the initial namespace or a
> different PID namespace, the issue of PIDs being inherently racy is
> a real problem.  Can you help me understand how TSEM avoids the
> common pitfalls associated with using PIDs to identify processes on
> the system?

The second version of the TSEM series, now includes support for a
requirement that a process being externally modeled, authenticate
itself to the TMA in order for the trust control call to act on
the process.

> > > > +                       The COE field has the same format as the field
> > > > +                       emitted for a trajectory or forensics event.
> > > > +
> > > > +                       The CELL_DEFINITION are the same field
> > > > +                       definitions that are emitted for a trajectory
> > > > +                       or forensics event.
> > > > +
> > > > +               log process{name} event{type} action{type}
> > > > +                       The log event is emitted when an untrusted
> > > > +                       task attempts to execute a security event.
> > > > +
> > > > +                       The name value of the COE field is the name of
> > > > +                       the process (comm value) that is executing the
> > > > +                       security event.
> > > > +
> > > > +                       The type value of the event field is the name
> > > > +                       of the security event being executed as
> > > > +                       defined in the tsem_names array in the
> > > > +                       security/tsem/tsem.c file.
> > > > +
> > > > +                       The type value of the action field is the type
> > > > +                       of action the LSM enforced in response to
> > > > +                       encountering the untrusted process.  This
> > > > +                       value will be either LOG or EPERM to represent
> > > > +                       whether or not the trust violation is being
> > > > +                       logged or enforced.
> > > > +
> > > > +What:          /sys/fs/tsem/control
> > > > +Date:          November 2022
> > > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > > +Description:
> > > > +               The control file is the only writable file in the
> > > > +               filesystem and is used by the trust orchestrators to
> > > > +               configure and control the behavior of the TSEM
> > > > +               implementation.
> > > > +
> > > > +               The following keyword and arguments are recognized:
> > > > +
> > > > +               internal:
> > > > +                       The internal keyword causes an internally
> > > > +                       modeled domain to be created for the calling
> > > > +                       process.
> > > > +
> > > > +               external:
> > > > +                       The external keyword causes an externally
> > > > +                       modeled domain to be created for the calling
> > > > +                       process.
> > > > +
> > > > +               enforce:
> > > > +                       The enforce keyword causes the modeling
> > > > +                       domain/namespace of the process to enter
> > > > +                       enforcing mode.  In this mode a value of
> > > > +                       -EPERM will be returned for a security event
> > > > +                       that does not map into the current set of
> > > > +                       allowed state points for the security model
> > > > +                       being implemented for the domain/namespace.
> > > > +
> > > > +               seal:
> > > > +                       The seal keyword causes the security model
> > > > +                       being implemented for the model to be placed
> > > > +                       in sealed state.  In this state the current
> > > > +                       set of security event points is considered to
> > > > +                       be the only set of valid points for the
> > > > +                       domain/model.  Any subsequent events that map
> > > > +                       to a point not in the current model will be
> > > > +                       considered a violation of the model.
> > > > +
> > > > +               trusted PID:
> > > > +                       The trusted keyword is used by a trust
> > > > +                       orchestrator to indicate that the process
> > > > +                       identified by the PID argument should be
> > > > +                       allowed to run in trusted status.
> > > > +
> > > > +               untrusted PID:
> > > > +                       The untrusted keyword is used by a trust
> > > > +                       orchestrator to indicate that the process
> > > > +                       identified by the PID argument should be
> > > > +                       allowed to run but designated as an untrusted
> > > > +                       process.
> >
> > > The 'trusted PID:' and 'untrusted PID:' commands are concerning for
> > > the reasons described above about PIDs being racy and generally an
> > > unreliable way of identifying processes across the kernel/userspace
> > > boundary.  I suspect it would not be too difficult for a malicious
> > > user to trick an external modeler into marking the wrong process as
> > > trusted/untrusted.
> >
> > An external TMA needs the PID value to determine which process to wake
> > up and set the trust status value on in the task control structure,
> > after the event is modeled.  As was noted above, the PID value is the
> > unmapped value maintained by the OS.
> >
> > Lets see if we can reason through why the PID can be used safely.
> >
> > CAP_TRUST, or whatever ends up getting used, is required by the trust
> > orchestrator to create a security/modeling namespace for the workload
> > being modeled.  This results in the creation of the following
> > pseudo-file for surfacing the security event descriptions for the
> > namespace/workload:
> >
> > /sys/fs/tsem/ExternalTMA/N
> >
> > Where N is the id number of the modeling domain.
> >
> > CAP_TRUST, caveats applied, is required to open the pseudo-file.  The
> > trust orchestrator only receives and acts on PID values through this
> > conduit from the kernel.
> >
> > When an event description is exported, the trust status of the task is
> > set to 'pending' and the process is placed in interruptible sleep and
> > scheduled away, with the 'wakeup' criteria being the trust status
> > being changed from pending to either trusted or untrusted.
> >
> > The only path to change the trust status value in the LSM task control
> > structure and wake up the process is by the trust orchestrator that
> > created the namespace, by writing the appropriate value to the
> > /sys/fs/tsem/control file.  Access to that file is gated by CAP_TRUST
> > or its equivalent.
> >
> > See the following code locations for further details:
> >
> > security/tsem/export.c:tsem_export_event()
> >
> > security/tsem/fs.c:control_COE()
> >
> > As long as the process 'exists', albeit sleeping, the PID slot is
> > occupied and an adversary, regardless of namespace, cannot substitute
> > a task with the same PID value.
> >
> > This leaves an adversary with the need to terminate the task being
> > modeled in order to capture its PID slot.
> >
> > Precautions are implemented in the following function to protect the
> > process from being terminated by an adversary:
> >
> > security/tsem/tsem.c:tsem_task_kill()

> What about the OOM killer?
> 
> The security_task_kill() LSM hook only offers an access control point
> for one process sending another process a signal, it doesn't gate a
> process being killed for other reasons.  The OOM killer is the first
> thing that comes to mind, but I'm reasonably certain there are other
> similar scenarios.

As noted above, as an additional protection, the next version of the
series requires that a process authenticate itself as being a member
of the modeling domain in order for the trust status control call to
succeed.

With this implementation, substituting an alternate process would now
require that an adversary break the security context between the TMA
and process in the modeling domain.

> > > > +               state HEXID:
> > > > +                       The state keyword is used to indicate that the
> > > > +                       security state point identified by the ASCII
> > > > +                       base 16 encoded value should be loaded into
> > > > +                       the current security model as a valid security
> > > > +                       event state.
> > > > +
> > > > +               pseudonym HEXID
> > > > +                       The pseudonym keyword is used to indicate that
> > > > +                       the pathname, identified by the 256 bit ASCII
> > > > +                       base 16 encoded value HEXID, should be
> > > > +                       designated to return a constant digest value
> > > > +                       for the contents of the file.
> > > > +
> > > > +                       The HEXID value is computed with the following
> > > > +                       function:
> > > > +
> > > > +                       HEXID = SHA256(PATHNAME_LENGTH || PATHNAME)
> >
> > > This seems like an unusual design choice, and perhaps one born from
> > > necessity ... ?  It's nice that it is opt-in, but I would be curious
> > > to hear what problems this solved.
> >
> > It is an approximation method that allows things like log files and
> > .bash_history files to be effectively modeled.
> 
> Okay, that's what I suspected, I just wanted to make sure there wasn't
> something else I was missing.
> 
> > > > +               base HEXID
> > > > +                       The base keyword is used to indicate that the
> > > > +                       256 bit ASCII base 16 encoded value HEXID
> > > > +                       should be registered as the value used to
> > > > +                       generate model specific security event points.
> > > > +
> > > > +                       A model specific base value is designed to be
> > > > +                       used as a 'freshness' nonce, similar to an
> > > > +                       attestation nonce, to prove that a model state
> > > > +                       value or measurement is current and not being
> > > > +                       replayed.
> > > > diff --git a/Documentation/admin-guide/LSM/tsem.rst b/Documentation/admin-guide/LSM/tsem.rst
> > > > new file mode 100644
> > > > index 000000000000..f03e5269cd25
> > > > --- /dev/null
> > > > +++ b/Documentation/admin-guide/LSM/tsem.rst
> > > > @@ -0,0 +1,1240 @@
> > > > +====
> > > > +TSEM
> > > > +====
> > >
> > > ...
> > >
> > > > +Process and Platform Trust Status
> > > > +=================================
> > > > +
> > > > +A fundamental concept in TSEM is the notion of providing a precise
> > > > +definition for what it means for a platform or workload to be trusted.
> > > > +A trusted platform or workload is one where there has not been an
> > > > +attempt by a process to execute a security relevant event that does
> > > > +not map into a known security state point.
> > > > +
> > > > +The process trust status is a characteristic of the process that is
> > > > +passed to any subordinate processes that are descendants of that
> > > > +process.  Once a process is tagged as untrusted, that characteristic
> > > > +cannot be removed from the process.  In a 'fruit from the poisoned
> > > > +vine' paradigm, all subordinate processes created by an untrusted
> > > > +process are untrusted as well.
> > > > +
> > > > +On entry into each TSEM security event handler, the trust status of a
> > > > +process is checked before an attempt to model the event is made.  An
> > > > +attempt to execute a security event by an untrusted process will cause
> > > > +the event, and its characteristics, to be logged.  The return status
> > > > +of the hook will be determined by the enforcement state of the model.
> > > > +A permission denial is only returned if the TMA is running in
> > > > +enforcing mode.
> > > > +
> > > > +If the platform running the TSEM LSM has a TPM, the hardware aggregate
> > > > +value is computed at the time that TSEM is initialized.  This hardware
> > > > +aggregate value is the linear extension sum over Platform
> > > > +Configuration Registers (PCR's) 0 through 7.  This is the same
> > > > +aggregate value that is computed by the Integrity Measurement
> > > > +Architecture (IMA) and is the industry standard method of providing an
> > > > +evaluation measurement of the hardware platform state.
> > > > +
> > > > +Internally model domains have the hardware aggregate measurement
> > > > +included as the first state point in the security model.  Externally
> > > > +modeled domains export the hardware aggregate value to the TMA for
> > > > +inclusion as the first state point of the model maintained by the TMA.
> > > > +
> > > > +The root modeling domain extends each security state point into PCR
> > > > +11.  This allows hardware based TSEM measurements to coexist with IMA
> > > > +measurement values.  This hardware measurement value can be used to
> > > > +attest to the security execution trajectory that the root model
> > > > +maintains.
> >
> > > It seems like making the target PCR configurable would be a good
> > > idea, at the very least make it a Kconfig option.
> >
> > That was something that we have thought about, it probably needs a
> > Kconfig option.
> >
> > Contrary to all appearances, as a team we are really minimalists at
> > heart and tend to not make things more complex or configurable than
> > needed.... :-)
> >
> > > Also, can you elaborate on how the security state points are
> > > extended into the PCR?  I imagine for it to be useful at an
> > > arbitrary point in time this would require the PCR to be extended as
> > > the security points were generated, which would imply that the PCR
> > > value would be dependent on execution order, and in most cases,
> > > scheduling order as well.  How useful do you expect this to be for
> > > most users?
> >
> > Your assessment is correct, the state points are extended into the PCR
> > whenever a unique security state point is generated.
> >
> > In a 'free-running' model, the value in the register will be fungible
> > due to scheduling dependencies.

> In other words, garbage ;)

We don't disagree on the utility of a scheduling fungible measurement
value.  However, this is an remarkably interesting
conclusion/statement, by the Linux security sub-system maintainer no
less, given that it describes the current state of the art with
respect to hardware security co-processors and trusted system
technology.. :-)

> > If the model is pre-defined, the security state points will be
> > extended into the register as they are loaded through the
> > /sys/fs/tsem/map pseudo-file interface.  In this case, the value will
> > be fixed and any departure from the value would signal that the
> > modeling domain has departed from its specification.
> >
> > With respect to the utility of the value, in a 'free-running' model it
> > is about as useful as the value that IMA maintains in PCR 10, which in
> > our opinion is not very useful and is why we implemented the notion of
> > the 'state' value of a model.

> For a variety of reasons, and mostly to help keep things civil,
> let's refrain from comparing one LSM to another.  Each LSM makes its
> own choices, and needs to stand on its own; just because LSM did X
> doesn't mean TSEM can do X if it is silly in the context of TSEM.

Our intent was not to be incivil, but rather to call out one of the
motivations in the implementation of TSEM, and in a larger context,
the notion of a TMA based security architecture.

A now prehistoric version of TSEM was implemented as a patch on top of
IMA.  We actually built systems for clients on top of that
architecture.  Our concept of a 'state' value was driven by the
difficulties we experienced in implementing, and maintaining, these
systems in a field environment.

We offer the concept of a 'state' value in order to simplify the
attestation model, which classically, has required that a verifying
party review an event log for its validity, after verifying that the
measurement value confirms the integrity of the log.

> > The primary utility of the value is that it is a hardware maintained
> > reference value that can be used to confirm the set of measurements
> > committed to the register.

> Given that the PCR value is only deterministic in the case of a
> predefined policy/model, it seems like it would be worth stating that
> a bit more clearly in the docs.

We thought it was covered thoroughly in the 'Security model functional
definitions' section of the tsem.rst file, but we are reviewing all of
that, including the context of the ABI documentation.

> > So our 'state' value gives us a constant 'good' value for the security
> > model.  The PCR 11 value provides a hardware root of trust for the set
> > of points that lead to the state value.

> Just to make sure I understand you, in the predefined case PCR 11 is
> extended with the SRTM PCRs as well as a measurement of the TSEM
> policy at load time, yes?

To be clear, PCR 11 is only extended for events generated in the root
modeling domain, a TMA acts as a virtual TPM so it maintains its own
measurement values.

To the specific point, you are correct, the aggregate value is
injected as the first measurement into a modeling domain.

> > > > +Internal vs external modeling
> > > > +-----------------------------
> > > > +
> > > > +When a TSEM modeling domain is created, a designation is made as to
> > > > +whether the domain is to be internally or externally modeled.
> > > > +
> > > > +In an internally modeled domain, the security event handlers pass the
> > > > +event type and its characteristics to the designated internal trusted
> > > > +modeling agent.  The agent provides the permission value for the
> > > > +security event handler to return as the result of the event and sets
> > > > +the trust status of the process executing the event.
> > > > +
> > > > +In an externally modeled domain, the event type and parameters are
> > > > +exported to userspace for processing by a trust orchestrator with an
> > > > +associated TMA.  The trust orchestrator communicates the result of the
> > > > +modeling back to the kernel to support the setting of the process
> > > > +trust status.
> > > > +
> > > > +This model poses a limitation to the ability of TSEM to model some
> > > > +security events.  This is secondary to the fact that some event
> > > > +handlers (LSM hooks) are called from a non-sleeping context, as a
> > > > +result the process cannot be scheduled.  This is particularly the case
> > > > +with the task based hooks, since they are typically called with the
> > > > +tasklist lock held.
> > > > +
> > > > +This limitation is also inherent to the root model that extends the
> > > > +security state points into TPM PCR 11, secondary to the fact that the
> > > > +process invoking the security event hook will be scheduled away while
> > > > +the TPM transaction completes.
> > > > +
> > > > +Addressing this problem directly requires a consideration of the
> > > > +context from which the security event handlers are being called.
> > > > +Subsequent implementations of TSEM will include a mechanism for
> > > > +asynchronous deferral of model processing, until when and if, a review
> > > > +of the call context would be considered worthwhile by the LSM
> > > > +community.
> >
> > > This is a pretty big limitation, and in conjunction with the some of
> > > the other issues brought up earlier (the PID issue seems the most
> > > concerning), I'm having a difficult time believeing that an external
> > > modeler could operate safely given the design presented here.
> >
> > With respect to the PID issue, we would welcome any comments on the
> > analysis that we provided above as to its design safety.
> 
> >From what I can tell from the documentation and our discussion thus
> far is that TSEM relies on a security_task_kill() hook implementation
> to ensure that a process is not killed, and the PID released, without
> explicit TSEM approval.  Unfortunately, I believe that relying solely
> on security_task_kill() will not fully cover all of the cases where a
> process can be killed, mostly because security_task_kill() does not
> control process destruction, it controls the ability of one process to
> signal another.

> You might be able to do something with security_task_free(), but I
> haven't given that much thought.

Our analysis suggested that an authentication strategy was the
strongest and most complete implementation moving forward.

> > If the PID issue remains a concern, we have an extension to the export
> > descriptions that would include a random nonce that would be emitted
> > with the PID.  The nonce would be placed in the LSM task control
> > 'blob' for the sleeping task and used to confirm that the task release
> > directive was acting on the correct process.

> That should help, but ultimately a nonce is still a bounded resource
> and subject to recycling just like the PID.  I'm open to hearing
> other ways in which you believe you can resolve this issue, but I
> remain skeptical.

FWIW, I believe that current thinking is that a nonce based on a
64-bit value is immune from recycling.  The classic metric for a
64-bit counter is that a consumption rate of 1000 values/second yields
a counter cycle time of 584,942,417 years.  Nanosecond rates still
buys you 584 years.

I believe that Jason built the Wireguard protocol on this predicate.

We believe the second series will fully address this issue, without
using nonces, for whatever that is worth.  We can reserve further
discussion once that code is available and submitted for review.

> > > Unfortunately, there will always be LSM hooks which need to operate
> > > in a non-blocking context, meaning this challenge is here to stay.
> > > Help me understand how you could safely do asynchronous policy
> > > enforcement with an external modeler, I'm not sure it's possible.
> >
> > Electing to implement asynchronous enforcement would require further
> > thought.  We were operating in the context of full disclosure in our
> > documentation and wanted to be up front about limitations and options.
> >
> > To be clear, at this time, we are not advocating for or bringing
> > forward an asynchronous update architecture.
> >
> > So, at this time, there is a well understood modeling limitation with
> > respect to the LSM hook implementations.  That limitation is not
> > limited to external TMA's, since the event state points cannot be
> > extended into a TPM in a non-blocking context.

> I think these limitations need to be made explicit in the
> documentation.  If the TSEM security model can not be faithfully
> implemented, the documented security model may need to change.

We will further explain the trade-offs between the different modeling
environments in the documentation.

> > > Frankly, I also wonder how a system would perform with an external
> > > modeler, indepdent of the issues with non-blocking hooks.  How does
> > > the system perform with every blockable LSM hook invocation
> > > potentially blocking on a response from userspace?  Or with the COE
> > > being somewhat coarse, does the trajectory/policy populate itself
> > > quickly?
> >
> > One obviously experiences a latency hit in going to userspace, by
> > definition, implementing security always has an associated resource
> > cost.  So, once again, this comes down to a cost/benefit analysis.
> >
> > As a Gedanken exercise, consider the value proposition of a Linux
> > based RTU, or other device, controlling infrastructure that can only
> > execute security relevant events that are guaranteed to be known good
> > by an external co-processor that is only accessible as a security
> > oracle.
> >
> > Given that frame of reference.
> >
> > Time for a userspace or SGX based TMA transaction is running around
> > 890 micro-seconds.
> >
> > Going to a TMA based in a Xen stubdomain implementation runs a bit
> > longer, probably around 940 micro-seconds or so.
> >
> > The micro-controller implementations are decidedly slower, with the
> > NRF52840-DONGLE clocking in at around 40 micro-seconds, but that is
> > strictly a CPU horsepower issue.
> >
> > All of this with the caveat that we have been focusing almost
> > exclusively on correctness and not optimizing performance.
> >
> > We've thought a bit, mainly on long walks with our Golden Retriever
> > Izzy, about the issue of building a kernel based policy cache with
> > externally modeled domains.  Given that the kernel does not, a-priori,
> > know what modeling algorithm a TMA might be using, we would need to
> > come up with a method of deterministically mapping a security event
> > description to a known good state point value.
> >
> > The other issue with all this is that with containerized workloads,
> > particularly micro-services, the rate of security event generation can
> > be surprisingly low.  Obviously this is also the case with embedded
> > implementations.
> >
> > Once again, what are you willing to pay to be safe?

> For better or worse, when code is proposed for the upstream Linux
> Kernel it is subject to scrutiny from all manner of developers and
> users, with most being focused on their own pet projects/subsystems,
> not whatever new security promises you are providing.
> 
> There have been patch(sets) and discussions relating to performance
> gains/losses on the other of tens of nanoseconds per operation.
> 
> I think most of us in the security community are sympathetic to the
> question of "what are you willing to pay to be safe", but please
> understand that while we are understanding, there are others who will
> disagree not only with the performance cost tradeoff, but the very
> idea of safety you are promising.  My only suggestion is to be
> prepared, and be honest with the performance assessments of TSEM.

We seem to be in agreement that there will always be a natural tension
between security and performance.  With TSEM our goal is to offer
choices.

If an environment is sensitive to performance defects on the order of
tens of nanoseconds, it would seem unlikely that the architects or
administrators of such systems would be implementing integrity
controls of any kind.  In that context, we are no different than IMA
or IPE, it would seem highly unlikely that such environments are going
to tolerate a security solution involving a cryptographic checksum of
any type.

fTPM's and embedding TPM style functionality on the core, ie. the
Microsoft Pluton model, may change all of this, but currently hitting
a discrete TPM isn't a fast operation either.

So, with respect to choices.

We offer the tsem_mode= kernel command-line argument in order to
support only namespace based modeling.  In that configuration, the
performance penalty is paid only by workloads where a decision is made
to run them in a modeled security environment.

From that point, you have a choice on whether a security namespace
should be internally or externally modeled.  Optimum performance, of
course, would be with an internally modeled domain.

There is also the option of completely disabling TSEM by using the
'lsm=' command-line option

So hopefully all of this indicates honesty with respect to performance
issues.

In any event, we will make it clear in the documentation that electing
to use external modeling will have a performance hit and the
mechanisms available for addressing that issue.

With respect to external modeling, significant advantage is that it
opens the door to being able to implement alternate security models
without writing kernel code, which is not inconsequential, given the
challenges to working in kernel context let alone getting code
upstreamed and accepted by distributions.

In some cases, such as SGX, the only way to integrate those types of
protections into a TMA architecture is to go to userspace.

We currently have micro-controller based TMA implementations that have
embedded CAT-1M cellular modems that allow modeling, auditing and
alerting to be done entirely outside of the kernel.  It is probably no
surprise that it is profoundly easier to build these types of
architectures outside of the kernel.

> > > > +Event handlers that cannot be directly modeled, still consider, on
> > > > +entry, whether or not they are being called by an trusted or untrusted
> > > > +process.  As a result, an untrusted process will cause a non-modeled
> > > > +event to return a permissions violation in enforcing mode, even if the
> > > > +security event cannot be directly modeled.
> > > > +
> > > > +Security event modeling typically traps violations of trust by a COE
> > > > +with unmodeled characteristics that is attempting to access/execute a
> > > > +file or map memory as executable; or by a COE with known
> > > > +characteristics attempting to access or execute a CELL not prescribed
> > > > +by a model.  As a result, the impact of the ability to not directly
> > > > +model these events is lessened.
> > >
> > > ...
> > >
> > > > +Event modeling
> > > > +--------------
> > > > +
> > > > +TSEM security event modeling is based on the following functional
> > > > +definition for a security state point:
> > > > +
> > > > +Sp = SHA256(SHA256(EVENT_ID) || TASK_ID || SHA256(COE) || SHA256(CELL))
> >
> > > It appears that all of the hasing in TSEM is SHA256 based, you might
> > > want to consider making that a Kconfig option at the very least.
> >
> > That has been something that we have talked about as well.
> >
> > As I indicated previously, we really are minimalists, particularly
> > after watching IMA fight with issues surrounding algorithmic agility.
> >
> > It would be easy enough to make this configurable but does anyone see
> > SHA256 as not being useful in in this role anywhere in the next 10
> > years?

> There are any number of reasons why one might need to select a
> different hash algorithm: legal constraints, security
> certifications, corporate policy.  I would strongly suggest making
> this configurable.

Certainly sound and well reasoned advice, but the question then becomes
what hashes and what hash lengths, do you have any specific
recommendations?

IMA currently has the options of SHA1, SHA256, SHA512, WHIRLPOOL512
and SM3; is this sufficient coverage, given that SHA1 in a new
implementation like TSEM probably doesn't make any sense?

Our current inclination, for the initial release, in an embrace of
minimalisim, would be to make this a selectable option when a modeling
domain is setup, with the only selectable option being SHA256.  This
would place the onus on userspace to make the decision and doesn't
lock the kernel to an ABI.

We would obviously pair this with a kernel command-line option for the
root modeling domain.

In the meantime we will start work on the infrastructure needed to
support an adequate amount of 'cryptographic agility', whatever group
consensus would suggest that to be..

> paul-moore.com

Let us know if we can provide any additional clarifications.

Otherwise, the most efficient use of your review time would be to give
us a quick overview on any style issues you see.  The second patch
series already represents a sufficient delta that time spent reviewing
the current code for correctnes wouldn't be an optimum use of your
time.

Best wishes for a productive week.

As always,
Dr. Greg

The Quixote Project - Flailing at the Travails of Cybersecurity

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 02/14] Add TSEM specific documentation.
  2023-03-13 22:52         ` Dr. Greg
@ 2023-03-22 23:45           ` Paul Moore
  2023-03-30  3:34             ` Dr. Greg
  0 siblings, 1 reply; 42+ messages in thread
From: Paul Moore @ 2023-03-22 23:45 UTC (permalink / raw)
  To: Dr. Greg; +Cc: linux-security-module

On Mon, Mar 13, 2023 at 6:52 PM Dr. Greg <greg@enjellic.com> wrote:
> On Thu, Mar 02, 2023 at 11:15:56PM -0500, Paul Moore wrote:
>
> Hi Paul, thanks for sending along further comments.
>
> You note below that you haven't had time to look at the code since you
> wanted to confirm the TSEM security model before moving forward.
>
> From a development perspective we are now three weeks into what will
> become version 2 of the patch series.  So at this point I wouldn't
> advocate spending a lot of time on the current patchset.
>
> That being said, if you some have time, we would appreciate a quick
> look at the code on your part, with respect to style changes and the
> like we can enforce in the second series, ie. ordering of local
> variable declarations by length and the like.

To be perfectly honest I'm still very concerned about some of the
issues that I've seen in the docs, until that is sorted out I'm not
sure there is much point in looking at the code.

> > On Tue, Feb 14, 2023 at 6:58???AM Dr. Greg <greg@enjellic.com> wrote:
> > > On Sun, Feb 12, 2023 at 11:33:26PM -0500, Paul Moore wrote:
> > > > On Sat, Feb 4, 2023 at 12:33 AM Dr. Greg <greg@enjellic.com> wrote:
> > > > >
> > > > > An entry was added to the ABI testing documentation to document
> > > > > the files in the TSEM management filesystem.
> > > > >
> > > > > The file documenting the kernel command-line parameters was
> > > > > updated to document the tsem_mode command-line parameter.
> > > > >
> > > > > The primary TSEM documentation file was added to the LSM
> > > > > administration guide and the file was linked to the index of LSM
> > > > > documentation.
> > > > >
> > > > > Signed-off-by: Greg Wettstein <greg@enjellic.com>
> > > > > ---
> > > > >  Documentation/ABI/testing/tsemfs              |  576 ++++++++
> > > > >  Documentation/admin-guide/LSM/index.rst       |    1 +
> > > > >  Documentation/admin-guide/LSM/tsem.rst        | 1240 +++++++++++++++++
> > > > >  .../admin-guide/kernel-parameters.txt         |    5 +
> > > > >  4 files changed, 1822 insertions(+)
> > > > >  create mode 100644 Documentation/ABI/testing/tsemfs
> > > > >  create mode 100644 Documentation/admin-guide/LSM/tsem.rst
> > >
> > > > One of the more important requirements for any new LSM is that it
> > > > documents a clear, understandable, and reasonable security model along
> > > > with an implementation that faithfully implements that model.  Before
> > > > I looked at your code I wanted to try and understand the TSEM security
> > > > model and a few things jumped out at me rather quickly, I imagine
> > > > there would be others as I start to look a bit closer but I wanted to
> > > > send these questions/comments along now to get your take on them ...
> > >
> > > Hi Paul, thanks for taking time to review the documentation and raise
> > > questions, responses below.
> > >
> > > > > diff --git a/Documentation/ABI/testing/tsemfs b/Documentation/ABI/testing/tsemfs
> > > > > new file mode 100644
> > > > > index 000000000000..3d326934624c
> > > > > --- /dev/null
> > > > > +++ b/Documentation/ABI/testing/tsemfs
> >
> > ...
> >
> > > > > +What:          /sys/fs/tsem/measurement
> > > > > +Date:          November 2022
> > > > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > > > +Description:
> > > > > +               The measurement file contains the ASCII base 16
> > > > > +               hexadecimal representation of the 256 bit measurement
> > > > > +               value of the security model that the process is
> > > > > +               operating in.
> > > > > +
> > > > > +               The measurement value is the classic linear extension
> > > > > +               measurement of the model.  An updated measurement
> > > > > +               value is created by extending the current measurement
> > > > > +               value with the state coefficient computed for a
> > > > > +               security event.
> > > > > +
> > > > > +               This measurement value represents a time dependent
> > > > > +               measurement of a model and is susceptible to
> > > > > +               deviations caused by scheduling differences between
> > > > > +               subsequent invocations of a workload.
> > >
> > > > Given the very volatile nature of this value, what is it used for in
> > > > userspace?  My apologies if I missed it in the docs.
> > >
> > > It serves the same role as PCR register 10 in IMA, or any other
> > > register in a TPM based architecture using a classic linear extension
> > > mechanism strategy, it can be used to validate a list of time or
> > > sequence ordered measurement values.
> > >
> > > Our personal prejudice is that these types of measurements are of
> > > limited value, which is why we introduce in TSEM, the notion of the
> > > 'state' value for a model, discussed below.
> > >
> > > I would have to go looking on lore for a reference to the exact thread
> > > but Roberto Sassu had offered up a patch set for IMA that addressed
> > > the deficiency of these types of measurements.
>
> > If we all agree that this measurement isn't very useful, and you
> > have implemented an alternative which is intended to address these
> > usability shortcomings, why bother including this measurement in
> > TSEM?
>
> To provide comparable functionality to TPM based security
> architectures, that are currently, considered state of the art for the
> security industry.
>
> As our documentation calls out, TSEM's concept of Trusted Modeling
> Agent's (TMA's), are being proposed to both explore and implement next
> generation hardware assisted security technologies.
>
> Currently, the only measurements that TPM based systems support are
> classic linear extension summing, which I believe we all consider to
> be problematic.
>
> That being said, the 'measurement' value can be used to validate the
> order of the security event execution trajectory.  In that role it
> provides the same value that PCR register 10 plays for IMA.
>
> We believe there is a legitimate discussion that can occur, as to
> whether or not this classic attestation architecture is relevant, but
> it seemed appropriate to support it.

It is relatively easy to add user visible features to the kernel, but
it's almost impossible to remove them.  If you see little value in
feature X, to the point that you've developed an alternate mechanism
to avoid the shortcomings which limit the usefulness of X, why include
it?  If you later realize that it is important you can always add it.

Add new functionality to the kernel because it meets a user need, not
simply because "everybody else is doing it".  If you've got a defined
use case for this, keep it; however, if you can't define a reasonable
use case I would suggest dropping it and making your life easier.

> > It's relatively easy to add features to the Linux Kernel as time
> > goes on, it is *very* difficult to remove them.  For this initial
> > submission I would encourage you to implement the bare minimum
> > functionality you need to do something useful and meet your goals.
>
> We can certainly pull the export of the measurement value.  In that
> case, would you recommend that we also pull the code that extends the
> security coefficients from the root modeling domain, if a TPM is
> available, into PCR register 11?

Once again, if you've got a use case, keep it; if not, drop it.  Don't
add to the kernel API without a use case.

> > > > > +What:          /sys/fs/tsem/trajectory
> > > > > +Date:          November 2022
> > > > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > > > +Description:
> > > > > +               The trajectory file contains a description of the
> > > > > +               security events that have occurred in a security
> > > > > +               domain/model.
> > > > > +
> > > > > +               Each entry in this file represents a single security
> > > > > +               event and consists of brace {} delimited fields that
> > > > > +               describe the characteristics of a security event.
> > > > > +               Each field has key=value pairs that define
> > > > > +               characteristics of the field.
> > > > > +
> > > > > +               Each line in a trajectory, or forensics, file will
> > > > > +               always have the event{} and COE{} fields.  The event
> > > > > +               field describes the characteristics of a security
> > > > > +               event while the COE field describes the Context Of
> > > > > +               Execution that is executing the security event.
> > >
> > > > I think it would be good to provide a concrete definition of
> > > > CELL_DEFINITION field as other areas of the documentation make
> > > > reference to it within the tsem/trajectory file documentation.  We can
> > > > somewhat infer it's format, fields, etc. but it's much better to be
> > > > explicit about these things.
> > >
> > > Valid point, we will incorporate a broad definition of what the 'CELL'
> > > represents.
> > >
> > > Conceptually, it is equivalent to the 'object' in mandatory access
> > > controls.  In an events based architecture like TSEM, it is
> > > essentially the 'bucket' of values that describe the parameters of a
> > > security event that a COE/process is requesting permission for.
>
> > Yes, I understood conceptually what it represents and what data
> > might be present given a specific operation/rule, but it wasn't
> > clear to me how that data would be represented in the
> > CELL_DEFINITION.
>
> As a bit of further clarification, regarding the security model that
> TSEM is based on.
>
> A TMA extracts the event description parameters, now encoded in
> JSON.. :-), into a structure and then computes a digest value,
> referred to as the 'CELL identity value', over those elements, in
> whatever order the TMA elects to do so in.
>
> Further, a TMA implementation may elect to only include certain
> characteristics in the computation of the CELL identity, depending on
> the model being implemented.
>
> > > > > +               The event{} field consists of the following
> > > > > +               characteristic definitions:
> > >
> > > > I'm unclear as to the purpose of the event{} field as it is neither
> > > > part of the COE or the CELL, is it here simply to make the event
> > > > easier to read?  Or am I misunderstanding things and the event{}
> > > > field is part of the COE?
> > >
> > > It actually serves two roles, one of which, as you note, is to make
> > > the event description easier to read and understand.
> > >
> > > It probably comes as no surprise, but the trust orchestration system
> > > that this is all designed to support, has a security console that can
> > > be used to review the status of all the trust orchestrators that are
> > > supervising security workloads.  Either in the cloud, or perhaps, a
> > > large body of edge devices protecting critical infrastructure, if that
> > > doesn't give away too much.... :-)
> > >
> > > Having the process name and executable easily visualized is fairly
> > > useful.
> > >
> > > The second role is to allow the event description records to be
> > > self-describing.  The value for the type= key is used by the Trusted
> > > Modeling Agent (TMA) to determine what to look for in the remainder of
> > > the event description record in order to compute the CELL value.
> > >
> > > It also contains the TASK_ID value that ties the security state points
> > > to the integrity of the executable.  Since that value is a synthetic
> > > value it was deemed most appropriate to be placed in the event{}
> > > field.
>
> > I think it would be good to provide a more succinct version of the
> > above in the documentation.
>
> We will clarify that.
>
> > > > > +                       process=COMM
> > > > > +                               Where COMM is the ASCII representation
> > > > > +                               of the name of the process executing
> > > > > +                               the event.
> > > > > +
> > > > > +                       filename=PATH
> > > > > +                               If the CELL definition for an event
> > > > > +                               references a file the filename
> > > > > +                               characteristic contains a definition
> > > > > +                               of the path to the file.
> > > > > +
> > > > > +                               In the case where an event does not
> > > > > +                               have a file the PATH value is set to a
> > > > > +                               value of none.
> > >
> > > > What happens in cases where multiple file paths are present in an
> > > > event?  Also, given this is visible to userspace, and multiple
> > > > things can affect the path to a file (e.g. namespaces), how is the
> > > > file path determined?
> > >
> > > Unless we have missed something, which is no doubt possible, all of
> > > the security event hooks that we have implemented, which number about
> > > 87 now, that act on a 'file', receive only a single 'struct file *'
> > > pointer as a parameter to the event.
> > >
> > > So we haven't encountered a situation where there would be multiple
> > > files for a single event description.
>
> > I haven't seriously looked at the TSEM sources yet, I'm trying to
> > make sure that I first understand the security model while also
> > ensuring that it is well documented and reasonable.  While I can't
> > speak to what LSM hooks TSEM implements, it seems like there are at
> > least a few operations, rename and link come immediately to mind,
> > which would have multiple filenames as part of the operation.  How
> > are those operations handled in TSEM, or are they outside the scope
> > of TSEM?
>
> We are currently handling them as generically modeled events so the
> current model treats them as whether or not they occurred.
>
> When they get promoted to explicitly modeled events, the current
> presumption would be to include the involved filenames in the
> description of the event.

Hmmm.

With the understanding that I didn't go re-read the docs just now, my
gut feeling is that omitting/downgrading events like rename/link/etc.
from the modeling is a pretty significant shortcoming given the
importance of filenames as an identifier in the TSEM events.  The fact
that you chose to say "When they get promoted ..." as opposed to "If
they get promited ..." appears to add some credibility to that
thought.

However, I will be honest and say that I'm not sure I recall the
difference between "generically modeled" and "explicitly modeled"
events in the context of TSEM.  Perhaps that would make this clear,
maybe it wouldn't.

Regardless, can you help me understand why this isn't a concern for
this initial effort and why you've decided to add this later?

> > > > > +                       euid=NN
> > > > > +                               The ASCII base 10 representation of
> > > > > +                               the numeric value of the effective
> > > > > +                               discretionary user id of the process
> > > > > +                               that is executing the security event.
> > > > > +
> > > > > +                       euid=NN
> > > > > +                               The ASCII base 10 representation of
> > > > > +                               the numeric value of the effective
> > > > > +                               discretionary user id of the process
> > > > > +                               that is executing the security event.
> > > > > +
> > > > > +                       suid=NN
> > > > > +                               The ASCII base 10 representation of
> > > > > +                               the numeric value of the saved user id
> > > > > +                               of the process that is executing the
> > > > > +                               security event.
> > > > > +
> > > > > +                       gid=NN
> > > > > +                               The ASCII base 10 representation of
> > > > > +                               the numeric value of the discretionary
> > > > > +                               group id of the process that is
> > > > > +                               executing the security event.
> > > > > +
> > > > > +                       egid=NN
> > > > > +                               The ASCII base 10 representation of
> > > > > +                               the numeric value of the discretionary
> > > > > +                               effective group id of the process that
> > > > > +                               is executing the security event.
> > > > > +
> > > > > +                       egid=NN
> > > > > +                               The ASCII base 10 representation of
> > > > > +                               the numeric value of the discretionary
> > > > > +                               effective group id of the process that
> > > > > +                               is executing the security event.
> > > > > +
> > > > > +                       sgid=NN
> > > > > +                               The base 10 ASCII representation of
> > > > > +                               the numeric value of the saved
> > > > > +                               discretionary group id of the process
> > > > > +                               that is executing the security event.
> > > > > +
> > > > > +                       fsuid=NN
> > > > > +                               The base 10 ASCII representation of
> > > > > +                               the numeric value of the discretionary
> > > > > +                               filesystem user id of the process that
> > > > > +                               is executing the security event.
> > > > > +
> > > > > +                       fsgid=NN
> > > > > +                               The ASCII base 10 representation of
> > > > > +                               the numeric value of the discretionary
> > > > > +                               filesystem group id of the process
> > > > > +                               that is executing the security event.
> > > > > +
> > > > > +                       cap=0xNNN
> > > > > +                               The ASCII base 16 representation of
> > > > > +                               the numeric value of effective
> > > > > +                               capabilities of the process that is
> > > > > +                               executing the security event.
> > > > > +
> > > > > +               If the CELL value for a security event includes the
> > > > > +               definition of a file a file{} event field will be
> > > > > +               included.  The following characteristics will be
> > > > > +               encoded in this field:
> > > > > +
> > > > > +                       flags=NN
> > > > > +                               The ASCII base 10 representation of
> > > > > +                               the flags value of the 'struct file'
> > > > > +                               structure that is the source of the
> > > > > +                               file description.
> > > > > +
> > > > > +                       uid=NN
> > > > > +                               The ASCII base 10 representation of
> > > > > +                               the discretionary user id of the file.
> > > > > +
> > > > > +                       gid=NN
> > > > > +                               The base 10 ASCII representation of
> > > > > +                               the discretionary group id of the
> > > > > +                               file.
> > >
> > > > Similar to the task UID/GID mapping questions above, there are
> > > > mechanisms which map the file user/group IDs, which will be used in
> > > > the CELL definition and how will that be resolved between the kernel
> > > > and an external modeler?
> > >
> > > The answer is the same as with the COE, see the following function:
> > >
> > > security/tsem/event.c:get_file_cell()
> > >
> > > Once again, the TMA only operates on the event description presented
> > > to it and is not influenced by its own namespace.
>
> > For this particular point, my concern isn't what policy the TMA
> > implements, or what it uses as input, it's about understanding how
> > this event information is collected.  For fields which can be
> > namespaced (I'm referring to "normal" Linux Kernel namespaces and
> > not any TSEM namespaces), the TSEM documentation should make it
> > clear which namespace is used as a basis for the value.
>
> FWIW, based on feedback we have received, there may be a modeling
> domain/namspace setup option forthcoming that allows a trust
> orchestrator to request that the uid/gid et.al characteristics be
> exported in the context of the current user namespace.

Please make sure you are explicit in which "current user namespace":
the namespace which generated the event, or the namespace in which the
modeling agent is running.  You should also provide some guidance on
how to handle issues that might arise when the two namespaces
(generating namespace, modeler namespace) are different.  If you don't
plan to allow the modeling agent to run in a separate namespace from
the generating event stream please explain how that requirement will
be enforced by the kernel.

> > > > > +What:          /sys/fs/tsem/ExternalTMA
> > > > > +Date:          November 2022
> > > > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > > > +Description:
> > > > > +               The ExternalTMA directory is a container directory
> > > > > +               that hold files that will be used to export the
> > > > > +               security events, and their associated parameters, for
> > > > > +               externally modeled security domains/namespaces.
> > > > > +
> > > > > +               The files created in this directory will be named by
> > > > > +               the base 10 ASCII representation of the id value
> > > > > +               assigned to the modeling domain/namespace.  See the
> > > > > +               documentation for the /sys/fs/tsem/id file in this
> > > > > +               documentation for more details on this value.
> > > > > +
> > > > > +               This file will is a read-only file that can be polled
> > > > > +               by a userspace trust orchestration implementation to
> > > > > +               process security events that are to be modeled by
> > > > > +               an external Trusted Modeling Agent.
> > > > > +
> > > > > +               The type of the exported event is the first keyword of
> > > > > +               the line that is output and have the following
> > > > > +               values and arguments:
> > > > > +
> > > > > +               aggregate HEXID:
> > > > > +                       Where HEXID is the ASCII base 16
> > > > > +                       representation of the 256 bit hardware
> > > > > +                       platform aggregate value.
> > > > > +
> > > > > +               export pid{NNN} COE{} CELL_DEFINITION
> > > > > +                       Where the NNN in the pid field is the ASCII
> > > > > +                       base 10 value of the id of the process that is
> > > > > +                       executing the security event that will be
> > > > > +                       modeled.
> > >
> > > > I worry whenever I see a PID used as an identifier shared across the
> > > > kernel/userspace boundary as it is inherently racy.  Given the
> > > > somewhat coarse COE definition where one can expect multiple
> > > > processes/PIDs to share the same COE value, and the ability of
> > > > untrusted users/processes to manipulate the PID table, what do you
> > > > expect to use the pid{NNN} field for in this event?
> > > >
> > > > Similar to the other namespace/mapping issues discussed previously,
> > > > there is also the PID namespace issue to worry about.  How is that
> > > > handled here?
> > >
> > > The concern over the PID issue is understandable, I will treat the
> > > reasoning behind its use below.
> > >
> > > The PID value is the 'native' value managed by the kernel, not a
> > > mapped value.
>
> > Regardless of if the PID is rooted in the initial namespace or a
> > different PID namespace, the issue of PIDs being inherently racy is
> > a real problem.  Can you help me understand how TSEM avoids the
> > common pitfalls associated with using PIDs to identify processes on
> > the system?
>
> The second version of the TSEM series, now includes support for a
> requirement that a process being externally modeled, authenticate
> itself to the TMA in order for the trust control call to act on
> the process.

Please bear with me, I want to make sure I'm clear on this point.  In
order for a process to be modeled by an external modeling-agent/TMA it
would need to first authenticate with the TMA (using a TBD mechanism);
is that correct?  I guess we will need to see how the authentication
works, but is there a mechanism in place to ensure that a malicious
process could not pass an authentication token to another (PID
recycled) process?

Do you plan to support unauthenticated external modeling?  If so, how
do you plan to address PID recycling?

> > > > > +What:          /sys/fs/tsem/control
> > > > > +Date:          November 2022
> > > > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > > > +Description:
> > > > > +               The control file is the only writable file in the
> > > > > +               filesystem and is used by the trust orchestrators to
> > > > > +               configure and control the behavior of the TSEM
> > > > > +               implementation.
> > > > > +
> > > > > +               The following keyword and arguments are recognized:
> > > > > +
> > > > > +               internal:
> > > > > +                       The internal keyword causes an internally
> > > > > +                       modeled domain to be created for the calling
> > > > > +                       process.
> > > > > +
> > > > > +               external:
> > > > > +                       The external keyword causes an externally
> > > > > +                       modeled domain to be created for the calling
> > > > > +                       process.
> > > > > +
> > > > > +               enforce:
> > > > > +                       The enforce keyword causes the modeling
> > > > > +                       domain/namespace of the process to enter
> > > > > +                       enforcing mode.  In this mode a value of
> > > > > +                       -EPERM will be returned for a security event
> > > > > +                       that does not map into the current set of
> > > > > +                       allowed state points for the security model
> > > > > +                       being implemented for the domain/namespace.
> > > > > +
> > > > > +               seal:
> > > > > +                       The seal keyword causes the security model
> > > > > +                       being implemented for the model to be placed
> > > > > +                       in sealed state.  In this state the current
> > > > > +                       set of security event points is considered to
> > > > > +                       be the only set of valid points for the
> > > > > +                       domain/model.  Any subsequent events that map
> > > > > +                       to a point not in the current model will be
> > > > > +                       considered a violation of the model.
> > > > > +
> > > > > +               trusted PID:
> > > > > +                       The trusted keyword is used by a trust
> > > > > +                       orchestrator to indicate that the process
> > > > > +                       identified by the PID argument should be
> > > > > +                       allowed to run in trusted status.
> > > > > +
> > > > > +               untrusted PID:
> > > > > +                       The untrusted keyword is used by a trust
> > > > > +                       orchestrator to indicate that the process
> > > > > +                       identified by the PID argument should be
> > > > > +                       allowed to run but designated as an untrusted
> > > > > +                       process.
> > >
> > > > The 'trusted PID:' and 'untrusted PID:' commands are concerning for
> > > > the reasons described above about PIDs being racy and generally an
> > > > unreliable way of identifying processes across the kernel/userspace
> > > > boundary.  I suspect it would not be too difficult for a malicious
> > > > user to trick an external modeler into marking the wrong process as
> > > > trusted/untrusted.
> > >
> > > An external TMA needs the PID value to determine which process to wake
> > > up and set the trust status value on in the task control structure,
> > > after the event is modeled.  As was noted above, the PID value is the
> > > unmapped value maintained by the OS.
> > >
> > > Lets see if we can reason through why the PID can be used safely.
> > >
> > > CAP_TRUST, or whatever ends up getting used, is required by the trust
> > > orchestrator to create a security/modeling namespace for the workload
> > > being modeled.  This results in the creation of the following
> > > pseudo-file for surfacing the security event descriptions for the
> > > namespace/workload:
> > >
> > > /sys/fs/tsem/ExternalTMA/N
> > >
> > > Where N is the id number of the modeling domain.
> > >
> > > CAP_TRUST, caveats applied, is required to open the pseudo-file.  The
> > > trust orchestrator only receives and acts on PID values through this
> > > conduit from the kernel.
> > >
> > > When an event description is exported, the trust status of the task is
> > > set to 'pending' and the process is placed in interruptible sleep and
> > > scheduled away, with the 'wakeup' criteria being the trust status
> > > being changed from pending to either trusted or untrusted.
> > >
> > > The only path to change the trust status value in the LSM task control
> > > structure and wake up the process is by the trust orchestrator that
> > > created the namespace, by writing the appropriate value to the
> > > /sys/fs/tsem/control file.  Access to that file is gated by CAP_TRUST
> > > or its equivalent.
> > >
> > > See the following code locations for further details:
> > >
> > > security/tsem/export.c:tsem_export_event()
> > >
> > > security/tsem/fs.c:control_COE()
> > >
> > > As long as the process 'exists', albeit sleeping, the PID slot is
> > > occupied and an adversary, regardless of namespace, cannot substitute
> > > a task with the same PID value.
> > >
> > > This leaves an adversary with the need to terminate the task being
> > > modeled in order to capture its PID slot.
> > >
> > > Precautions are implemented in the following function to protect the
> > > process from being terminated by an adversary:
> > >
> > > security/tsem/tsem.c:tsem_task_kill()
>
> > What about the OOM killer?
> >
> > The security_task_kill() LSM hook only offers an access control point
> > for one process sending another process a signal, it doesn't gate a
> > process being killed for other reasons.  The OOM killer is the first
> > thing that comes to mind, but I'm reasonably certain there are other
> > similar scenarios.
>
> As noted above, as an additional protection, the next version of the
> series requires that a process authenticate itself as being a member
> of the modeling domain in order for the trust status control call to
> succeed.
>
> With this implementation, substituting an alternate process would now
> require that an adversary break the security context between the TMA
> and process in the modeling domain.

I'll look forward to seeing the new authentication mechanism.  Please
ensure it is properly documented.

> > > > > +Process and Platform Trust Status
> > > > > +=================================
> > > > > +
> > > > > +A fundamental concept in TSEM is the notion of providing a precise
> > > > > +definition for what it means for a platform or workload to be trusted.
> > > > > +A trusted platform or workload is one where there has not been an
> > > > > +attempt by a process to execute a security relevant event that does
> > > > > +not map into a known security state point.
> > > > > +
> > > > > +The process trust status is a characteristic of the process that is
> > > > > +passed to any subordinate processes that are descendants of that
> > > > > +process.  Once a process is tagged as untrusted, that characteristic
> > > > > +cannot be removed from the process.  In a 'fruit from the poisoned
> > > > > +vine' paradigm, all subordinate processes created by an untrusted
> > > > > +process are untrusted as well.
> > > > > +
> > > > > +On entry into each TSEM security event handler, the trust status of a
> > > > > +process is checked before an attempt to model the event is made.  An
> > > > > +attempt to execute a security event by an untrusted process will cause
> > > > > +the event, and its characteristics, to be logged.  The return status
> > > > > +of the hook will be determined by the enforcement state of the model.
> > > > > +A permission denial is only returned if the TMA is running in
> > > > > +enforcing mode.
> > > > > +
> > > > > +If the platform running the TSEM LSM has a TPM, the hardware aggregate
> > > > > +value is computed at the time that TSEM is initialized.  This hardware
> > > > > +aggregate value is the linear extension sum over Platform
> > > > > +Configuration Registers (PCR's) 0 through 7.  This is the same
> > > > > +aggregate value that is computed by the Integrity Measurement
> > > > > +Architecture (IMA) and is the industry standard method of providing an
> > > > > +evaluation measurement of the hardware platform state.
> > > > > +
> > > > > +Internally model domains have the hardware aggregate measurement
> > > > > +included as the first state point in the security model.  Externally
> > > > > +modeled domains export the hardware aggregate value to the TMA for
> > > > > +inclusion as the first state point of the model maintained by the TMA.
> > > > > +
> > > > > +The root modeling domain extends each security state point into PCR
> > > > > +11.  This allows hardware based TSEM measurements to coexist with IMA
> > > > > +measurement values.  This hardware measurement value can be used to
> > > > > +attest to the security execution trajectory that the root model
> > > > > +maintains.
> > >
> > > > It seems like making the target PCR configurable would be a good
> > > > idea, at the very least make it a Kconfig option.
> > >
> > > That was something that we have thought about, it probably needs a
> > > Kconfig option.
> > >
> > > Contrary to all appearances, as a team we are really minimalists at
> > > heart and tend to not make things more complex or configurable than
> > > needed.... :-)
> > >
> > > > Also, can you elaborate on how the security state points are
> > > > extended into the PCR?  I imagine for it to be useful at an
> > > > arbitrary point in time this would require the PCR to be extended as
> > > > the security points were generated, which would imply that the PCR
> > > > value would be dependent on execution order, and in most cases,
> > > > scheduling order as well.  How useful do you expect this to be for
> > > > most users?
> > >
> > > Your assessment is correct, the state points are extended into the PCR
> > > whenever a unique security state point is generated.
> > >
> > > In a 'free-running' model, the value in the register will be fungible
> > > due to scheduling dependencies.
>
> > In other words, garbage ;)
>
> We don't disagree on the utility of a scheduling fungible measurement
> value.  However, this is an remarkably interesting
> conclusion/statement, by the Linux security sub-system maintainer no
> less, given that it describes the current state of the art with
> respect to hardware security co-processors and trusted system
> technology.. :-)

I've yet to meet a kernel maintainer that doesn't hold amusing
opinions on at least one issue; one could almost make an argument that
it is a prerequisite for the role.  However, I feel that using
non-deterministic values as a measure of system state/attestation is
well understood to be garbage and isn't quite as interesting as you
would make it.

Based on the rest of the TSEM docs and this discussion, I'm guessing
you are referencing IMA's measurements into PCR 10, or something
similar, when you talk about the current state of the art, is that
correct?  In the case of IMA, the important thing to remember is that
PCR 10 can be reliably attested using the IMA measurement log; the IMA
project even provides tools and documentation demonstrating how to do
so.  Does TSEM offer a similar measurement log?  My apologies if I
missed it.

> > > If the model is pre-defined, the security state points will be
> > > extended into the register as they are loaded through the
> > > /sys/fs/tsem/map pseudo-file interface.  In this case, the value will
> > > be fixed and any departure from the value would signal that the
> > > modeling domain has departed from its specification.
> > >
> > > With respect to the utility of the value, in a 'free-running' model it
> > > is about as useful as the value that IMA maintains in PCR 10, which in
> > > our opinion is not very useful and is why we implemented the notion of
> > > the 'state' value of a model.
>
> > For a variety of reasons, and mostly to help keep things civil,
> > let's refrain from comparing one LSM to another.  Each LSM makes its
> > own choices, and needs to stand on its own; just because LSM did X
> > doesn't mean TSEM can do X if it is silly in the context of TSEM.
>
> Our intent was not to be incivil, but rather to call out one of the
> motivations in the implementation of TSEM, and in a larger context,
> the notion of a TMA based security architecture.
>
> A now prehistoric version of TSEM was implemented as a patch on top of
> IMA.  We actually built systems for clients on top of that
> architecture.  Our concept of a 'state' value was driven by the
> difficulties we experienced in implementing, and maintaining, these
> systems in a field environment.
>
> We offer the concept of a 'state' value in order to simplify the
> attestation model, which classically, has required that a verifying
> party review an event log for its validity, after verifying that the
> measurement value confirms the integrity of the log.

Having a log ordered by the sequence of events can be important.
After all, if a security critical configuration knob is toggled
multiple times, and the event ordering is not preserved, how does one
know the current state of the system?  I might be able to see that the
knob was turned both on and off, but without knowing which occurred
last, how do I know if the system is in a known good state?

> > > > > +Internal vs external modeling
> > > > > +-----------------------------
> > > > > +
> > > > > +When a TSEM modeling domain is created, a designation is made as to
> > > > > +whether the domain is to be internally or externally modeled.
> > > > > +
> > > > > +In an internally modeled domain, the security event handlers pass the
> > > > > +event type and its characteristics to the designated internal trusted
> > > > > +modeling agent.  The agent provides the permission value for the
> > > > > +security event handler to return as the result of the event and sets
> > > > > +the trust status of the process executing the event.
> > > > > +
> > > > > +In an externally modeled domain, the event type and parameters are
> > > > > +exported to userspace for processing by a trust orchestrator with an
> > > > > +associated TMA.  The trust orchestrator communicates the result of the
> > > > > +modeling back to the kernel to support the setting of the process
> > > > > +trust status.
> > > > > +
> > > > > +This model poses a limitation to the ability of TSEM to model some
> > > > > +security events.  This is secondary to the fact that some event
> > > > > +handlers (LSM hooks) are called from a non-sleeping context, as a
> > > > > +result the process cannot be scheduled.  This is particularly the case
> > > > > +with the task based hooks, since they are typically called with the
> > > > > +tasklist lock held.
> > > > > +
> > > > > +This limitation is also inherent to the root model that extends the
> > > > > +security state points into TPM PCR 11, secondary to the fact that the
> > > > > +process invoking the security event hook will be scheduled away while
> > > > > +the TPM transaction completes.
> > > > > +
> > > > > +Addressing this problem directly requires a consideration of the
> > > > > +context from which the security event handlers are being called.
> > > > > +Subsequent implementations of TSEM will include a mechanism for
> > > > > +asynchronous deferral of model processing, until when and if, a review
> > > > > +of the call context would be considered worthwhile by the LSM
> > > > > +community.
> > >
> > > > This is a pretty big limitation, and in conjunction with the some of
> > > > the other issues brought up earlier (the PID issue seems the most
> > > > concerning), I'm having a difficult time believeing that an external
> > > > modeler could operate safely given the design presented here.
> > >
> > > With respect to the PID issue, we would welcome any comments on the
> > > analysis that we provided above as to its design safety.
> >
> > >From what I can tell from the documentation and our discussion thus
> > far is that TSEM relies on a security_task_kill() hook implementation
> > to ensure that a process is not killed, and the PID released, without
> > explicit TSEM approval.  Unfortunately, I believe that relying solely
> > on security_task_kill() will not fully cover all of the cases where a
> > process can be killed, mostly because security_task_kill() does not
> > control process destruction, it controls the ability of one process to
> > signal another.
>
> > You might be able to do something with security_task_free(), but I
> > haven't given that much thought.
>
> Our analysis suggested that an authentication strategy was the
> strongest and most complete implementation moving forward.

I'll look for that in the next revision.

> > > If the PID issue remains a concern, we have an extension to the export
> > > descriptions that would include a random nonce that would be emitted
> > > with the PID.  The nonce would be placed in the LSM task control
> > > 'blob' for the sleeping task and used to confirm that the task release
> > > directive was acting on the correct process.
>
> > That should help, but ultimately a nonce is still a bounded resource
> > and subject to recycling just like the PID.  I'm open to hearing
> > other ways in which you believe you can resolve this issue, but I
> > remain skeptical.
>
> FWIW, I believe that current thinking is that a nonce based on a
> 64-bit value is immune from recycling.  The classic metric for a
> 64-bit counter is that a consumption rate of 1000 values/second yields
> a counter cycle time of 584,942,417 years.  Nanosecond rates still
> buys you 584 years.
>
> I believe that Jason built the Wireguard protocol on this predicate.

Once again, just because project X did something doesn't mean it is
acceptable here.

> We believe the second series will fully address this issue, without
> using nonces, for whatever that is worth.  We can reserve further
> discussion once that code is available and submitted for review.

I mentioned this above, but please ensure the authentication approach
is well documented.

> > > > Frankly, I also wonder how a system would perform with an external
> > > > modeler, indepdent of the issues with non-blocking hooks.  How does
> > > > the system perform with every blockable LSM hook invocation
> > > > potentially blocking on a response from userspace?  Or with the COE
> > > > being somewhat coarse, does the trajectory/policy populate itself
> > > > quickly?
> > >
> > > One obviously experiences a latency hit in going to userspace, by
> > > definition, implementing security always has an associated resource
> > > cost.  So, once again, this comes down to a cost/benefit analysis.
> > >
> > > As a Gedanken exercise, consider the value proposition of a Linux
> > > based RTU, or other device, controlling infrastructure that can only
> > > execute security relevant events that are guaranteed to be known good
> > > by an external co-processor that is only accessible as a security
> > > oracle.
> > >
> > > Given that frame of reference.
> > >
> > > Time for a userspace or SGX based TMA transaction is running around
> > > 890 micro-seconds.
> > >
> > > Going to a TMA based in a Xen stubdomain implementation runs a bit
> > > longer, probably around 940 micro-seconds or so.
> > >
> > > The micro-controller implementations are decidedly slower, with the
> > > NRF52840-DONGLE clocking in at around 40 micro-seconds, but that is
> > > strictly a CPU horsepower issue.
> > >
> > > All of this with the caveat that we have been focusing almost
> > > exclusively on correctness and not optimizing performance.
> > >
> > > We've thought a bit, mainly on long walks with our Golden Retriever
> > > Izzy, about the issue of building a kernel based policy cache with
> > > externally modeled domains.  Given that the kernel does not, a-priori,
> > > know what modeling algorithm a TMA might be using, we would need to
> > > come up with a method of deterministically mapping a security event
> > > description to a known good state point value.
> > >
> > > The other issue with all this is that with containerized workloads,
> > > particularly micro-services, the rate of security event generation can
> > > be surprisingly low.  Obviously this is also the case with embedded
> > > implementations.
> > >
> > > Once again, what are you willing to pay to be safe?
>
> > For better or worse, when code is proposed for the upstream Linux
> > Kernel it is subject to scrutiny from all manner of developers and
> > users, with most being focused on their own pet projects/subsystems,
> > not whatever new security promises you are providing.
> >
> > There have been patch(sets) and discussions relating to performance
> > gains/losses on the other of tens of nanoseconds per operation.
> >
> > I think most of us in the security community are sympathetic to the
> > question of "what are you willing to pay to be safe", but please
> > understand that while we are understanding, there are others who will
> > disagree not only with the performance cost tradeoff, but the very
> > idea of safety you are promising.  My only suggestion is to be
> > prepared, and be honest with the performance assessments of TSEM.
>
> We seem to be in agreement that there will always be a natural tension
> between security and performance.  With TSEM our goal is to offer
> choices.
>
> If an environment is sensitive to performance defects on the order of
> tens of nanoseconds, it would seem unlikely that the architects or
> administrators of such systems would be implementing integrity
> controls of any kind.  In that context, we are no different than IMA
> or IPE, it would seem highly unlikely that such environments are going
> to tolerate a security solution involving a cryptographic checksum of
> any type.

Performance comparisons are always going to be relative.  In the
tens-of-nanoseconds example that I'm thinking of, it wasn't about
disabling security functionality, it was about optimizing the security
functionality.

> > > > > +Event handlers that cannot be directly modeled, still consider, on
> > > > > +entry, whether or not they are being called by an trusted or untrusted
> > > > > +process.  As a result, an untrusted process will cause a non-modeled
> > > > > +event to return a permissions violation in enforcing mode, even if the
> > > > > +security event cannot be directly modeled.
> > > > > +
> > > > > +Security event modeling typically traps violations of trust by a COE
> > > > > +with unmodeled characteristics that is attempting to access/execute a
> > > > > +file or map memory as executable; or by a COE with known
> > > > > +characteristics attempting to access or execute a CELL not prescribed
> > > > > +by a model.  As a result, the impact of the ability to not directly
> > > > > +model these events is lessened.
> > > >
> > > > ...
> > > >
> > > > > +Event modeling
> > > > > +--------------
> > > > > +
> > > > > +TSEM security event modeling is based on the following functional
> > > > > +definition for a security state point:
> > > > > +
> > > > > +Sp = SHA256(SHA256(EVENT_ID) || TASK_ID || SHA256(COE) || SHA256(CELL))
> > >
> > > > It appears that all of the hasing in TSEM is SHA256 based, you might
> > > > want to consider making that a Kconfig option at the very least.
> > >
> > > That has been something that we have talked about as well.
> > >
> > > As I indicated previously, we really are minimalists, particularly
> > > after watching IMA fight with issues surrounding algorithmic agility.
> > >
> > > It would be easy enough to make this configurable but does anyone see
> > > SHA256 as not being useful in in this role anywhere in the next 10
> > > years?
>
> > There are any number of reasons why one might need to select a
> > different hash algorithm: legal constraints, security
> > certifications, corporate policy.  I would strongly suggest making
> > this configurable.
>
> Certainly sound and well reasoned advice, but the question then becomes
> what hashes and what hash lengths, do you have any specific
> recommendations?

My recommendation is to make it configurable such that as algorithms
are added, or removed, from the the kernel crypto code, they can be
added to TSEM without much more than some Kconfig changes.

> IMA currently has the options of SHA1, SHA256, SHA512, WHIRLPOOL512
> and SM3; is this sufficient coverage, given that SHA1 in a new
> implementation like TSEM probably doesn't make any sense?

I can't honestly pretend to understand all of the different
requirements which would dictate a user's choice of a hash algorithm.
About the only thing I can say is that given a choice of stronger
options, I wouldn't use SHA1 in a security context on any of the
systems I maintain.

> Our current inclination, for the initial release, in an embrace of
> minimalisim, would be to make this a selectable option when a modeling
> domain is setup, with the only selectable option being SHA256.  This
> would place the onus on userspace to make the decision and doesn't
> lock the kernel to an ABI.

So long as it is configurable, and the API is designed to support
different algorithms, it may be acceptable to only implement one
algorithm in the initial implementation.  However, one of the easiest
ways to ensure the specification and the implementation work correctly
would be to support at least two algorithms in the initial
implementation so that this ability can be tested.

-- 
paul-moore.com

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 02/14] Add TSEM specific documentation.
  2023-03-22 23:45           ` Paul Moore
@ 2023-03-30  3:34             ` Dr. Greg
  2023-04-05 20:45               ` Paul Moore
  0 siblings, 1 reply; 42+ messages in thread
From: Dr. Greg @ 2023-03-30  3:34 UTC (permalink / raw)
  To: Paul Moore; +Cc: linux-security-module

On Wed, Mar 22, 2023 at 07:45:26PM -0400, Paul Moore wrote:

Hi, I hope the week is going well for everyone.

> On Mon, Mar 13, 2023 at 6:52???PM Dr. Greg <greg@enjellic.com> wrote:
> > On Thu, Mar 02, 2023 at 11:15:56PM -0500, Paul Moore wrote:
> >
> > Hi Paul, thanks for sending along further comments.
> >
> > You note below that you haven't had time to look at the code since you
> > wanted to confirm the TSEM security model before moving forward.
> >
> > From a development perspective we are now three weeks into what will
> > become version 2 of the patch series.  So at this point I wouldn't
> > advocate spending a lot of time on the current patchset.
> >
> > That being said, if you some have time, we would appreciate a quick
> > look at the code on your part, with respect to style changes and the
> > like we can enforce in the second series, ie. ordering of local
> > variable declarations by length and the like.

> To be perfectly honest I'm still very concerned about some of the
> issues that I've seen in the docs, until that is sorted out I'm not
> sure there is much point in looking at the code.

I think those concerns can be resolved, see below for more
information, the second patch series that we are closing in on should
help address the concerns that are currently on the table.

That being said, since TSEM is a new codebase, we were hoping that you
could give us some guidance on function local variable ordering.
Reverse Christmas tree seems popular writ large in the kernel, I
believe that you commented in a posting a month or two ago that you
prefer standard Christmas tree, SMACK and SeLinux don't seem to
religiously embrace a style.

Our codebase uses ordering based on least complex to most complex
variables and has worked for us, both in the kernel and elsewhere, but
we are ambivalent, as our primary objective is to avoid wasting
everyone's time on issues such as this.

So we would look forward to a recommendation, given that it shouldn't
involve wasting any time looking at code.

> > > On Tue, Feb 14, 2023 at 6:58???AM Dr. Greg <greg@enjellic.com> wrote:
> > > > On Sun, Feb 12, 2023 at 11:33:26PM -0500, Paul Moore wrote:
> > > > > On Sat, Feb 4, 2023 at 12:33 AM Dr. Greg <greg@enjellic.com> wrote:
> > > > > >
> > > > > > An entry was added to the ABI testing documentation to document
> > > > > > the files in the TSEM management filesystem.
> > > > > >
> > > > > > The file documenting the kernel command-line parameters was
> > > > > > updated to document the tsem_mode command-line parameter.
> > > > > >
> > > > > > The primary TSEM documentation file was added to the LSM
> > > > > > administration guide and the file was linked to the index of LSM
> > > > > > documentation.
> > > > > >
> > > > > > Signed-off-by: Greg Wettstein <greg@enjellic.com>
> > > > > > ---
> > > > > >  Documentation/ABI/testing/tsemfs              |  576 ++++++++
> > > > > >  Documentation/admin-guide/LSM/index.rst       |    1 +
> > > > > >  Documentation/admin-guide/LSM/tsem.rst        | 1240 +++++++++++++++++
> > > > > >  .../admin-guide/kernel-parameters.txt         |    5 +
> > > > > >  4 files changed, 1822 insertions(+)
> > > > > >  create mode 100644 Documentation/ABI/testing/tsemfs
> > > > > >  create mode 100644 Documentation/admin-guide/LSM/tsem.rst
> > > >
> > > > > One of the more important requirements for any new LSM is that it
> > > > > documents a clear, understandable, and reasonable security model along
> > > > > with an implementation that faithfully implements that model.  Before
> > > > > I looked at your code I wanted to try and understand the TSEM security
> > > > > model and a few things jumped out at me rather quickly, I imagine
> > > > > there would be others as I start to look a bit closer but I wanted to
> > > > > send these questions/comments along now to get your take on them ...
> > > >
> > > > Hi Paul, thanks for taking time to review the documentation and raise
> > > > questions, responses below.
> > > >
> > > > > > diff --git a/Documentation/ABI/testing/tsemfs b/Documentation/ABI/testing/tsemfs
> > > > > > new file mode 100644
> > > > > > index 000000000000..3d326934624c
> > > > > > --- /dev/null
> > > > > > +++ b/Documentation/ABI/testing/tsemfs
> > >
> > > ...
> > >
> > > > > > +What:          /sys/fs/tsem/measurement
> > > > > > +Date:          November 2022
> > > > > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > > > > +Description:
> > > > > > +               The measurement file contains the ASCII base 16
> > > > > > +               hexadecimal representation of the 256 bit measurement
> > > > > > +               value of the security model that the process is
> > > > > > +               operating in.
> > > > > > +
> > > > > > +               The measurement value is the classic linear extension
> > > > > > +               measurement of the model.  An updated measurement
> > > > > > +               value is created by extending the current measurement
> > > > > > +               value with the state coefficient computed for a
> > > > > > +               security event.
> > > > > > +
> > > > > > +               This measurement value represents a time dependent
> > > > > > +               measurement of a model and is susceptible to
> > > > > > +               deviations caused by scheduling differences between
> > > > > > +               subsequent invocations of a workload.
> > > >
> > > > > Given the very volatile nature of this value, what is it used for in
> > > > > userspace?  My apologies if I missed it in the docs.
> > > >
> > > > It serves the same role as PCR register 10 in IMA, or any other
> > > > register in a TPM based architecture using a classic linear extension
> > > > mechanism strategy, it can be used to validate a list of time or
> > > > sequence ordered measurement values.
> > > >
> > > > Our personal prejudice is that these types of measurements are of
> > > > limited value, which is why we introduce in TSEM, the notion of the
> > > > 'state' value for a model, discussed below.
> > > >
> > > > I would have to go looking on lore for a reference to the exact thread
> > > > but Roberto Sassu had offered up a patch set for IMA that addressed
> > > > the deficiency of these types of measurements.
> >
> > > If we all agree that this measurement isn't very useful, and you
> > > have implemented an alternative which is intended to address these
> > > usability shortcomings, why bother including this measurement in
> > > TSEM?
> >
> > To provide comparable functionality to TPM based security
> > architectures, that are currently, considered state of the art for the
> > security industry.
> >
> > As our documentation calls out, TSEM's concept of Trusted Modeling
> > Agent's (TMA's), are being proposed to both explore and implement next
> > generation hardware assisted security technologies.
> >
> > Currently, the only measurements that TPM based systems support are
> > classic linear extension summing, which I believe we all consider to
> > be problematic.
> >
> > That being said, the 'measurement' value can be used to validate the
> > order of the security event execution trajectory.  In that role it
> > provides the same value that PCR register 10 plays for IMA.
> >
> > We believe there is a legitimate discussion that can occur, as to
> > whether or not this classic attestation architecture is relevant, but
> > it seemed appropriate to support it.
> 
> It is relatively easy to add user visible features to the kernel, but
> it's almost impossible to remove them.  If you see little value in
> feature X, to the point that you've developed an alternate mechanism
> to avoid the shortcomings which limit the usefulness of X, why include
> it?  If you later realize that it is important you can always add it.
> 
> Add new functionality to the kernel because it meets a user need, not
> simply because "everybody else is doing it".  If you've got a defined
> use case for this, keep it; however, if you can't define a reasonable
> use case I would suggest dropping it and making your life easier.

The discussion on this has caused us to implement changes, that will
be in V2, that should better justify the measurement value, but see
below.

> > > It's relatively easy to add features to the Linux Kernel as time
> > > goes on, it is *very* difficult to remove them.  For this initial
> > > submission I would encourage you to implement the bare minimum
> > > functionality you need to do something useful and meet your goals.
> >
> > We can certainly pull the export of the measurement value.  In that
> > case, would you recommend that we also pull the code that extends the
> > security coefficients from the root modeling domain, if a TPM is
> > available, into PCR register 11?
> 
> Once again, if you've got a use case, keep it; if not, drop it.  Don't
> add to the kernel API without a use case.
> 
> > > > > > +What:          /sys/fs/tsem/trajectory
> > > > > > +Date:          November 2022
> > > > > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > > > > +Description:
> > > > > > +               The trajectory file contains a description of the
> > > > > > +               security events that have occurred in a security
> > > > > > +               domain/model.
> > > > > > +
> > > > > > +               Each entry in this file represents a single security
> > > > > > +               event and consists of brace {} delimited fields that
> > > > > > +               describe the characteristics of a security event.
> > > > > > +               Each field has key=value pairs that define
> > > > > > +               characteristics of the field.
> > > > > > +
> > > > > > +               Each line in a trajectory, or forensics, file will
> > > > > > +               always have the event{} and COE{} fields.  The event
> > > > > > +               field describes the characteristics of a security
> > > > > > +               event while the COE field describes the Context Of
> > > > > > +               Execution that is executing the security event.
> > > >
> > > > > I think it would be good to provide a concrete definition of
> > > > > CELL_DEFINITION field as other areas of the documentation make
> > > > > reference to it within the tsem/trajectory file documentation.  We can
> > > > > somewhat infer it's format, fields, etc. but it's much better to be
> > > > > explicit about these things.
> > > >
> > > > Valid point, we will incorporate a broad definition of what the 'CELL'
> > > > represents.
> > > >
> > > > Conceptually, it is equivalent to the 'object' in mandatory access
> > > > controls.  In an events based architecture like TSEM, it is
> > > > essentially the 'bucket' of values that describe the parameters of a
> > > > security event that a COE/process is requesting permission for.
> >
> > > Yes, I understood conceptually what it represents and what data
> > > might be present given a specific operation/rule, but it wasn't
> > > clear to me how that data would be represented in the
> > > CELL_DEFINITION.
> >
> > As a bit of further clarification, regarding the security model that
> > TSEM is based on.
> >
> > A TMA extracts the event description parameters, now encoded in
> > JSON.. :-), into a structure and then computes a digest value,
> > referred to as the 'CELL identity value', over those elements, in
> > whatever order the TMA elects to do so in.
> >
> > Further, a TMA implementation may elect to only include certain
> > characteristics in the computation of the CELL identity, depending on
> > the model being implemented.
> >
> > > > > > +               The event{} field consists of the following
> > > > > > +               characteristic definitions:
> > > >
> > > > > I'm unclear as to the purpose of the event{} field as it is neither
> > > > > part of the COE or the CELL, is it here simply to make the event
> > > > > easier to read?  Or am I misunderstanding things and the event{}
> > > > > field is part of the COE?
> > > >
> > > > It actually serves two roles, one of which, as you note, is to make
> > > > the event description easier to read and understand.
> > > >
> > > > It probably comes as no surprise, but the trust orchestration system
> > > > that this is all designed to support, has a security console that can
> > > > be used to review the status of all the trust orchestrators that are
> > > > supervising security workloads.  Either in the cloud, or perhaps, a
> > > > large body of edge devices protecting critical infrastructure, if that
> > > > doesn't give away too much.... :-)
> > > >
> > > > Having the process name and executable easily visualized is fairly
> > > > useful.
> > > >
> > > > The second role is to allow the event description records to be
> > > > self-describing.  The value for the type= key is used by the Trusted
> > > > Modeling Agent (TMA) to determine what to look for in the remainder of
> > > > the event description record in order to compute the CELL value.
> > > >
> > > > It also contains the TASK_ID value that ties the security state points
> > > > to the integrity of the executable.  Since that value is a synthetic
> > > > value it was deemed most appropriate to be placed in the event{}
> > > > field.
> >
> > > I think it would be good to provide a more succinct version of the
> > > above in the documentation.
> >
> > We will clarify that.
> >
> > > > > > +                       process=COMM
> > > > > > +                               Where COMM is the ASCII representation
> > > > > > +                               of the name of the process executing
> > > > > > +                               the event.
> > > > > > +
> > > > > > +                       filename=PATH
> > > > > > +                               If the CELL definition for an event
> > > > > > +                               references a file the filename
> > > > > > +                               characteristic contains a definition
> > > > > > +                               of the path to the file.
> > > > > > +
> > > > > > +                               In the case where an event does not
> > > > > > +                               have a file the PATH value is set to a
> > > > > > +                               value of none.
> > > >
> > > > > What happens in cases where multiple file paths are present in an
> > > > > event?  Also, given this is visible to userspace, and multiple
> > > > > things can affect the path to a file (e.g. namespaces), how is the
> > > > > file path determined?
> > > >
> > > > Unless we have missed something, which is no doubt possible, all of
> > > > the security event hooks that we have implemented, which number about
> > > > 87 now, that act on a 'file', receive only a single 'struct file *'
> > > > pointer as a parameter to the event.
> > > >
> > > > So we haven't encountered a situation where there would be multiple
> > > > files for a single event description.
> >
> > > I haven't seriously looked at the TSEM sources yet, I'm trying to
> > > make sure that I first understand the security model while also
> > > ensuring that it is well documented and reasonable.  While I can't
> > > speak to what LSM hooks TSEM implements, it seems like there are at
> > > least a few operations, rename and link come immediately to mind,
> > > which would have multiple filenames as part of the operation.  How
> > > are those operations handled in TSEM, or are they outside the scope
> > > of TSEM?
> >
> > We are currently handling them as generically modeled events so the
> > current model treats them as whether or not they occurred.
> >
> > When they get promoted to explicitly modeled events, the current
> > presumption would be to include the involved filenames in the
> > description of the event.

> Hmmm.
> 
> With the understanding that I didn't go re-read the docs just now, my
> gut feeling is that omitting/downgrading events like rename/link/etc.
> from the modeling is a pretty significant shortcoming given the
> importance of filenames as an identifier in the TSEM events.  The fact
> that you chose to say "When they get promoted ..." as opposed to "If
> they get promited ..." appears to add some credibility to that
> thought.
>
> However, I will be honest and say that I'm not sure I recall the
> difference between "generically modeled" and "explicitly modeled"
> events in the context of TSEM.  Perhaps that would make this clear,
> maybe it wouldn't.
> 
> Regardless, can you help me understand why this isn't a concern for
> this initial effort and why you've decided to add this later?

Least complex answer; minimalism in the initial implementation, which
from your previous comments would seem to be a virtue.

Slightly more complex; the current models that we are training don't
benefit from numerical resolution beyond what is in the initial
implementation.

Some clarifications that may be useful:

Filenames are no more, or no less, important in TSEM than any of the
other parameters of the security event basis set.  The security
relevant entity is the coefficient that gets computed for the event.

As the 'Event modeling' section of the TSEM documentation points out,
the security coefficient is a functional product of the event, task,
COE and CELL identities.  Simplisticaly, a generically modeled event
operates under the presumption that the security model will only be
dependent on whether or not a particular portion of executable memory,
executed by a process with defined characteristics, is requesting
approval for a specific security event.

If the (EVENT:TASK:COE) tuple has not been shown to generate, for
example, a filename rename, the event will be denied.  If a rename is
allowed, and it results in a pathname that has not been included in
the model, an attempt to subsequently access the file will also result
in a pertubation of the model state.

A critical element in all of this is the notion of modeling namespaces
that reduce the complexity scope of the implemented models.  As an
additional, and hopefully helpful example, a micro-services
application running in a container may never demonstrate the need to
rename or unlink a file.  An attempt to do so, if for example the
application were compromised, will be denied, regardless of the object
of the rename.

We have additional work that will be forthcoming on this issue, but as
you noted above, and in the last e-mail, better to be simple first.

> > > > > > +                       euid=NN
> > > > > > +                               The ASCII base 10 representation of
> > > > > > +                               the numeric value of the effective
> > > > > > +                               discretionary user id of the process
> > > > > > +                               that is executing the security event.
> > > > > > +
> > > > > > +                       euid=NN
> > > > > > +                               The ASCII base 10 representation of
> > > > > > +                               the numeric value of the effective
> > > > > > +                               discretionary user id of the process
> > > > > > +                               that is executing the security event.
> > > > > > +
> > > > > > +                       suid=NN
> > > > > > +                               The ASCII base 10 representation of
> > > > > > +                               the numeric value of the saved user id
> > > > > > +                               of the process that is executing the
> > > > > > +                               security event.
> > > > > > +
> > > > > > +                       gid=NN
> > > > > > +                               The ASCII base 10 representation of
> > > > > > +                               the numeric value of the discretionary
> > > > > > +                               group id of the process that is
> > > > > > +                               executing the security event.
> > > > > > +
> > > > > > +                       egid=NN
> > > > > > +                               The ASCII base 10 representation of
> > > > > > +                               the numeric value of the discretionary
> > > > > > +                               effective group id of the process that
> > > > > > +                               is executing the security event.
> > > > > > +
> > > > > > +                       egid=NN
> > > > > > +                               The ASCII base 10 representation of
> > > > > > +                               the numeric value of the discretionary
> > > > > > +                               effective group id of the process that
> > > > > > +                               is executing the security event.
> > > > > > +
> > > > > > +                       sgid=NN
> > > > > > +                               The base 10 ASCII representation of
> > > > > > +                               the numeric value of the saved
> > > > > > +                               discretionary group id of the process
> > > > > > +                               that is executing the security event.
> > > > > > +
> > > > > > +                       fsuid=NN
> > > > > > +                               The base 10 ASCII representation of
> > > > > > +                               the numeric value of the discretionary
> > > > > > +                               filesystem user id of the process that
> > > > > > +                               is executing the security event.
> > > > > > +
> > > > > > +                       fsgid=NN
> > > > > > +                               The ASCII base 10 representation of
> > > > > > +                               the numeric value of the discretionary
> > > > > > +                               filesystem group id of the process
> > > > > > +                               that is executing the security event.
> > > > > > +
> > > > > > +                       cap=0xNNN
> > > > > > +                               The ASCII base 16 representation of
> > > > > > +                               the numeric value of effective
> > > > > > +                               capabilities of the process that is
> > > > > > +                               executing the security event.
> > > > > > +
> > > > > > +               If the CELL value for a security event includes the
> > > > > > +               definition of a file a file{} event field will be
> > > > > > +               included.  The following characteristics will be
> > > > > > +               encoded in this field:
> > > > > > +
> > > > > > +                       flags=NN
> > > > > > +                               The ASCII base 10 representation of
> > > > > > +                               the flags value of the 'struct file'
> > > > > > +                               structure that is the source of the
> > > > > > +                               file description.
> > > > > > +
> > > > > > +                       uid=NN
> > > > > > +                               The ASCII base 10 representation of
> > > > > > +                               the discretionary user id of the file.
> > > > > > +
> > > > > > +                       gid=NN
> > > > > > +                               The base 10 ASCII representation of
> > > > > > +                               the discretionary group id of the
> > > > > > +                               file.
> > > >
> > > > > Similar to the task UID/GID mapping questions above, there are
> > > > > mechanisms which map the file user/group IDs, which will be used in
v> > > > > the CELL definition and how will that be resolved between the kernel
> > > > > and an external modeler?
> > > >
> > > > The answer is the same as with the COE, see the following function:
> > > >
> > > > security/tsem/event.c:get_file_cell()
> > > >
> > > > Once again, the TMA only operates on the event description presented
> > > > to it and is not influenced by its own namespace.
> >
> > > For this particular point, my concern isn't what policy the TMA
> > > implements, or what it uses as input, it's about understanding how
> > > this event information is collected.  For fields which can be
> > > namespaced (I'm referring to "normal" Linux Kernel namespaces and
> > > not any TSEM namespaces), the TSEM documentation should make it
> > > clear which namespace is used as a basis for the value.
> >
> > FWIW, based on feedback we have received, there may be a modeling
> > domain/namspace setup option forthcoming that allows a trust
> > orchestrator to request that the uid/gid et.al characteristics be
> > exported in the context of the current user namespace.

> Please make sure you are explicit in which "current user namespace":
> the namespace which generated the event, or the namespace in which
> the modeling agent is running.  You should also provide some
> guidance on how to handle issues that might arise when the two
> namespaces (generating namespace, modeler namespace) are different.
> If you don't plan to allow the modeling agent to run in a separate
> namespace from the generating event stream please explain how that
> requirement will be enforced by the kernel.

We have already validated the implementation for allowing the user
namespace reference for a modeling domain to be selected on a domain
by domain basis.

We will document these issues, FWIW, some clarifications that may be
helpful for those following this discussion.

For an internally modeled domain, there are no separate entities to be
concerned about.  The processes that execute in the context of the
domain will model their events based on whatever user namespace they
are in.  If the user namespace changes, the representative
characteristics being used will change, which would seem to be
reasonable, if the domain has been configured to be sensitive to the
user namespace mappings that the process is running in.

In an externally modeled domain, by definition, the modeling process
must be in a different modeling domain than the modeled process.  Our
reference to Heisenberg, in the documentation, was not by
happenstance, the act of modeling would perturb the state of the
modeled system.

The modeling process and the modeled processes can run in separate or
different user namespaces.  The modeling process and the modeled
processes will generate and report their derived security state
coefficients to different modeling domains.

> > > > > > +What:          /sys/fs/tsem/ExternalTMA
> > > > > > +Date:          November 2022
> > > > > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > > > > +Description:
> > > > > > +               The ExternalTMA directory is a container directory
> > > > > > +               that hold files that will be used to export the
> > > > > > +               security events, and their associated parameters, for
> > > > > > +               externally modeled security domains/namespaces.
> > > > > > +
> > > > > > +               The files created in this directory will be named by
> > > > > > +               the base 10 ASCII representation of the id value
> > > > > > +               assigned to the modeling domain/namespace.  See the
> > > > > > +               documentation for the /sys/fs/tsem/id file in this
> > > > > > +               documentation for more details on this value.
> > > > > > +
> > > > > > +               This file will is a read-only file that can be polled
> > > > > > +               by a userspace trust orchestration implementation to
> > > > > > +               process security events that are to be modeled by
> > > > > > +               an external Trusted Modeling Agent.
> > > > > > +
> > > > > > +               The type of the exported event is the first keyword of
> > > > > > +               the line that is output and have the following
> > > > > > +               values and arguments:
> > > > > > +
> > > > > > +               aggregate HEXID:
> > > > > > +                       Where HEXID is the ASCII base 16
> > > > > > +                       representation of the 256 bit hardware
> > > > > > +                       platform aggregate value.
> > > > > > +
> > > > > > +               export pid{NNN} COE{} CELL_DEFINITION
> > > > > > +                       Where the NNN in the pid field is the ASCII
> > > > > > +                       base 10 value of the id of the process that is
> > > > > > +                       executing the security event that will be
> > > > > > +                       modeled.
> > > >
> > > > > I worry whenever I see a PID used as an identifier shared across the
> > > > > kernel/userspace boundary as it is inherently racy.  Given the
> > > > > somewhat coarse COE definition where one can expect multiple
> > > > > processes/PIDs to share the same COE value, and the ability of
> > > > > untrusted users/processes to manipulate the PID table, what do you
> > > > > expect to use the pid{NNN} field for in this event?
> > > > >
> > > > > Similar to the other namespace/mapping issues discussed previously,
> > > > > there is also the PID namespace issue to worry about.  How is that
> > > > > handled here?
> > > >
> > > > The concern over the PID issue is understandable, I will treat the
> > > > reasoning behind its use below.
> > > >
> > > > The PID value is the 'native' value managed by the kernel, not a
> > > > mapped value.
> >
> > > Regardless of if the PID is rooted in the initial namespace or a
> > > different PID namespace, the issue of PIDs being inherently racy is
> > > a real problem.  Can you help me understand how TSEM avoids the
> > > common pitfalls associated with using PIDs to identify processes on
> > > the system?
> >
> > The second version of the TSEM series, now includes support for a
> > requirement that a process being externally modeled, authenticate
> > itself to the TMA in order for the trust control call to act on
> > the process.

> Please bear with me, I want to make sure I'm clear on this point.
> In order for a process to be modeled by an external
> modeling-agent/TMA it would need to first authenticate with the TMA
> (using a TBD mechanism); is that correct?

Yes, somewhat more specifically, we implemented the requirement for
mutual authentication between an external TMA and the modeled process.

> I guess we will need to see how the authentication works, but is
> there a mechanism in place to ensure that a malicious process could
> not pass an authentication token to another (PID recycled) process?

If we understand the concern correctly, this would imply that a
malicious process has read/write access to arbitrary kernel memory
that it is not allowed to access, which would seem to represent a
catastrophic security event that cannot be defended against.

I think the appropriate metaphor, in classic subject/object security
models, would be if a malicious process had the ability to modify
either its own or another processes label, i.e if CAP_MAC_ADMIN were
lost to an adversary.

> Do you plan to support unauthenticated external modeling?  If so,
> how do you plan to address PID recycling?

The current codebase no longer supports anything other than
authenticated trust control.

> > > > > > +What:          /sys/fs/tsem/control
> > > > > > +Date:          November 2022
> > > > > > +Contact:       Greg Wettstein <greg@enjellic.com>
> > > > > > +Description:
> > > > > > +               The control file is the only writable file in the
> > > > > > +               filesystem and is used by the trust orchestrators to
> > > > > > +               configure and control the behavior of the TSEM
> > > > > > +               implementation.
> > > > > > +
> > > > > > +               The following keyword and arguments are recognized:
> > > > > > +
> > > > > > +               internal:
> > > > > > +                       The internal keyword causes an internally
> > > > > > +                       modeled domain to be created for the calling
> > > > > > +                       process.
> > > > > > +
> > > > > > +               external:
> > > > > > +                       The external keyword causes an externally
> > > > > > +                       modeled domain to be created for the calling
> > > > > > +                       process.
> > > > > > +
> > > > > > +               enforce:
> > > > > > +                       The enforce keyword causes the modeling
> > > > > > +                       domain/namespace of the process to enter
> > > > > > +                       enforcing mode.  In this mode a value of
> > > > > > +                       -EPERM will be returned for a security event
> > > > > > +                       that does not map into the current set of
> > > > > > +                       allowed state points for the security model
> > > > > > +                       being implemented for the domain/namespace.
> > > > > > +
> > > > > > +               seal:
> > > > > > +                       The seal keyword causes the security model
> > > > > > +                       being implemented for the model to be placed
> > > > > > +                       in sealed state.  In this state the current
> > > > > > +                       set of security event points is considered to
> > > > > > +                       be the only set of valid points for the
> > > > > > +                       domain/model.  Any subsequent events that map
> > > > > > +                       to a point not in the current model will be
> > > > > > +                       considered a violation of the model.
> > > > > > +
> > > > > > +               trusted PID:
> > > > > > +                       The trusted keyword is used by a trust
> > > > > > +                       orchestrator to indicate that the process
> > > > > > +                       identified by the PID argument should be
> > > > > > +                       allowed to run in trusted status.
> > > > > > +
> > > > > > +               untrusted PID:
> > > > > > +                       The untrusted keyword is used by a trust
> > > > > > +                       orchestrator to indicate that the process
> > > > > > +                       identified by the PID argument should be
> > > > > > +                       allowed to run but designated as an untrusted
> > > > > > +                       process.
> > > >
> > > > > The 'trusted PID:' and 'untrusted PID:' commands are concerning for
> > > > > the reasons described above about PIDs being racy and generally an
> > > > > unreliable way of identifying processes across the kernel/userspace
> > > > > boundary.  I suspect it would not be too difficult for a malicious
> > > > > user to trick an external modeler into marking the wrong process as
> > > > > trusted/untrusted.
> > > >
> > > > An external TMA needs the PID value to determine which process to wake
> > > > up and set the trust status value on in the task control structure,
> > > > after the event is modeled.  As was noted above, the PID value is the
> > > > unmapped value maintained by the OS.
> > > >
> > > > Lets see if we can reason through why the PID can be used safely.
> > > >
> > > > CAP_TRUST, or whatever ends up getting used, is required by the trust
> > > > orchestrator to create a security/modeling namespace for the workload
> > > > being modeled.  This results in the creation of the following
> > > > pseudo-file for surfacing the security event descriptions for the
> > > > namespace/workload:
> > > >
> > > > /sys/fs/tsem/ExternalTMA/N
> > > >
> > > > Where N is the id number of the modeling domain.
> > > >
> > > > CAP_TRUST, caveats applied, is required to open the pseudo-file.  The
> > > > trust orchestrator only receives and acts on PID values through this
> > > > conduit from the kernel.
> > > >
> > > > When an event description is exported, the trust status of the task is
> > > > set to 'pending' and the process is placed in interruptible sleep and
> > > > scheduled away, with the 'wakeup' criteria being the trust status
> > > > being changed from pending to either trusted or untrusted.
> > > >
> > > > The only path to change the trust status value in the LSM task control
> > > > structure and wake up the process is by the trust orchestrator that
> > > > created the namespace, by writing the appropriate value to the
> > > > /sys/fs/tsem/control file.  Access to that file is gated by CAP_TRUST
> > > > or its equivalent.
> > > >
> > > > See the following code locations for further details:
> > > >
> > > > security/tsem/export.c:tsem_export_event()
> > > >
> > > > security/tsem/fs.c:control_COE()
> > > >
> > > > As long as the process 'exists', albeit sleeping, the PID slot is
> > > > occupied and an adversary, regardless of namespace, cannot substitute
> > > > a task with the same PID value.
> > > >
> > > > This leaves an adversary with the need to terminate the task being
> > > > modeled in order to capture its PID slot.
> > > >
> > > > Precautions are implemented in the following function to protect the
> > > > process from being terminated by an adversary:
> > > >
> > > > security/tsem/tsem.c:tsem_task_kill()
> >
> > > What about the OOM killer?
> > >
> > > The security_task_kill() LSM hook only offers an access control point
> > > for one process sending another process a signal, it doesn't gate a
> > > process being killed for other reasons.  The OOM killer is the first
> > > thing that comes to mind, but I'm reasonably certain there are other
> > > similar scenarios.
> >
> > As noted above, as an additional protection, the next version of the
> > series requires that a process authenticate itself as being a member
> > of the modeling domain in order for the trust status control call to
> > succeed.
> >
> > With this implementation, substituting an alternate process would now
> > require that an adversary break the security context between the TMA
> > and process in the modeling domain.

> I'll look forward to seeing the new authentication mechanism.  Please
> ensure it is properly documented.

The full details will be there.

> > > > > > +Process and Platform Trust Status
> > > > > > +=================================
> > > > > > +
> > > > > > +A fundamental concept in TSEM is the notion of providing a precise
> > > > > > +definition for what it means for a platform or workload to be trusted.
> > > > > > +A trusted platform or workload is one where there has not been an
> > > > > > +attempt by a process to execute a security relevant event that does
> > > > > > +not map into a known security state point.
> > > > > > +
> > > > > > +The process trust status is a characteristic of the process that is
> > > > > > +passed to any subordinate processes that are descendants of that
> > > > > > +process.  Once a process is tagged as untrusted, that characteristic
> > > > > > +cannot be removed from the process.  In a 'fruit from the poisoned
> > > > > > +vine' paradigm, all subordinate processes created by an untrusted
> > > > > > +process are untrusted as well.
> > > > > > +
> > > > > > +On entry into each TSEM security event handler, the trust status of a
> > > > > > +process is checked before an attempt to model the event is made.  An
> > > > > > +attempt to execute a security event by an untrusted process will cause
> > > > > > +the event, and its characteristics, to be logged.  The return status
> > > > > > +of the hook will be determined by the enforcement state of the model.
> > > > > > +A permission denial is only returned if the TMA is running in
> > > > > > +enforcing mode.
> > > > > > +
> > > > > > +If the platform running the TSEM LSM has a TPM, the hardware aggregate
> > > > > > +value is computed at the time that TSEM is initialized.  This hardware
> > > > > > +aggregate value is the linear extension sum over Platform
> > > > > > +Configuration Registers (PCR's) 0 through 7.  This is the same
> > > > > > +aggregate value that is computed by the Integrity Measurement
> > > > > > +Architecture (IMA) and is the industry standard method of providing an
> > > > > > +evaluation measurement of the hardware platform state.
> > > > > > +
> > > > > > +Internally model domains have the hardware aggregate measurement
> > > > > > +included as the first state point in the security model.  Externally
> > > > > > +modeled domains export the hardware aggregate value to the TMA for
> > > > > > +inclusion as the first state point of the model maintained by the TMA.
> > > > > > +
> > > > > > +The root modeling domain extends each security state point into PCR
> > > > > > +11.  This allows hardware based TSEM measurements to coexist with IMA
> > > > > > +measurement values.  This hardware measurement value can be used to
> > > > > > +attest to the security execution trajectory that the root model
> > > > > > +maintains.
> > > >
> > > > > It seems like making the target PCR configurable would be a good
> > > > > idea, at the very least make it a Kconfig option.
> > > >
> > > > That was something that we have thought about, it probably needs a
> > > > Kconfig option.
> > > >
> > > > Contrary to all appearances, as a team we are really minimalists at
> > > > heart and tend to not make things more complex or configurable than
> > > > needed.... :-)
> > > >
> > > > > Also, can you elaborate on how the security state points are
> > > > > extended into the PCR?  I imagine for it to be useful at an
> > > > > arbitrary point in time this would require the PCR to be extended as
> > > > > the security points were generated, which would imply that the PCR
> > > > > value would be dependent on execution order, and in most cases,
> > > > > scheduling order as well.  How useful do you expect this to be for
> > > > > most users?
> > > >
> > > > Your assessment is correct, the state points are extended into the PCR
> > > > whenever a unique security state point is generated.
> > > >
> > > > In a 'free-running' model, the value in the register will be fungible
> > > > due to scheduling dependencies.
> >
> > > In other words, garbage ;)
> >
> > We don't disagree on the utility of a scheduling fungible measurement
> > value.  However, this is an remarkably interesting
> > conclusion/statement, by the Linux security sub-system maintainer no
> > less, given that it describes the current state of the art with
> > respect to hardware security co-processors and trusted system
> > technology.. :-)

> I've yet to meet a kernel maintainer that doesn't hold amusing
> opinions on at least one issue; one could almost make an argument that
> it is a prerequisite for the role.  However, I feel that using
> non-deterministic values as a measure of system state/attestation is
> well understood to be garbage and isn't quite as interesting as you
> would make it.
>
> Based on the rest of the TSEM docs and this discussion, I'm guessing
> you are referencing IMA's measurements into PCR 10, or something
> similar, when you talk about the current state of the art, is that
> correct?

Yes.

> In the case of IMA, the important thing to remember is that PCR 10
> can be reliably attested using the IMA measurement log; the IMA
> project even provides tools and documentation demonstrating how to
> do so.  Does TSEM offer a similar measurement log?

Yes, in TSEM, the 'measurement' value can be used to validate the
order that the security state coefficients, ie. the values surfaced in
the /sys/kernel/security/tsem/points pseudo-file, were generated in.

> My apologies if I missed it.

I always tell people that all of this is straight forward, but there
is probably a lot here.

> > > > If the model is pre-defined, the security state points will be
> > > > extended into the register as they are loaded through the
> > > > /sys/fs/tsem/map pseudo-file interface.  In this case, the value will
> > > > be fixed and any departure from the value would signal that the
> > > > modeling domain has departed from its specification.
> > > >
> > > > With respect to the utility of the value, in a 'free-running' model it
> > > > is about as useful as the value that IMA maintains in PCR 10, which in
> > > > our opinion is not very useful and is why we implemented the notion of
> > > > the 'state' value of a model.
> >
> > > For a variety of reasons, and mostly to help keep things civil,
> > > let's refrain from comparing one LSM to another.  Each LSM makes its
> > > own choices, and needs to stand on its own; just because LSM did X
> > > doesn't mean TSEM can do X if it is silly in the context of TSEM.
> >
> > Our intent was not to be incivil, but rather to call out one of the
> > motivations in the implementation of TSEM, and in a larger context,
> > the notion of a TMA based security architecture.
> >
> > A now prehistoric version of TSEM was implemented as a patch on top of
> > IMA.  We actually built systems for clients on top of that
> > architecture.  Our concept of a 'state' value was driven by the
> > difficulties we experienced in implementing, and maintaining, these
> > systems in a field environment.
> >
> > We offer the concept of a 'state' value in order to simplify the
> > attestation model, which classically, has required that a verifying
> > party review an event log for its validity, after verifying that the
> > measurement value confirms the integrity of the log.

> Having a log ordered by the sequence of events can be important.
> After all, if a security critical configuration knob is toggled
> multiple times, and the event ordering is not preserved, how does one
> know the current state of the system?  I might be able to see that the
> knob was turned both on and off, but without knowing which occurred
> last, how do I know if the system is in a known good state?

Yes, that is classically the explanation that is given for having an
ordered event log.  That being said, we tend to struggle with the
validity of this thinking, that is not criticism, perhaps more of a
lack of understanding on our part.

Let's consider IMA, or TSEM running in a model context that only
observes the integrity of binaries run with root privileges, roughly
equivalent implementations.  In either scenario, you have an
attestation of the fact that a known binary executed in a known
temporal order, but does that tell you the final state of the system
from a security perspective?

Take iptables as an example, given its potential contribution to the
trust status of a system.  If you know that it executed twice, can it
be effectively reasoned what it was doing each time it executed,
without access to things like the command-line arguments?

Conceptually, in an extremely static system configuration, the rule
might be that system attestation fails if iptables ran more than once,
but in a multi-execution scenario it is unclear what can be reasoned.

> > > > > > +Internal vs external modeling
> > > > > > +-----------------------------
> > > > > > +
> > > > > > +When a TSEM modeling domain is created, a designation is made as to
> > > > > > +whether the domain is to be internally or externally modeled.
> > > > > > +
> > > > > > +In an internally modeled domain, the security event handlers pass the
> > > > > > +event type and its characteristics to the designated internal trusted
> > > > > > +modeling agent.  The agent provides the permission value for the
> > > > > > +security event handler to return as the result of the event and sets
> > > > > > +the trust status of the process executing the event.
> > > > > > +
> > > > > > +In an externally modeled domain, the event type and parameters are
> > > > > > +exported to userspace for processing by a trust orchestrator with an
> > > > > > +associated TMA.  The trust orchestrator communicates the result of the
> > > > > > +modeling back to the kernel to support the setting of the process
> > > > > > +trust status.
> > > > > > +
> > > > > > +This model poses a limitation to the ability of TSEM to model some
> > > > > > +security events.  This is secondary to the fact that some event
> > > > > > +handlers (LSM hooks) are called from a non-sleeping context, as a
> > > > > > +result the process cannot be scheduled.  This is particularly the case
> > > > > > +with the task based hooks, since they are typically called with the
> > > > > > +tasklist lock held.
> > > > > > +
> > > > > > +This limitation is also inherent to the root model that extends the
> > > > > > +security state points into TPM PCR 11, secondary to the fact that the
> > > > > > +process invoking the security event hook will be scheduled away while
> > > > > > +the TPM transaction completes.
> > > > > > +
> > > > > > +Addressing this problem directly requires a consideration of the
> > > > > > +context from which the security event handlers are being called.
> > > > > > +Subsequent implementations of TSEM will include a mechanism for
> > > > > > +asynchronous deferral of model processing, until when and if, a review
> > > > > > +of the call context would be considered worthwhile by the LSM
> > > > > > +community.
> > > >
> > > > > This is a pretty big limitation, and in conjunction with the some of
> > > > > the other issues brought up earlier (the PID issue seems the most
> > > > > concerning), I'm having a difficult time believeing that an external
> > > > > modeler could operate safely given the design presented here.
> > > >
> > > > With respect to the PID issue, we would welcome any comments on the
> > > > analysis that we provided above as to its design safety.
> > >
> > > >From what I can tell from the documentation and our discussion thus
> > > far is that TSEM relies on a security_task_kill() hook implementation
> > > to ensure that a process is not killed, and the PID released, without
> > > explicit TSEM approval.  Unfortunately, I believe that relying solely
> > > on security_task_kill() will not fully cover all of the cases where a
> > > process can be killed, mostly because security_task_kill() does not
> > > control process destruction, it controls the ability of one process to
> > > signal another.
> >
> > > You might be able to do something with security_task_free(), but I
> > > haven't given that much thought.
> >
> > Our analysis suggested that an authentication strategy was the
> > strongest and most complete implementation moving forward.
> 
> I'll look for that in the next revision.
> 
> > > > If the PID issue remains a concern, we have an extension to the export
> > > > descriptions that would include a random nonce that would be emitted
> > > > with the PID.  The nonce would be placed in the LSM task control
> > > > 'blob' for the sleeping task and used to confirm that the task release
> > > > directive was acting on the correct process.
> >
> > > That should help, but ultimately a nonce is still a bounded resource
> > > and subject to recycling just like the PID.  I'm open to hearing
> > > other ways in which you believe you can resolve this issue, but I
> > > remain skeptical.
> >
> > FWIW, I believe that current thinking is that a nonce based on a
> > 64-bit value is immune from recycling.  The classic metric for a
> > 64-bit counter is that a consumption rate of 1000 values/second yields
> > a counter cycle time of 584,942,417 years.  Nanosecond rates still
> > buys you 584 years.
> >
> > I believe that Jason built the Wireguard protocol on this predicate.

> Once again, just because project X did something doesn't mean it is
> acceptable here.

FWIW, from a design perspective, we try to operate under the
assumption that there are well understood architectural predicates
that secure systems can be built on.

For example, the statistical infeasibility of predicting a large
number generated by a random number generator with known numerical
characteristics or the lack of a direct solution to the discrete
logarithm problem.

We bin the chronological infeasibility of wrapping a 64-bit counter in
the same bucket, perhaps that is an oversight on our part.

> > We believe the second series will fully address this issue, without
> > using nonces, for whatever that is worth.  We can reserve further
> > discussion once that code is available and submitted for review.

> I mentioned this above, but please ensure the authentication approach
> is well documented.

It will be explained in detail.

> > > > > Frankly, I also wonder how a system would perform with an external
> > > > > modeler, indepdent of the issues with non-blocking hooks.  How does
> > > > > the system perform with every blockable LSM hook invocation
> > > > > potentially blocking on a response from userspace?  Or with the COE
> > > > > being somewhat coarse, does the trajectory/policy populate itself
> > > > > quickly?
> > > >
> > > > One obviously experiences a latency hit in going to userspace, by
> > > > definition, implementing security always has an associated resource
> > > > cost.  So, once again, this comes down to a cost/benefit analysis.
> > > >
> > > > As a Gedanken exercise, consider the value proposition of a Linux
> > > > based RTU, or other device, controlling infrastructure that can only
> > > > execute security relevant events that are guaranteed to be known good
> > > > by an external co-processor that is only accessible as a security
> > > > oracle.
> > > >
> > > > Given that frame of reference.
> > > >
> > > > Time for a userspace or SGX based TMA transaction is running around
> > > > 890 micro-seconds.
> > > >
> > > > Going to a TMA based in a Xen stubdomain implementation runs a bit
> > > > longer, probably around 940 micro-seconds or so.
> > > >
> > > > The micro-controller implementations are decidedly slower, with the
> > > > NRF52840-DONGLE clocking in at around 40 micro-seconds, but that is
> > > > strictly a CPU horsepower issue.
> > > >
> > > > All of this with the caveat that we have been focusing almost
> > > > exclusively on correctness and not optimizing performance.
> > > >
> > > > We've thought a bit, mainly on long walks with our Golden Retriever
> > > > Izzy, about the issue of building a kernel based policy cache with
> > > > externally modeled domains.  Given that the kernel does not, a-priori,
> > > > know what modeling algorithm a TMA might be using, we would need to
> > > > come up with a method of deterministically mapping a security event
> > > > description to a known good state point value.
> > > >
> > > > The other issue with all this is that with containerized workloads,
> > > > particularly micro-services, the rate of security event generation can
> > > > be surprisingly low.  Obviously this is also the case with embedded
> > > > implementations.
> > > >
> > > > Once again, what are you willing to pay to be safe?
> >
> > > For better or worse, when code is proposed for the upstream Linux
> > > Kernel it is subject to scrutiny from all manner of developers and
> > > users, with most being focused on their own pet projects/subsystems,
> > > not whatever new security promises you are providing.
> > >
> > > There have been patch(sets) and discussions relating to performance
> > > gains/losses on the other of tens of nanoseconds per operation.
> > >
> > > I think most of us in the security community are sympathetic to the
> > > question of "what are you willing to pay to be safe", but please
> > > understand that while we are understanding, there are others who will
> > > disagree not only with the performance cost tradeoff, but the very
> > > idea of safety you are promising.  My only suggestion is to be
> > > prepared, and be honest with the performance assessments of TSEM.
> >
> > We seem to be in agreement that there will always be a natural tension
> > between security and performance.  With TSEM our goal is to offer
> > choices.
> >
> > If an environment is sensitive to performance defects on the order of
> > tens of nanoseconds, it would seem unlikely that the architects or
> > administrators of such systems would be implementing integrity
> > controls of any kind.  In that context, we are no different than IMA
> > or IPE, it would seem highly unlikely that such environments are going
> > to tolerate a security solution involving a cryptographic checksum of
> > any type.

> Performance comparisons are always going to be relative.  In the
> tens-of-nanoseconds example that I'm thinking of, it wasn't about
> disabling security functionality, it was about optimizing the
> security functionality.

Given the current performance hit that speculative execution has given
us, with respect to indirect function calls, it would seem that the
LSM is going to be a problematic architecture, particularly with any
type of stacking.... :-)

> > > > > > +Event handlers that cannot be directly modeled, still consider, on
> > > > > > +entry, whether or not they are being called by an trusted or untrusted
> > > > > > +process.  As a result, an untrusted process will cause a non-modeled
> > > > > > +event to return a permissions violation in enforcing mode, even if the
> > > > > > +security event cannot be directly modeled.
> > > > > > +
> > > > > > +Security event modeling typically traps violations of trust by a COE
> > > > > > +with unmodeled characteristics that is attempting to access/execute a
> > > > > > +file or map memory as executable; or by a COE with known
> > > > > > +characteristics attempting to access or execute a CELL not prescribed
> > > > > > +by a model.  As a result, the impact of the ability to not directly
> > > > > > +model these events is lessened.
> > > > >
> > > > > ...
> > > > >
> > > > > > +Event modeling
> > > > > > +--------------
> > > > > > +
> > > > > > +TSEM security event modeling is based on the following functional
> > > > > > +definition for a security state point:
> > > > > > +
> > > > > > +Sp = SHA256(SHA256(EVENT_ID) || TASK_ID || SHA256(COE) || SHA256(CELL))
> > > >
> > > > > It appears that all of the hasing in TSEM is SHA256 based, you might
> > > > > want to consider making that a Kconfig option at the very least.
> > > >
> > > > That has been something that we have talked about as well.
> > > >
> > > > As I indicated previously, we really are minimalists, particularly
> > > > after watching IMA fight with issues surrounding algorithmic agility.
> > > >
> > > > It would be easy enough to make this configurable but does anyone see
> > > > SHA256 as not being useful in in this role anywhere in the next 10
> > > > years?
> >
> > > There are any number of reasons why one might need to select a
> > > different hash algorithm: legal constraints, security
> > > certifications, corporate policy.  I would strongly suggest making
> > > this configurable.
> >
> > Certainly sound and well reasoned advice, but the question then becomes
> > what hashes and what hash lengths, do you have any specific
> > recommendations?

> My recommendation is to make it configurable such that as algorithms
> are added, or removed, from the the kernel crypto code, they can be
> added to TSEM without much more than some Kconfig changes.

TSEM/V2 now can use any hash function that a kernel has available, it
was actually a remarkably straight forward implementation.

> > IMA currently has the options of SHA1, SHA256, SHA512, WHIRLPOOL512
> > and SM3; is this sufficient coverage, given that SHA1 in a new
> > implementation like TSEM probably doesn't make any sense?

> I can't honestly pretend to understand all of the different
> requirements which would dictate a user's choice of a hash algorithm.
> About the only thing I can say is that given a choice of stronger
> options, I wouldn't use SHA1 in a security context on any of the
> systems I maintain.

Nor would we, but it is now available if anyone wants it.... :-)

> > Our current inclination, for the initial release, in an embrace of
> > minimalisim, would be to make this a selectable option when a modeling
> > domain is setup, with the only selectable option being SHA256.  This
> > would place the onus on userspace to make the decision and doesn't
> > lock the kernel to an ABI.

> So long as it is configurable, and the API is designed to support
> different algorithms, it may be acceptable to only implement one
> algorithm in the initial implementation.  However, one of the easiest
> ways to ensure the specification and the implementation work correctly
> would be to support at least two algorithms in the initial
> implementation so that this ability can be tested.

We are now validating against multiple hash implementations, each with
multiple digest sizes, so hopefully this will lay the cryptographic
agility issue to rest.

> paul-moore.com

FWIW, we do appreciate your perspective on these issues, the
implementation has already improved as a result of your concerns.

Have a good remainder of the week.

As always,
Dr. Greg

The Quixote Project - Flailing at the Travails of Cybersecurity

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 02/14] Add TSEM specific documentation.
  2023-03-30  3:34             ` Dr. Greg
@ 2023-04-05 20:45               ` Paul Moore
  2023-04-07 14:10                 ` Dr. Greg
  0 siblings, 1 reply; 42+ messages in thread
From: Paul Moore @ 2023-04-05 20:45 UTC (permalink / raw)
  To: Dr. Greg; +Cc: linux-security-module

On Wed, Mar 29, 2023 at 11:35 PM Dr. Greg <greg@enjellic.com> wrote:
> On Wed, Mar 22, 2023 at 07:45:26PM -0400, Paul Moore wrote:
> > On Mon, Mar 13, 2023 at 6:52???PM Dr. Greg <greg@enjellic.com> wrote:
> > > On Thu, Mar 02, 2023 at 11:15:56PM -0500, Paul Moore wrote:
> > >
> > > Hi Paul, thanks for sending along further comments.
> > >
> > > You note below that you haven't had time to look at the code since you
> > > wanted to confirm the TSEM security model before moving forward.
> > >
> > > From a development perspective we are now three weeks into what will
> > > become version 2 of the patch series.  So at this point I wouldn't
> > > advocate spending a lot of time on the current patchset.
> > >
> > > That being said, if you some have time, we would appreciate a quick
> > > look at the code on your part, with respect to style changes and the
> > > like we can enforce in the second series, ie. ordering of local
> > > variable declarations by length and the like.
>
> > To be perfectly honest I'm still very concerned about some of the
> > issues that I've seen in the docs, until that is sorted out I'm not
> > sure there is much point in looking at the code.
>
> I think those concerns can be resolved, see below for more
> information, the second patch series that we are closing in on should
> help address the concerns that are currently on the table.

In that case, I think it might be best to wrap up this thread and we
can resume the discussion on the next patchset.

> That being said, since TSEM is a new codebase, we were hoping that you
> could give us some guidance on function local variable ordering.
> Reverse Christmas tree seems popular writ large in the kernel, I
> believe that you commented in a posting a month or two ago that you
> prefer standard Christmas tree, SMACK and SeLinux don't seem to
> religiously embrace a style.
>
> Our codebase uses ordering based on least complex to most complex
> variables and has worked for us, both in the kernel and elsewhere, but
> we are ambivalent, as our primary objective is to avoid wasting
> everyone's time on issues such as this.

The canonical guidance on coding style within the kernel is in the kernel docs:

https://www.kernel.org/doc/html/latest/process/coding-style.html

When in doubt, I would recommend following that as closely as possible.

As far as local variable ordering is concerned, I don't believe I've
ever rejected patches due to that.  My own personal preference usually
follows what you've described above: the least complex (simple
scalars) at the top, with the more complex variables (composites) at
the bottom.  In practice this tends to result in a "Christmas Tree"
ordering, but it can be a bit lumpy (?) in some cases; that is fine.

There are two style nitpicks which annoy me enough to make it worth mentioning:

* Stick to 80 characters as much as possible, yes we all have
terminals that can go wider, but I like to have several terminals on
my screen and if they all need to be 100 chars wide I can't fit as
many.  There are going to be some exceptions, e.g. error message
string literals, but that should only happen a few times in a given
file.  If you are finding that every function you write has a line
that goes past 80 characters you are doing *something* wrong.

* If/when you split a single line across multiple lines due to the
above, make sure the
lines are indented properly such that they line up properly with the
code above.  It's tricky to give all of the different examples so I'm
not going to even try.  I realize that is garbage guidance, but the
kernel coding style is a help here.

If you are really lost, I use the following 'astyle' command in other
projects, and it should produce fairly kernel-style friendly code:

% astyle --options=none --lineend=linux --mode=c \
    --style=linux \
    --indent=force-tab=8 \
    --indent-preprocessor \
    --indent-col1-comments \
    --min-conditional-indent=0 \
    --max-instatement-indent=80 \
    --pad-oper \
    --align-pointer=name \
    --align-reference=name \
    --max-code-length=80 \
    --break-after-logical

-- 
paul-moore.com

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 02/14] Add TSEM specific documentation.
  2023-04-05 20:45               ` Paul Moore
@ 2023-04-07 14:10                 ` Dr. Greg
  0 siblings, 0 replies; 42+ messages in thread
From: Dr. Greg @ 2023-04-07 14:10 UTC (permalink / raw)
  To: Paul Moore; +Cc: linux-security-module

On Wed, Apr 05, 2023 at 04:45:26PM -0400, Paul Moore wrote:

Good morning, I hope the week has gone well for everyone.

> On Wed, Mar 29, 2023 at 11:35???PM Dr. Greg <greg@enjellic.com> wrote:
> > On Wed, Mar 22, 2023 at 07:45:26PM -0400, Paul Moore wrote:
> > > On Mon, Mar 13, 2023 at 6:52???PM Dr. Greg <greg@enjellic.com> wrote:
> > > > On Thu, Mar 02, 2023 at 11:15:56PM -0500, Paul Moore wrote:
> > > >
> > > > Hi Paul, thanks for sending along further comments.
> > > >
> > > > You note below that you haven't had time to look at the code since you
> > > > wanted to confirm the TSEM security model before moving forward.
> > > >
> > > > From a development perspective we are now three weeks into what will
> > > > become version 2 of the patch series.  So at this point I wouldn't
> > > > advocate spending a lot of time on the current patchset.
> > > >
> > > > That being said, if you some have time, we would appreciate a quick
> > > > look at the code on your part, with respect to style changes and the
> > > > like we can enforce in the second series, ie. ordering of local
> > > > variable declarations by length and the like.
> >
> > > To be perfectly honest I'm still very concerned about some of the
> > > issues that I've seen in the docs, until that is sorted out I'm not
> > > sure there is much point in looking at the code.
> >
> > I think those concerns can be resolved, see below for more
> > information, the second patch series that we are closing in on should
> > help address the concerns that are currently on the table.

> In that case, I think it might be best to wrap up this thread and we
> can resume the discussion on the next patchset.

Very good, we will look forward to the review of V2, which has now
been enhanced on a number of fronts.

> > That being said, since TSEM is a new codebase, we were hoping that you
> > could give us some guidance on function local variable ordering.
> > Reverse Christmas tree seems popular writ large in the kernel, I
> > believe that you commented in a posting a month or two ago that you
> > prefer standard Christmas tree, SMACK and SeLinux don't seem to
> > religiously embrace a style.
> >
> > Our codebase uses ordering based on least complex to most complex
> > variables and has worked for us, both in the kernel and elsewhere, but
> > we are ambivalent, as our primary objective is to avoid wasting
> > everyone's time on issues such as this.
> 
> The canonical guidance on coding style within the kernel is in the kernel docs:
> 
> https://www.kernel.org/doc/html/latest/process/coding-style.html
> 
> When in doubt, I would recommend following that as closely as possible.
> 
> As far as local variable ordering is concerned, I don't believe I've
> ever rejected patches due to that.  My own personal preference usually
> follows what you've described above: the least complex (simple
> scalars) at the top, with the more complex variables (composites) at
> the bottom.  In practice this tends to result in a "Christmas Tree"
> ordering, but it can be a bit lumpy (?) in some cases; that is fine.
> 
> There are two style nitpicks which annoy me enough to make it worth mentioning:
> 
> * Stick to 80 characters as much as possible, yes we all have
> terminals that can go wider, but I like to have several terminals on
> my screen and if they all need to be 100 chars wide I can't fit as
> many.  There are going to be some exceptions, e.g. error message
> string literals, but that should only happen a few times in a given
> file.  If you are finding that every function you write has a line
> that goes past 80 characters you are doing *something* wrong.
> 
> * If/when you split a single line across multiple lines due to the
> above, make sure the
> lines are indented properly such that they line up properly with the
> code above.  It's tricky to give all of the different examples so I'm
> not going to even try.  I realize that is garbage guidance, but the
> kernel coding style is a help here.
> 
> If you are really lost, I use the following 'astyle' command in other
> projects, and it should produce fairly kernel-style friendly code:
> 
> % astyle --options=none --lineend=linux --mode=c \
>     --style=linux \
>     --indent=force-tab=8 \
>     --indent-preprocessor \
>     --indent-col1-comments \
>     --min-conditional-indent=0 \
>     --max-instatement-indent=80 \
>     --pad-oper \
>     --align-pointer=name \
>     --align-reference=name \
>     --max-code-length=80 \
>     --break-after-logical

All of the above is consistent with what we have used for years,
particularly 80 columns, given that the principles of TSEM extend from
programming with a Model 29 keypunch and a drum card to applying
machine learning to security.

> paul-moore.com

Have a good weekend.

As always,
Dr. Greg

The Quixote Project - Flailing at the Travails of Cybersecurity

^ permalink raw reply	[flat|nested] 42+ messages in thread

end of thread, other threads:[~2023-04-07 14:11 UTC | newest]

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.