diff --git a/security/tsem/fs.c b/security/tsem/fs.c
new file mode 100644
index 000000000000..04762dd5fd5c
--- /dev/null
+++ b/security/tsem/fs.c
@@ -0,0 +1,2304 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * Copyright (C) 2024 Enjellic Systems Development, LLC
+ * Author: Dr. Greg Wettstein <greg@enjellic.com>
+ *
+ * This file implements the TSEM control plane that is surfaced
+ * through the following directory heirarchy:
+ *
+ * /sys/kernel/security/tsem
+ *
+ * The TSEM ABI documentation documents the directories and files that
+ * are implemented in this directory heirarchy.
+ *
+ * A significant portion of the functions in this file are used to
+ * generate the JSON encoding of a security event description.  This
+ * encoding is surfaced to the tsem_export_show() function through the
+ * tsem_fs_show_trajectory() function.  This latter function is also
+ * used by the trajectory and forensics pseudo files that output the
+ * characteristics of security events modeled by the internal trusted
+ * modeling agent implementation.
+ *
+ * The pseudo-files implemented are context sensitive in that they
+ * provide output describing the security modeling namespace that the
+ * process that accesses the file is running in.
+ */
+
+#include <linux/seq_file.h>
+#include <linux/poll.h>
+
+#include "tsem.h"
+#include "nsmgr.h"
+
+static struct dentry *tsem_dir;
+static struct dentry *control;
+static struct dentry *id;
+static struct dentry *aggregate;
+static struct dentry *internal_tma;
+static struct dentry *model;
+static struct dentry *forensics;
+static struct dentry *forensics_counts;
+static struct dentry *forensics_coeff;
+static struct dentry *trajectory;
+static struct dentry *trajectory_counts;
+static struct dentry *trajectory_coeff;
+static struct dentry *measurement;
+static struct dentry *state;
+static struct dentry *external_tma;
+
+struct control_commands {
+	char *cmd;
+	enum tsem_control_type type;
+};
+
+static const char * const control_commands[] = {
+	"internal",
+	"external",
+	"export",
+	"enforce",
+	"seal",
+	"trusted",
+	"untrusted",
+	"state",
+	"pseudonym",
+	"base",
+	"lock"
+};
+
+enum namespace_argument_type {
+	NS_MODEL = 0,
+	NS_REF,
+	NS_DIGEST,
+	NS_KEY,
+	NS_CACHE
+};
+
+static const char * const namespace_arguments[] = {
+	"model",
+	"nsref",
+	"digest",
+	"key",
+	"cache"
+};
+
+enum control_argument_type {
+	CONTROL_KEY = 0,
+	CONTROL_PID
+};
+
+static const char * const control_arguments[] = {
+	"key",
+	"pid"
+};
+
+static bool can_access_fs(void)
+{
+	struct tsem_context *ctx = tsem_context(current);
+
+	if (ctx->external)
+		return false;
+	if (capable(CAP_MAC_ADMIN))
+		return true;
+	if (ctx->sealed)
+		return false;
+	return true;
+}
+
+static int control_COE(unsigned long cmd, pid_t pid, char *keystr)
+{
+	bool wakeup = false;
+	int retn = -ESRCH;
+	u8 event_key[HASH_MAX_DIGESTSIZE];
+	struct task_struct *COE;
+	struct tsem_task *task;
+	struct tsem_task *tma = tsem_task(current);
+
+	rcu_read_lock();
+	COE = find_task_by_vpid(pid);
+	if (COE != NULL) {
+		task = tsem_task(COE);
+		if (tsem_context(COE)->id != tma->tma_for_ns) {
+			retn = -EINVAL;
+			goto done;
+		}
+
+		retn = tsem_ns_event_key(task->task_key, keystr, event_key);
+		if (retn)
+			goto done;
+
+		if (memcmp(tma->task_key, event_key, tsem_digestsize())) {
+			retn = -EINVAL;
+			goto done;
+		}
+
+		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;
+	}
+
+ done:
+	rcu_read_unlock();
+
+	if (retn == -EINVAL)
+		pr_warn("tsem: Invalid process release request.\n");
+
+	if (wakeup)
+		wake_up_process(COE);
+
+	return retn;
+}
+
+static int config_COE(unsigned long cmd, char *arg)
+{
+	char **argv, *argp, *key = NULL;
+	int argc, retn = -EINVAL;
+	unsigned int lp;
+	long pid = 0;
+	enum control_argument_type control_arg;
+
+	if (!*arg)
+		return retn;
+
+	argv = argv_split(GFP_KERNEL, arg, &argc);
+	if (!argv)
+		return -ENOMEM;
+
+	for (lp = 0; lp < argc; ++lp) {
+		argp = strchr(argv[lp], '=');
+		if (!argp)
+			goto done;
+		*argp++ = '\0';
+
+		control_arg = match_string(control_arguments,
+					   ARRAY_SIZE(control_arguments),
+					   argv[lp]);
+		if (control_arg < 0)
+			goto done;
+
+		switch (control_arg) {
+		case CONTROL_KEY:
+			key = argp;
+			if (strlen(key) != tsem_digestsize()*2)
+				goto done;
+			break;
+		case CONTROL_PID:
+			if (kstrtol(argp, 0, &pid))
+				goto done;
+			break;
+		}
+	}
+
+	if (!key || !pid)
+		goto done;
+	retn = control_COE(cmd, pid, key);
+
+ done:
+	argv_free(argv);
+	return retn;
+}
+
+static int config_context(unsigned long cmd, char *bufr)
+{
+	int retn = -EINVAL;
+	unsigned int lp;
+	struct tsem_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, char *arg)
+{
+	char *argp;
+	int retn = -EINVAL;
+	u8 mapping[HASH_MAX_DIGESTSIZE];
+
+	if (!arg)
+		goto done;
+
+	argp = strchr(arg, '=');
+	if (!argp)
+		goto done;
+	*argp++ = '\0';
+
+	if (strcmp(arg, "value"))
+		goto done;
+
+	if (strlen(argp) != tsem_digestsize()*2)
+		goto done;
+	if (hex2bin(mapping, argp, tsem_digestsize()))
+		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 int config_namespace(enum tsem_control_type type, const char *arg)
+{
+	char **argv, *argp, *digest = "sha256", *key = NULL;
+	int argc, retn = -EINVAL;
+	unsigned int lp, cache_size = TSEM_MAGAZINE_SIZE_INTERNAL;
+	enum namespace_argument_type ns_arg;
+	enum tsem_ns_reference ns_ref = TSEM_NS_INITIAL;
+	const struct tsem_context_ops *ops = &tsem_model0_ops;
+
+	if (type == TSEM_CONTROL_EXTERNAL || type == TSEM_CONTROL_EXPORT)
+		cache_size = TSEM_MAGAZINE_SIZE_EXTERNAL;
+
+	if (!arg) {
+		if (type == TSEM_CONTROL_EXTERNAL)
+			return retn;
+		return tsem_ns_create(type, digest, ns_ref, key, cache_size,
+				      ops);
+	}
+
+	argv = argv_split(GFP_KERNEL, arg, &argc);
+	if (!argv)
+		return -ENOMEM;
+
+	for (lp = 0; lp < argc; ++lp) {
+		argp = strchr(argv[lp], '=');
+		if (!argp)
+			goto done;
+		*argp++ = '\0';
+
+		ns_arg = match_string(namespace_arguments,
+				    ARRAY_SIZE(namespace_arguments), argv[lp]);
+		if (ns_arg < 0)
+			goto done;
+
+		switch (ns_arg) {
+		case NS_MODEL:
+			ops = tsem_nsmgr_get(argp);
+			if (!ops)
+				goto done;
+			break;
+		case NS_REF:
+			if (!strcmp(argp, "current"))
+				ns_ref = TSEM_NS_CURRENT;
+			else if (!strcmp(argp, "initial"))
+				ns_ref = TSEM_NS_INITIAL;
+			else
+				goto done;
+			break;
+		case NS_DIGEST:
+			digest = argp;
+			if (!crypto_has_shash(digest, 0, 0))
+				goto done;
+			break;
+		case NS_KEY:
+			key = argp;
+			if (strlen(key) % 2)
+				goto done;
+			break;
+		case NS_CACHE:
+			if (kstrtouint(argp, 0, &cache_size))
+				goto done;
+			if (!cache_size)
+				goto done;
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (type == TSEM_CONTROL_EXTERNAL && !key)
+		goto done;
+
+	retn = tsem_ns_create(type, digest, ns_ref, key, cache_size, ops);
+
+ done:
+	argv_free(argv);
+	return retn;
+}
+
+static void show_creds(struct seq_file *c, char *key, char *term,
+		       struct tsem_COE *cp)
+{
+	tsem_fs_show_field(c, key);
+	tsem_fs_show_key(c, "uid", ",", "%u", cp->uid);
+	tsem_fs_show_key(c, "euid", ",", "%u", cp->euid);
+	tsem_fs_show_key(c, "suid", ",", "%u", cp->suid);
+	tsem_fs_show_key(c, "gid", ",", "%u", cp->gid);
+	tsem_fs_show_key(c, "egid", ",", "%u", cp->egid);
+	tsem_fs_show_key(c, "sgid", ",", "%u", cp->sgid);
+	tsem_fs_show_key(c, "fsuid", ",", "%u", cp->fsuid);
+	tsem_fs_show_key(c, "fsgid", ",", "%u", cp->fsgid);
+	tsem_fs_show_key(c, "capeff", ",", "0x%llx", cp->capeff.value);
+	tsem_fs_show_key(c, "securebits", "}", "%u", cp->securebits);
+
+	seq_puts(c, term);
+}
+
+static void show_event(struct seq_file *c, struct tsem_event *ep)
+{
+	tsem_fs_show_field(c, "event");
+	if (ep->pid)
+		tsem_fs_show_key(c, "pid", ",", "%u", ep->pid);
+	tsem_fs_show_key(c, "context", ",", "%llu", ep->context);
+	tsem_fs_show_key(c, "number", ",", "%llu", ep->event_number);
+	tsem_fs_show_key(c, "process", ",", "%s", ep->comm);
+	tsem_fs_show_key(c, "type", ",", "%s", tsem_names[ep->event]);
+	tsem_fs_show_key(c, "ttd", ",", "%llu", ep->instance);
+	tsem_fs_show_key(c, "p_ttd", ",", "%llu", ep->p_instance);
+	tsem_fs_show_key(c, "task_id", ",", "%*phN", tsem_digestsize(),
+			 ep->task_id);
+	tsem_fs_show_key(c, "p_task_id", ",", "%*phN", tsem_digestsize(),
+			 ep->p_task_id);
+	tsem_fs_show_key(c, "ts", "}, ", "%llu", ep->timestamp);
+
+	tsem_fs_show_field(c, "COE");
+	tsem_fs_show_key(c, "uid", ",", "%u", ep->COE.uid);
+	tsem_fs_show_key(c, "euid", ",", "%u", ep->COE.euid);
+	tsem_fs_show_key(c, "suid", ",", "%u", ep->COE.suid);
+	tsem_fs_show_key(c, "gid", ",", "%u", ep->COE.gid);
+	tsem_fs_show_key(c, "egid", ",", "%u", ep->COE.egid);
+	tsem_fs_show_key(c, "sgid", ",", "%u", ep->COE.sgid);
+	tsem_fs_show_key(c, "fsuid", ",", "%u", ep->COE.fsuid);
+	tsem_fs_show_key(c, "fsgid", ",", "%u", ep->COE.fsgid);
+	tsem_fs_show_key(c, "capeff", "}, ", "0x%llx", ep->COE.capeff.value);
+
+	tsem_fs_show_field(c, tsem_names[ep->event]);
+}
+
+static void show_path(struct seq_file *c, char *key, char *term,
+		      struct tsem_path *path)
+{
+	tsem_fs_show_field(c, key);
+
+	if (path->dev) {
+		tsem_fs_show_field(c, "dev");
+		tsem_fs_show_key(c, "major", ",", "%u", MAJOR(path->dev));
+		tsem_fs_show_key(c, "minor", "}, ", "%u", MINOR(path->dev));
+	}
+
+	if (path->created) {
+		tsem_fs_show_key(c, "owner", ",", "%*phN", tsem_digestsize(),
+				 path->owner);
+		tsem_fs_show_key(c, "instance", ",", "%llu", path->instance);
+	}
+
+	tsem_fs_show_key(c, "pathname", "}", "%s", path->pathname);
+	seq_puts(c, term);
+}
+
+static void show_inode(struct seq_file *c, char *key, char *term,
+		       struct tsem_inode_cell *inode)
+{
+	tsem_fs_show_field(c, key);
+	tsem_fs_show_key(c, "uid", ",", "%u", inode->uid);
+	tsem_fs_show_key(c, "gid", ",", "%u", inode->gid);
+	tsem_fs_show_key(c, "mode", ",", "0%o", inode->mode);
+	tsem_fs_show_key(c, "s_magic", ",", "0x%0x", inode->s_magic);
+	tsem_fs_show_key(c, "s_id", ",", "%s", inode->s_id);
+	tsem_fs_show_key(c, "s_uuid", "}", "%*phN", sizeof(inode->s_uuid),
+			 inode->s_uuid);
+
+	seq_puts(c, term);
+}
+
+static void show_dentry(struct seq_file *c, char *key, char *term,
+			struct tsem_dentry *dentry)
+{
+	tsem_fs_show_field(c, key);
+	if (dentry->have_inode)
+		show_inode(c, "inode", ", ", &dentry->inode);
+
+	show_path(c, "path", "}", &dentry->path);
+
+	seq_puts(c, term);
+}
+
+static void show_file(struct seq_file *c, char *term,
+		      struct tsem_file_args *args)
+{
+	tsem_fs_show_field(c, "file");
+	tsem_fs_show_key(c, "flags", ",", "%u", args->out.flags);
+
+	show_inode(c, "inode", ", ", &args->out.inode);
+	show_path(c, "path", ", ", &args->out.path);
+	tsem_fs_show_key(c, "digest", "}", "%*phN", tsem_digestsize(),
+			 args->out.digest);
+
+	seq_puts(c, term);
+}
+
+static void show_inode_create(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_inode_args *args = &ep->CELL.inode;
+
+	show_event(c, ep);
+
+	show_inode(c, "dir", ", ", &args->out.dir);
+	show_dentry(c, "dentry", ", ", &args->out.dentry);
+	tsem_fs_show_key(c, "mode", "}", "0%o", args->mode);
+}
+
+static void show_inode_remove(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_inode_args *args = &ep->CELL.inode;
+
+	show_event(c, ep);
+
+	show_inode(c, "dir", ", ", &args->out.dir);
+	show_dentry(c, "dentry", "}", &args->out.dentry);
+}
+
+static void show_inode_link(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_inode_args *args = &ep->CELL.inode;
+
+	show_event(c, ep);
+
+	show_dentry(c, "old_dentry", ", ", &args->out.dentry);
+	show_inode(c, "dir", ", ", &args->out.dir);
+	show_dentry(c, "new_dentry", "}", &args->out.new_dentry);
+}
+
+static void show_syslog(struct seq_file *c, struct tsem_event *ep)
+{
+	show_event(c, ep);
+	tsem_fs_show_key(c, "type", "}", "%d", ep->CELL.value);
+}
+
+static void show_settime(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_time_args *args = &ep->CELL.time;
+
+	show_event(c, ep);
+
+	if (args->have_ts) {
+		tsem_fs_show_field(c, "ts");
+		tsem_fs_show_key(c, "seconds", ",", "%d", args->seconds);
+		tsem_fs_show_key(c, "nsecs", args->have_tz ? "}, " : "}",
+				 "%d", args->nsecs);
+	}
+
+	if (args->have_tz) {
+		tsem_fs_show_field(c, "tz");
+		tsem_fs_show_key(c, "minuteswest", ",", "%d",
+				 args->minuteswest);
+		tsem_fs_show_key(c, "dsttime", "}", "%d", args->dsttime);
+	}
+
+	seq_putc(c, '}');
+}
+
+static void show_inode_symlink(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_inode_args *args = &ep->CELL.inode;
+
+	show_event(c, ep);
+
+	show_inode(c, "dir", ", ", &args->out.dir);
+	show_dentry(c, "dentry", ", ", &args->out.dentry);
+	tsem_fs_show_key(c, "old_name", "}", "%s", args->out.old_name);
+}
+
+static void show_inode_mknod(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_inode_args *args = &ep->CELL.inode;
+
+	show_event(c, ep);
+
+	show_inode(c, "dir", ", ", &args->out.dir);
+
+	show_dentry(c, "dentry", ", ", &args->out.dentry);
+	tsem_fs_show_key(c, "mode", ",", "0%o", args->mode);
+	tsem_fs_show_field(c, "dev");
+	tsem_fs_show_key(c, "major", ",", "%u", MAJOR(args->dev));
+	tsem_fs_show_key(c, "minor", "}}", "%u", MINOR(args->dev));
+}
+
+static void show_inode_rename(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_inode_args *args = &ep->CELL.inode;
+
+	show_event(c, ep);
+
+	show_inode(c, "old_dir", ", ", &args->out.dir);
+	show_dentry(c, "old_dentry", ", ", &args->out.dentry);
+	show_inode(c, "new_dir", ", ", &args->out.new_dir);
+	show_dentry(c, "new_dentry", "}", &args->out.new_dentry);
+}
+
+static void show_inode_killpriv(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_inode_args *args = &ep->CELL.inode;
+
+	show_event(c, ep);
+
+	show_dentry(c, "dentry", "}", &args->out.dentry);
+}
+
+static void show_file_open(struct seq_file *c, struct tsem_event *ep)
+{
+	show_event(c, ep);
+
+	show_file(c, "}", &ep->CELL.file);
+}
+
+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);
+
+	if (!args->anonymous)
+		show_file(c, ", ", &args->file);
+	tsem_fs_show_key(c, "prot", ",", "%u", args->prot);
+	tsem_fs_show_key(c, "flags", "}", "%u", args->flags);
+}
+
+static void show_file_ioctl(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_file_args *args = &ep->CELL.file;
+
+	show_event(c, ep);
+
+	show_file(c, ", ", args);
+	tsem_fs_show_key(c, "cmd", "}", "%u", args->cmd);
+}
+
+static void show_socket_info(struct seq_file *c, const char *key, char *term,
+			     struct tsem_socket *args)
+{
+	tsem_fs_show_field(c, key);
+	tsem_fs_show_key(c, "family", ",", "%d", args->family);
+	tsem_fs_show_key(c, "type", ",", "%d", args->type);
+	tsem_fs_show_key(c, "protocol", ",", "%d", args->protocol);
+	tsem_fs_show_key(c, "owner", "}", "%*phN", tsem_digestsize(),
+			 args->owner);
+
+	seq_puts(c, term);
+}
+
+static void show_netlink(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_netlink_args *args = &ep->CELL.netlink;
+
+	show_event(c, ep);
+
+	show_socket_info(c, "sock", ", ", &args->out.sock);
+	tsem_fs_show_key(c, "uid", ",", "%u", args->out.uid);
+	tsem_fs_show_key(c, "gid", ",", "%u", args->out.gid);
+	tsem_fs_show_key(c, "portid", ",", "%u", args->out.portid);
+	tsem_fs_show_key(c, "dst_group", ",", "%u", args->out.dst_group);
+	tsem_fs_show_key(c, "flags", ",", "%u", args->out.flags);
+	tsem_fs_show_key(c, "nsid_set", ",", "%u", args->out.nsid_set);
+	tsem_fs_show_key(c, "nsid", "}", "%d", args->out.nsid);
+}
+
+static void show_ipc_cred(struct seq_file *c, char *key, char *term,
+			  struct tsem_ipc_args *args)
+{
+	tsem_fs_show_field(c, key);
+	tsem_fs_show_key(c, "uid", ",", "%u", args->out.perm.uid);
+	tsem_fs_show_key(c, "gid", ",", "%u", args->out.perm.gid);
+	tsem_fs_show_key(c, "cuid", ",", "%u", args->out.perm.cuid);
+	tsem_fs_show_key(c, "cgid", ",", "%u", args->out.perm.cgid);
+	tsem_fs_show_key(c, "mode", ",", "0%o", args->out.perm.mode);
+	tsem_fs_show_key(c, "owner", "}", "%*phN", tsem_digestsize(),
+			 args->out.owner);
+
+	seq_puts(c, term);
+}
+
+static void show_ipc_permission(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_ipc_args *args = &ep->CELL.ipc;
+
+	show_event(c, ep);
+
+	show_ipc_cred(c, "ipcp", ", ", args);
+	tsem_fs_show_key(c, "flag", "}", "%u", args->perm_flag);
+}
+
+static void show_ipc_shm_value(struct seq_file *c, struct tsem_event *ep,
+			       char *name)
+{
+	struct tsem_ipc_args *args = &ep->CELL.ipc;
+
+	show_event(c, ep);
+
+	show_ipc_cred(c, "perm", ", ", args);
+	tsem_fs_show_key(c, name, "}", "%d", args->perm_flag);
+}
+
+static void show_msg_queue_msgrcv(struct seq_file *c, struct tsem_event *ep)
+
+{
+	struct tsem_ipc_args *args = &ep->CELL.ipc;
+
+	show_event(c, ep);
+
+	show_ipc_cred(c, "perm", ", ", args);
+	tsem_fs_show_key(c, "target", ",", "%*phN", tsem_digestsize(),
+			 args->out.target);
+	tsem_fs_show_key(c, "type", ",", "%ld", args->type);
+	tsem_fs_show_key(c, "mode", "}", "%d", args->value);
+}
+
+static void show_sem_semop(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_ipc_args *args = &ep->CELL.ipc;
+
+	show_event(c, ep);
+
+	show_ipc_cred(c, "perm", ", ", args);
+	tsem_fs_show_key(c, "nsops", ",", "%u", args->nsops);
+	tsem_fs_show_key(c, "alter", "}", "%d", args->value);
+}
+
+static void show_socket_pair(struct seq_file *c, struct tsem_event *ep,
+			     char *first, char *second)
+{
+	struct tsem_socket_args *args = &ep->CELL.socket;
+
+	show_event(c, ep);
+
+	show_socket_info(c, first, ", ", &args->out.socka);
+	show_socket_info(c, second, "}", &args->out.sockb);
+}
+
+static void show_socket_create(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_socket_args *args = &ep->CELL.socket;
+
+	show_event(c, ep);
+
+	tsem_fs_show_key(c, "family", ",", "%u", args->out.socka.family);
+	tsem_fs_show_key(c, "type", ",", "%u", args->out.socka.type);
+	tsem_fs_show_key(c, "protocol", ",", "%u", args->out.socka.protocol);
+	tsem_fs_show_key(c, "kern", "}", "%u", args->out.socka.kern);
+}
+
+static void show_socket_connect_bind(struct seq_file *c, struct tsem_event *ep)
+{
+	struct sockaddr_in *ipv4;
+	struct sockaddr_in6 *ipv6;
+	struct tsem_socket_args *args = &ep->CELL.socket;
+
+	show_event(c, ep);
+
+	show_socket_info(c, "sock", ", ", &args->out.socka);
+
+	tsem_fs_show_field(c, "addr");
+	switch (args->out.socka.family) {
+	case AF_INET:
+		ipv4 = (struct sockaddr_in *) &args->out.ipv4;
+		tsem_fs_show_field(c, "af_inet");
+		tsem_fs_show_key(c, "port", ",", "%u", ipv4->sin_port);
+		tsem_fs_show_key(c, "address", "}}}", "%u",
+				 ipv4->sin_addr.s_addr);
+		break;
+	case AF_INET6:
+		ipv6 = (struct sockaddr_in6 *) &args->out.ipv6;
+		tsem_fs_show_field(c, "af_inet6");
+		tsem_fs_show_key(c, "port", ",", "%u", ipv6->sin6_port);
+		tsem_fs_show_key(c, "flow", ",", "%u", ipv6->sin6_flowinfo);
+		tsem_fs_show_key(c, "scope", ",", "%u", ipv6->sin6_scope_id);
+		tsem_fs_show_key(c, "address", "}}}", "%*phN",
+			 (int) sizeof(ipv6->sin6_addr.in6_u.u6_addr8),
+			 ipv6->sin6_addr.in6_u.u6_addr8);
+		break;
+	case AF_UNIX:
+		tsem_fs_show_field(c, "af_unix");
+		tsem_fs_show_key(c, "address", "}}}", "%s", args->out.path);
+		break;
+	default:
+		tsem_fs_show_field(c, "af_other");
+		tsem_fs_show_key(c, "address", "}}}", "%*phN",
+				 tsem_digestsize(), args->out.mapping);
+		break;
+	}
+}
+
+static void show_socket_accept(struct seq_file *c, struct tsem_event *ep)
+{
+	char *p;
+	int size;
+	struct tsem_socket_args *args = &ep->CELL.socket;
+
+	show_event(c, ep);
+
+	show_socket_info(c, "sock", ", ", &args->out.socka);
+
+	tsem_fs_show_field(c, "addr");
+	switch (args->out.socka.family) {
+	case AF_INET:
+		tsem_fs_show_field(c, "af_inet");
+		tsem_fs_show_key(c, "port", ",", "%u",
+				 args->out.ipv4.sin_port);
+		tsem_fs_show_key(c, "address", "}}}", "%u",
+				 args->out.ipv4.sin_addr);
+		break;
+	case AF_INET6:
+		tsem_fs_show_field(c, "af_inet6");
+		tsem_fs_show_key(c, "port", ",", "%u",
+				 args->out.ipv6.sin6_port);
+		p = args->out.ipv6.sin6_addr.in6_u.u6_addr8;
+		size = sizeof(args->out.ipv6.sin6_addr.in6_u.u6_addr8);
+		tsem_fs_show_key(c, "address", "}}}", "%*phN", size, p);
+		break;
+	case AF_UNIX:
+		tsem_fs_show_field(c, "af_unix");
+		tsem_fs_show_key(c, "address", "}}}", "%s", args->out.path);
+		break;
+	default:
+		tsem_fs_show_field(c, "af_other");
+		tsem_fs_show_key(c, "address", "}}}", "%*phN",
+				 tsem_digestsize(), args->out.mapping);
+		break;
+	}
+}
+
+static void show_socket_value(struct seq_file *c, struct tsem_event *ep,
+			      char *key)
+{
+	struct tsem_socket_args *args = &ep->CELL.socket;
+
+	show_event(c, ep);
+
+	show_socket_info(c, "sock", ", ", &args->out.socka);
+	tsem_fs_show_key(c, key, "}", "%d", args->value);
+}
+
+static void show_socket_msg(struct seq_file *c, struct tsem_event *ep)
+{
+	int size;
+	struct sockaddr_in *ipv4;
+	struct sockaddr_in6 *ipv6;
+	struct tsem_socket_args *args = &ep->CELL.socket;
+
+	show_event(c, ep);
+
+	show_socket_info(c, "sock", args->out.have_addr ? ", " : "}",
+			 &args->out.socka);
+
+	if (args->out.have_addr) {
+		tsem_fs_show_field(c, "addr");
+		switch (args->out.socka.family) {
+		case AF_INET:
+			ipv4 = &args->out.ipv4;
+			tsem_fs_show_field(c, "af_inet");
+			tsem_fs_show_key(c, "port", ",", "%u", ipv4->sin_port);
+			tsem_fs_show_key(c, "address", "}}}", "%u",
+					 ipv4->sin_addr.s_addr);
+			break;
+		case AF_INET6:
+			ipv6 = &args->out.ipv6;
+			size = sizeof(ipv6->sin6_addr.in6_u.u6_addr8);
+			tsem_fs_show_field(c, "af_inet6");
+			tsem_fs_show_key(c, "port", ",", "%u",
+					 ipv6->sin6_port);
+			tsem_fs_show_key(c, "address", "}}}", "%*phN", size,
+					 ipv6->sin6_addr.in6_u.u6_addr8);
+			break;
+		}
+	}
+}
+
+static void show_socket_argument(struct seq_file *c, struct tsem_event *ep)
+{
+	show_event(c, ep);
+
+	show_socket_info(c, "sock", "}", &ep->CELL.socket.out.socka);
+}
+
+static void show_socket_setsockopt(struct seq_file *c, struct tsem_event *ep)
+{
+	show_event(c, ep);
+
+	show_socket_info(c, "sock", ", ", &ep->CELL.socket.out.socka);
+	tsem_fs_show_key(c, "level", ",", "%d", ep->CELL.socket.value);
+	tsem_fs_show_key(c, "optname", "}", "%d", ep->CELL.socket.optname);
+}
+
+static void show_kernel_module_request(struct seq_file *c,
+				       struct tsem_event *ep)
+{
+	struct tsem_kernel_args *args = &ep->CELL.kernel;
+
+	show_event(c, ep);
+	tsem_fs_show_key(c, "kmod_name", "}", "%s", args->out.kmod_name);
+}
+
+static void show_kernel_load_data(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_kernel_args *args = &ep->CELL.kernel;
+
+	show_event(c, ep);
+	tsem_fs_show_key(c, "id", ",", "%d", args->id);
+	tsem_fs_show_key(c, "contents", "}", "%d", args->contents);
+}
+
+static void show_kernel_read_file(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_kernel_args *args = &ep->CELL.kernel;
+
+	show_event(c, ep);
+
+	show_file(c, ", ", &args->out.file);
+	tsem_fs_show_key(c, "id", ",", "%d", args->id);
+	tsem_fs_show_key(c, "contents", "}", "%d", args->contents);
+}
+
+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);
+
+	tsem_fs_show_key(c, "target", ",", "%*phN", tsem_digestsize(),
+			 args->target);
+	tsem_fs_show_key(c, "sig", ",", "%u", args->signal);
+	tsem_fs_show_key(c, "cross_ns", "}", "%u", args->cross_model);
+}
+
+static void show_ptrace_access_check(struct seq_file *c,
+				     struct tsem_event *ep)
+{
+	struct tsem_task_kill_args *args = &ep->CELL.task_kill;
+
+	show_event(c, ep);
+
+	tsem_fs_show_key(c, "child", ", ", "%*phN", tsem_digestsize(),
+			 args->target);
+	tsem_fs_show_key(c, "mode", "}", "%u", args->u.resource);
+}
+
+static void show_task_ptraceme(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_task_kill_args *args = &ep->CELL.task_kill;
+
+	show_event(c, ep);
+
+	tsem_fs_show_key(c, "source", "}", "%*phN", tsem_digestsize(),
+			 args->source);
+}
+
+static void show_capget(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_capability_args *args = &ep->CELL.capability;
+
+	show_event(c, ep);
+
+	tsem_fs_show_key(c, "target", ",", "%*phN", tsem_digestsize(),
+			 args->target);
+	tsem_fs_show_key(c, "effective", ",", "0x%llx", args->effective);
+	tsem_fs_show_key(c, "inheritable", ",", "0x%llx", args->inheritable);
+	tsem_fs_show_key(c, "permitted", "}", "0x%llx", args->permitted);
+}
+
+static void show_capset(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_capability_args *args = &ep->CELL.capability;
+
+	show_event(c, ep);
+
+	tsem_fs_show_key(c, "effective", ",", "0x%llx", args->effective);
+	tsem_fs_show_key(c, "inheritable", ",", "0x%llx", args->inheritable);
+	tsem_fs_show_key(c, "permitted", "}", "0x%llx", args->permitted);
+}
+
+static void show_capable(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_capability_args *args = &ep->CELL.capability;
+
+	show_event(c, ep);
+
+	tsem_fs_show_key(c, "cap", ",", "%d", args->cap);
+	tsem_fs_show_key(c, "opts", "}", "%u", args->opts);
+}
+
+static void show_task_setpgid(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_task_kill_args *args = &ep->CELL.task_kill;
+
+	show_event(c, ep);
+
+	tsem_fs_show_key(c, "task", ",", "%*phN", tsem_digestsize(),
+			 args->target);
+	tsem_fs_show_key(c, "source", "}", "%*phN", tsem_digestsize(),
+			 args->source);
+}
+
+static void show_task_getpgid(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_task_kill_args *args = &ep->CELL.task_kill;
+
+	show_event(c, ep);
+
+	tsem_fs_show_key(c, "task", "}", "%*phN", tsem_digestsize(),
+			 args->target);
+}
+
+static void show_task_nice(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_task_kill_args *args = &ep->CELL.task_kill;
+
+	show_event(c, ep);
+
+	tsem_fs_show_key(c, "task", ",", "%*phN", tsem_digestsize(),
+			 args->target);
+	tsem_fs_show_key(c, "nice", "}", "%d", args->u.value);
+}
+
+static void show_task_prlimit(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_task_prlimit_args *args = &ep->CELL.task_prlimit;
+
+	show_event(c, ep);
+
+	show_creds(c, "cred", ", ", &args->out.cred);
+	show_creds(c, "tcred", ", ", &args->out.tcred);
+	tsem_fs_show_key(c, "flags", "}", "%d", args->flags);
+}
+
+static void show_task_setrlimit(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_task_kill_args *args = &ep->CELL.task_kill;
+
+	show_event(c, ep);
+
+	tsem_fs_show_key(c, "task", ",", "%*phN", tsem_digestsize(),
+			 args->target);
+	tsem_fs_show_field(c, "new_rlim");
+	tsem_fs_show_key(c, "resource", ",", "%u", args->u.resource);
+	tsem_fs_show_key(c, "current", ",", "%llu", args->cur);
+	tsem_fs_show_key(c, "max", "}", "%llu", args->max);
+	seq_putc(c, '}');
+}
+
+static void show_task_prctl(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_task_prctl_args *args = &ep->CELL.task_prctl;
+
+	show_event(c, ep);
+
+	tsem_fs_show_key(c, "option", ",", "%d", args->option);
+	tsem_fs_show_key(c, "arg2", ",", "%llu", args->arg2);
+	tsem_fs_show_key(c, "arg3", ",", "%llu", args->arg3);
+	tsem_fs_show_key(c, "arg4", ",", "%llu", args->arg4);
+	tsem_fs_show_key(c, "arg5", "}", "%llu", args->arg5);
+}
+
+static void show_task_value(struct seq_file *c, struct tsem_event *ep,
+			    char *key)
+{
+	struct tsem_task_kill_args *args = &ep->CELL.task_kill;
+
+	show_event(c, ep);
+
+	tsem_fs_show_key(c, "task", ",", "%*phN", tsem_digestsize(),
+			 args->target);
+	tsem_fs_show_key(c, key, "}", "%d", args->u.value);
+}
+
+static void show_inode_getattr(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_inode_attr_args *args = &ep->CELL.inode_attr;
+
+	show_event(c, ep);
+
+	show_dentry(c, "path", "}", &args->out.dentry);
+}
+
+static void show_inode_setattr(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_inode_attr_args *args = &ep->CELL.inode_attr;
+
+	show_event(c, ep);
+
+	show_dentry(c, "dentry", ", ", &args->out.dentry);
+	tsem_fs_show_field(c, "attr");
+	tsem_fs_show_key(c, "valid", ",", "%u", args->out.valid);
+	tsem_fs_show_key(c, "mode", ",", "0%o", args->out.mode);
+	tsem_fs_show_key(c, "uid", ",", "%u", args->out.uid);
+	tsem_fs_show_key(c, "gid", ",", "%u", args->out.gid);
+	tsem_fs_show_key(c, "size", "}", "%lu", args->out.size);
+	seq_putc(c, '}');
+}
+
+static void show_inode_setxattr(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_inode_xattr_args *args = &ep->CELL.inode_xattr;
+
+	show_event(c, ep);
+
+	show_dentry(c, "dentry", ", ", &args->out.dentry);
+	tsem_fs_show_key(c, "name", ",", "%s", args->out.name);
+	tsem_fs_show_key(c, "value", ",", "%s", args->out.encoded_value);
+	tsem_fs_show_key(c, "flags", "}", "%d", args->out.flags);
+}
+
+static void show_inode_getxattr(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_inode_xattr_args *args = &ep->CELL.inode_xattr;
+
+	show_event(c, ep);
+
+	show_dentry(c, "dentry", ", ", &args->out.dentry);
+	tsem_fs_show_key(c, "name", "}", "%s", args->out.name);
+}
+
+static void show_inode_listxattr(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_inode_xattr_args *args = &ep->CELL.inode_xattr;
+
+	show_event(c, ep);
+
+	show_dentry(c, "dentry", "}", &args->out.dentry);
+}
+
+static void show_key_alloc(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_key_args *args = &ep->CELL.key;
+
+	show_event(c, ep);
+
+	show_creds(c, "cred", ", ", &args->out.cred);
+	tsem_fs_show_key(c, "flags", "}", "%llu", args->flags);
+}
+
+static void show_key_permission(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_key_args *args = &ep->CELL.key;
+
+	show_event(c, ep);
+
+	tsem_fs_show_field(c, "key_ref");
+	tsem_fs_show_key(c, "possessed", ",", "%u", args->out.possessed);
+	tsem_fs_show_key(c, "uid", ",", "%u", args->out.uid);
+	tsem_fs_show_key(c, "gid", ",", "%u", args->out.gid);
+	tsem_fs_show_key(c, "flags", "}, ", "%lu", args->out.flags);
+	show_creds(c, "cred", ", ", &args->out.cred);
+	tsem_fs_show_key(c, "perm", "}", "%u", args->out.perm);
+}
+
+static void show_sb_mount(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_sb_args *args = &ep->CELL.sb;
+
+	show_event(c, ep);
+
+	if (args->out.dev_name)
+		tsem_fs_show_key(c, "dev_name", ",", "%s", args->out.dev_name);
+
+	show_path(c, "path", ", ", &args->out.path);
+
+	if (args->out.type)
+		tsem_fs_show_key(c, "type", ",", "%s", args->out.type);
+
+	tsem_fs_show_key(c, "flags", "}", "%lu", args->flags);
+}
+
+static void show_sb_umount(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_sb_args *args = &ep->CELL.sb;
+
+	show_event(c, ep);
+
+	show_dentry(c, "mnt", ", ", &args->out.dentry);
+	tsem_fs_show_key(c, "flags", "}", "%d", args->flags);
+}
+
+static void show_sb_remount(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_sb_args *args = &ep->CELL.sb;
+
+	show_event(c, ep);
+
+	tsem_fs_show_field(c, "sb");
+	show_dentry(c, "dentry", ", ", &args->out.dentry);
+	tsem_fs_show_key(c, "fstype", ",", "%s", args->out.type);
+	tsem_fs_show_key(c, "s_flags", "}", "%lu", args->flags);
+	seq_putc(c, '}');
+}
+
+static void show_sb_statfs(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_sb_args *args = &ep->CELL.sb;
+
+	show_event(c, ep);
+
+	show_dentry(c, "dentry", "}", &args->out.dentry);
+}
+
+static void show_move_path(struct seq_file *c, struct tsem_event *ep,
+			   char *path1, char *path2)
+{
+	struct tsem_sb_args *args = &ep->CELL.sb;
+
+	show_event(c, ep);
+
+	show_path(c, path1, ", ", &args->out.path);
+	show_path(c, path2, "}", &args->out.path2);
+}
+
+static void show_quotactl(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_quota_args *args = &ep->CELL.quota;
+
+	show_event(c, ep);
+
+	tsem_fs_show_key(c, "cmds", ",", "%d", args->cmds);
+	tsem_fs_show_key(c, "type", ",", "%d", args->type);
+	tsem_fs_show_key(c, "id", ",", "%d", args->id);
+
+	tsem_fs_show_field(c, "sb");
+	show_dentry(c, "dentry", ", ", &args->out.dentry);
+	tsem_fs_show_key(c, "fstype", ",", "%s", args->out.fstype);
+	tsem_fs_show_key(c, "s_flags", "}", "%d", args->out.s_flags);
+	seq_putc(c, '}');
+}
+
+static void show_quotaon(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_quota_args *args = &ep->CELL.quota;
+
+	show_event(c, ep);
+
+	show_dentry(c, "dentry", "}", &args->out.dentry);
+}
+
+static void show_bpf(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_bpf_args *args = &ep->CELL.bpf;
+
+	show_event(c, ep);
+
+	tsem_fs_show_key(c, "cmd", ",", "%d", args->bpf.cmd);
+	tsem_fs_show_field(c, "attr");
+	tsem_fs_show_key(c, "size", "}", "%u", args->bpf.size);
+	seq_putc(c, '}');
+}
+
+static void show_bpf_map(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_bpf_args *args = &ep->CELL.bpf;
+
+	show_event(c, ep);
+
+	tsem_fs_show_field(c, "map");
+	tsem_fs_show_key(c, "map_type", "}, ", "%d", args->map.map_type);
+	tsem_fs_show_key(c, "fmode", "}", "%u", args->map.fmode);
+}
+
+static void show_bpf_prog(struct seq_file *c, struct tsem_event *ep)
+{
+	struct tsem_bpf_args *args = &ep->CELL.bpf;
+
+	show_event(c, ep);
+
+	tsem_fs_show_field(c, "prog");
+	tsem_fs_show_key(c, "type", ",", "%d", args->prog.type);
+	tsem_fs_show_key(c, "attach_type", "}", "%d", args->prog.attach_type);
+	seq_putc(c, '}');
+}
+
+static void show_event_generic(struct seq_file *c, struct tsem_event *ep)
+{
+	show_event(c, ep);
+	seq_putc(c, '}');
+}
+
+static void *trajectory_start(struct seq_file *c, loff_t *pos)
+{
+	struct list_head *end;
+	struct tsem_model *model = tsem_model(current);
+
+	spin_lock(&model->trajectory_lock);
+	end = model->trajectory_list.prev;
+	spin_unlock(&model->trajectory_lock);
+
+	mutex_lock(&model->trajectory_end_mutex);
+	model->trajectory_end = end;
+
+	return seq_list_start(&model->trajectory_list, *pos);
+}
+
+static void *trajectory_next(struct seq_file *c, void *p, loff_t *pos)
+{
+	struct list_head *next = ((struct list_head *) p)->next;
+	struct tsem_model *model = tsem_model(current);
+
+	if (!model->trajectory_end) {
+		++*pos;
+		return NULL;
+	}
+
+	if (next == model->trajectory_end)
+		model->trajectory_end = NULL;
+
+	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_end_mutex);
+}
+
+static int trajectory_show(struct seq_file *c, void *trajectory)
+{
+	struct tsem_event *ep;
+
+	ep = list_entry(trajectory, struct tsem_event, list);
+
+	seq_putc(c, '{');
+	tsem_fs_show_trajectory(c, ep);
+	seq_puts(c, "}\n");
+
+	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 *trajectory_count_start(struct seq_file *c, loff_t *pos)
+{
+	struct list_head *end;
+	struct tsem_model *model = tsem_model(current);
+
+	spin_lock(&model->point_lock);
+	end = model->point_list.prev;
+	spin_unlock(&model->point_lock);
+
+	mutex_lock(&model->point_end_mutex);
+	model->point_end = end;
+
+	return seq_list_start(&model->point_list, *pos);
+}
+
+static void *trajectory_count_next(struct seq_file *c, void *p, loff_t *pos)
+{
+	struct list_head *next = ((struct list_head *) p)->next;
+	struct tsem_model *model = tsem_model(current);
+
+	if (!model->point_end) {
+		++*pos;
+		return NULL;
+	}
+
+	if (next == model->point_end)
+		model->point_end = NULL;
+
+	return seq_list_next(p, &model->point_list, pos);
+}
+
+static void trajectory_count_stop(struct seq_file *c, void *pos)
+{
+	struct tsem_model *model = tsem_model(current);
+
+	mutex_unlock(&model->point_end_mutex);
+}
+
+static int trajectory_count_show(struct seq_file *c, void *point)
+{
+	struct tsem_event_point *pt;
+
+	pt = list_entry(point, struct tsem_event_point, list);
+	if (!pt->valid)
+		return 0;
+
+	seq_printf(c, "%llu\n", pt->count);
+	return 0;
+}
+
+static const struct seq_operations trajectory_count_seqops = {
+	.start = trajectory_count_start,
+	.next = trajectory_count_next,
+	.stop = trajectory_count_stop,
+	.show = trajectory_count_show
+};
+
+static int trajectory_count_open(struct inode *inode, struct file *file)
+{
+	if (!can_access_fs())
+		return -EACCES;
+	return seq_open(file, &trajectory_count_seqops);
+}
+
+static const struct file_operations trajectory_count_ops = {
+	.open = trajectory_count_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+static void *trajectory_point_start(struct seq_file *c, loff_t *pos)
+{
+	struct list_head *end;
+	struct tsem_model *model = tsem_model(current);
+
+	spin_lock(&model->point_lock);
+	end = model->point_list.prev;
+	spin_unlock(&model->point_lock);
+
+	mutex_lock(&model->point_end_mutex);
+	model->point_end = end;
+
+	return seq_list_start(&model->point_list, *pos);
+}
+
+static void *trajectory_point_next(struct seq_file *c, void *p, loff_t *pos)
+{
+	struct list_head *next = ((struct list_head *) p)->next;
+	struct tsem_model *model = tsem_model(current);
+
+	if (!model->point_end) {
+		++*pos;
+		return NULL;
+	}
+
+	if (next == model->point_end)
+		model->point_end = NULL;
+
+	return seq_list_next(p, &model->point_list, pos);
+}
+
+static void trajectory_point_stop(struct seq_file *c, void *pos)
+{
+	struct tsem_model *model = tsem_model(current);
+
+	mutex_unlock(&model->point_end_mutex);
+}
+
+static int trajectory_point_show(struct seq_file *c, void *point)
+{
+	struct tsem_event_point *pt;
+
+	pt = list_entry(point, struct tsem_event_point, list);
+	if (!pt->valid)
+		return 0;
+
+	seq_printf(c, "%*phN\n", tsem_digestsize(), pt->point);
+	return 0;
+}
+
+static const struct seq_operations trajectory_point_seqops = {
+	.start = trajectory_point_start,
+	.next = trajectory_point_next,
+	.stop = trajectory_point_stop,
+	.show = trajectory_point_show
+};
+
+static int trajectory_point_open(struct inode *inode, struct file *file)
+{
+	if (!can_access_fs())
+		return -EACCES;
+	return seq_open(file, &trajectory_point_seqops);
+}
+
+static const struct file_operations trajectory_point_ops = {
+	.open = trajectory_point_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+static int open_control(struct inode *inode, struct file *filp)
+{
+	if (!capable(CAP_MAC_ADMIN))
+		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[128];
+	ssize_t retn = -EINVAL;
+	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, ' ');
+	if (arg != NULL) {
+		*arg = '\0';
+		++arg;
+	}
+
+	type = match_string(control_commands, ARRAY_SIZE(control_commands),
+			    cmdbufr);
+	if (type < 0)
+		goto done;
+
+	switch (type) {
+	case TSEM_CONTROL_EXTERNAL:
+	case TSEM_CONTROL_INTERNAL:
+	case TSEM_CONTROL_EXPORT:
+		retn = config_namespace(type, arg);
+		break;
+	case TSEM_CONTROL_ENFORCE:
+	case TSEM_CONTROL_SEAL:
+		retn = config_context(type, cmdbufr);
+		break;
+	case TSEM_CONTROL_TRUSTED:
+	case TSEM_CONTROL_UNTRUSTED:
+		retn = config_COE(type, arg);
+		break;
+	case TSEM_CONTROL_MAP_STATE:
+	case TSEM_CONTROL_MAP_PSEUDONYM:
+	case TSEM_CONTROL_MAP_BASE:
+		retn = config_point(type, arg);
+		break;
+	case TSEM_CONTROL_LOCK:
+		retn = tsem_nsmgr_lock(false);
+		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 list_head *end;
+	struct tsem_model *model = tsem_model(current);
+
+	spin_lock(&model->forensics_lock);
+	end = model->forensics_list.prev;
+	spin_unlock(&model->forensics_lock);
+
+	mutex_lock(&model->forensics_end_mutex);
+	model->forensics_end = end;
+
+	return seq_list_start(&model->forensics_list, *pos);
+}
+
+static void *forensics_next(struct seq_file *c, void *p, loff_t *pos)
+{
+	struct list_head *next = ((struct list_head *) p)->next;
+	struct tsem_model *model = tsem_model(current);
+
+	if (!model->forensics_end) {
+		++*pos;
+		return NULL;
+	}
+
+	if (next == model->forensics_end)
+		model->forensics_end = NULL;
+
+	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_end_mutex);
+}
+
+static int forensics_show(struct seq_file *c, void *event)
+{
+	struct tsem_event *ep;
+
+	ep = list_entry(event, struct tsem_event, list);
+
+	seq_putc(c, '{');
+	tsem_fs_show_trajectory(c, ep);
+	seq_puts(c, "}\n");
+
+	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 void *forensics_point_start(struct seq_file *c, loff_t *pos)
+{
+	struct list_head *end;
+	struct tsem_model *model = tsem_model(current);
+
+	spin_lock(&model->point_lock);
+	end = model->point_list.prev;
+	spin_unlock(&model->point_lock);
+
+	mutex_lock(&model->point_end_mutex);
+	model->point_end = end;
+
+	return seq_list_start(&model->point_list, *pos);
+}
+
+static void *forensics_point_next(struct seq_file *c, void *p, loff_t *pos)
+{
+	struct list_head *next = ((struct list_head *) p)->next;
+	struct tsem_model *model = tsem_model(current);
+
+	if (!model->point_end) {
+		++*pos;
+		return NULL;
+	}
+
+	if (next == model->point_end)
+		model->point_end = NULL;
+
+	return seq_list_next(p, &model->point_list, pos);
+}
+
+static void forensics_point_stop(struct seq_file *c, void *pos)
+{
+	struct tsem_model *model = tsem_model(current);
+
+	mutex_unlock(&model->point_end_mutex);
+}
+
+static int forensics_point_show(struct seq_file *c, void *point)
+{
+	struct tsem_event_point *pt;
+
+	pt = list_entry(point, struct tsem_event_point, list);
+	if (pt->valid)
+		return 0;
+
+	seq_printf(c, "%*phN\n", tsem_digestsize(), pt->point);
+	return 0;
+}
+
+static const struct seq_operations forensics_point_seqops = {
+	.start = forensics_point_start,
+	.next = forensics_point_next,
+	.stop = forensics_point_stop,
+	.show = forensics_point_show
+};
+
+static int forensics_point_open(struct inode *inode, struct file *file)
+{
+	if (!can_access_fs())
+		return -EACCES;
+	return seq_open(file, &forensics_point_seqops);
+}
+
+static const struct file_operations forensics_point_ops = {
+	.open = forensics_point_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+static void *forensics_count_start(struct seq_file *c, loff_t *pos)
+{
+	struct list_head *end;
+	struct tsem_model *model = tsem_model(current);
+
+	spin_lock(&model->point_lock);
+	end = model->point_list.prev;
+	spin_unlock(&model->point_lock);
+
+	mutex_lock(&model->point_end_mutex);
+	model->point_end = end;
+
+	return seq_list_start(&model->point_list, *pos);
+}
+
+static void *forensics_count_next(struct seq_file *c, void *p, loff_t *pos)
+{
+	struct list_head *next = ((struct list_head *) p)->next;
+	struct tsem_model *model = tsem_model(current);
+
+	if (!model->point_end) {
+		++*pos;
+		return NULL;
+	}
+
+	if (next == model->point_end)
+		model->point_end = NULL;
+
+	return seq_list_next(p, &model->point_list, pos);
+}
+
+static void forensics_count_stop(struct seq_file *c, void *pos)
+{
+	struct tsem_model *model = tsem_model(current);
+
+	mutex_unlock(&model->point_end_mutex);
+}
+
+static int forensics_count_show(struct seq_file *c, void *point)
+{
+	struct tsem_event_point *pt;
+
+	pt = list_entry(point, struct tsem_event_point, list);
+	if (pt->valid)
+		return 0;
+
+	seq_printf(c, "%llu\n", pt->count);
+	return 0;
+}
+
+static const struct seq_operations forensics_count_seqops = {
+	.start = forensics_count_start,
+	.next = forensics_count_next,
+	.stop = forensics_count_stop,
+	.show = forensics_count_show
+};
+
+static int forensics_count_open(struct inode *inode, struct file *file)
+{
+	if (!can_access_fs())
+		return -EACCES;
+	return seq_open(file, &forensics_count_seqops);
+}
+
+static const struct file_operations forensics_count_ops = {
+	.open = forensics_count_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", tsem_digestsize(), 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_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", tsem_digestsize(), 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", tsem_digestsize(), 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 __poll_t export_poll(struct file *file, struct poll_table_struct *wait)
+{
+	struct tsem_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(CAP_MAC_ADMIN))
+		return -EACCES;
+	return single_open(file, &tsem_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,
+};
+
+/**
+ * tsem_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/kernel/security/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
+ *	   the pointer with an encoded code will be returned.
+ */
+struct dentry *tsem_fs_create_external(const char *name)
+{
+	struct dentry *dentry;
+
+	dentry = securityfs_create_file(name, 0400, external_tma, NULL,
+					&export_ops);
+	if (!IS_ERR(dentry))
+		tsem_inode(dentry->d_inode)->status = TSEM_INODE_CONTROL_PLANE;
+	return dentry;
+}
+
+/**
+ * tsem_fs_show_trajectory() - Generate the output of a security event.
+ * @sf: A pointer to the seq_file structure to which output will
+ *      be set.
+ * @ep: A pointer to the event description that is to be output.
+ *
+ * This function is used to generate a record that will be output to
+ * the pseudo-file that outputs the security events for the
+ * domain being modeled.
+ */
+void tsem_fs_show_trajectory(struct seq_file *c, struct tsem_event *ep)
+{
+	if (ep->no_params)
+		show_event_generic(c, ep);
+
+	switch (ep->event) {
+	case TSEM_SYSLOG:
+		show_syslog(c, ep);
+		break;
+	case TSEM_SETTIME:
+		show_settime(c, ep);
+		break;
+	case TSEM_NETLINK_SEND:
+		show_netlink(c, ep);
+		break;
+	case TSEM_IPC_PERMISSION:
+		show_ipc_permission(c, ep);
+		break;
+	case TSEM_SHM_ASSOCIATE:
+	case TSEM_SHM_SHMAT:
+		show_ipc_shm_value(c, ep, "shmflg");
+		break;
+	case TSEM_SHM_SHMCTL:
+	case TSEM_SEM_SEMCTL:
+	case TSEM_MSG_QUEUE_MSGCTL:
+		show_ipc_shm_value(c, ep, "cmd");
+		break;
+	case TSEM_SEM_SEMOP:
+		show_sem_semop(c, ep);
+		break;
+	case TSEM_SEM_ASSOCIATE:
+		show_ipc_shm_value(c, ep, "semflg");
+		break;
+	case TSEM_MSG_QUEUE_ASSOCIATE:
+	case TSEM_MSG_QUEUE_MSGSND:
+		show_ipc_shm_value(c, ep, "msqflg");
+		break;
+	case TSEM_MSG_QUEUE_MSGRCV:
+		show_msg_queue_msgrcv(c, ep);
+		break;
+	case TSEM_INODE_CREATE:
+	case TSEM_INODE_MKDIR:
+		show_inode_create(c, ep);
+		break;
+	case TSEM_INODE_RMDIR:
+	case TSEM_INODE_UNLINK:
+		show_inode_remove(c, ep);
+		break;
+	case TSEM_INODE_LINK:
+		show_inode_link(c, ep);
+		break;
+	case TSEM_INODE_SYMLINK:
+		show_inode_symlink(c, ep);
+		break;
+	case TSEM_INODE_MKNOD:
+		show_inode_mknod(c, ep);
+		break;
+	case TSEM_INODE_RENAME:
+		show_inode_rename(c, ep);
+		break;
+	case TSEM_INODE_KILLPRIV:
+		show_inode_killpriv(c, ep);
+		break;
+	case TSEM_FILE_OPEN:
+	case TSEM_FILE_RECEIVE:
+		show_file_open(c, ep);
+		break;
+	case TSEM_MMAP_FILE:
+		show_mmap(c, ep);
+		break;
+	case TSEM_FILE_IOCTL:
+	case TSEM_FILE_LOCK:
+	case TSEM_FILE_FCNTL:
+		show_file_ioctl(c, ep);
+		break;
+	case TSEM_UNIX_STREAM_CONNECT:
+	case TSEM_UNIX_MAY_SEND:
+		show_socket_pair(c, ep, "sock", "other");
+		break;
+	case TSEM_SOCKET_SOCKETPAIR:
+		show_socket_pair(c, ep, "socka", "sockb");
+		break;
+	case TSEM_SOCKET_CREATE:
+		show_socket_create(c, ep);
+		break;
+	case TSEM_SOCKET_CONNECT:
+	case TSEM_SOCKET_BIND:
+		show_socket_connect_bind(c, ep);
+		break;
+	case TSEM_SOCKET_SENDMSG:
+	case TSEM_SOCKET_RECVMSG:
+		show_socket_msg(c, ep);
+		break;
+	case TSEM_SOCKET_GETSOCKNAME:
+	case TSEM_SOCKET_GETPEERNAME:
+	case TSEM_TUN_DEV_ATTACH_QUEUE:
+		show_socket_argument(c, ep);
+		break;
+	case TSEM_SOCKET_SETSOCKOPT:
+		show_socket_setsockopt(c, ep);
+		break;
+	case TSEM_SOCKET_ACCEPT:
+		show_socket_accept(c, ep);
+		break;
+	case TSEM_SOCKET_LISTEN:
+		show_socket_value(c, ep, "backlog");
+		break;
+	case TSEM_SOCKET_SHUTDOWN:
+		show_socket_value(c, ep, "how");
+		break;
+	case TSEM_KERNEL_MODULE_REQUEST:
+		show_kernel_module_request(c, ep);
+		break;
+	case TSEM_KERNEL_LOAD_DATA:
+		show_kernel_load_data(c, ep);
+		break;
+	case TSEM_KERNEL_READ_FILE:
+		show_kernel_read_file(c, ep);
+		break;
+	case TSEM_TASK_KILL:
+		show_task_kill(c, ep);
+		break;
+	case TSEM_PTRACE_ACCESS_CHECK:
+		show_ptrace_access_check(c, ep);
+		break;
+	case TSEM_PTRACE_TRACEME:
+		show_task_ptraceme(c, ep);
+		break;
+	case TSEM_CAPGET:
+		show_capget(c, ep);
+		break;
+	case TSEM_CAPSET:
+		show_capset(c, ep);
+		break;
+	case TSEM_CAPABLE:
+		show_capable(c, ep);
+		break;
+	case TSEM_TASK_SETPGID:
+		show_task_setpgid(c, ep);
+		break;
+	case TSEM_TASK_GETPGID:
+	case TSEM_TASK_GETSID:
+	case TSEM_TASK_GETIOPRIO:
+	case TSEM_TASK_SETSCHEDULER:
+	case TSEM_TASK_GETSCHEDULER:
+		show_task_getpgid(c, ep);
+		break;
+	case TSEM_TASK_SETNICE:
+		show_task_nice(c, ep);
+		break;
+	case TSEM_TASK_SETIOPRIO:
+		show_task_value(c, ep, "ioprio");
+		break;
+	case TSEM_TASK_PRLIMIT:
+		show_task_prlimit(c, ep);
+		break;
+	case TSEM_TASK_SETRLIMIT:
+		show_task_setrlimit(c, ep);
+		break;
+	case TSEM_TASK_PRCTL:
+		show_task_prctl(c, ep);
+		break;
+	case TSEM_INODE_GETATTR:
+		show_inode_getattr(c, ep);
+		break;
+	case TSEM_INODE_SETATTR:
+		show_inode_setattr(c, ep);
+		break;
+	case TSEM_INODE_SETXATTR:
+		show_inode_setxattr(c, ep);
+		break;
+	case TSEM_INODE_GETXATTR:
+	case TSEM_INODE_REMOVEXATTR:
+		show_inode_getxattr(c, ep);
+		break;
+	case TSEM_INODE_LISTXATTR:
+		show_inode_listxattr(c, ep);
+		break;
+	case TSEM_KEY_ALLOC:
+		show_key_alloc(c, ep);
+		break;
+	case TSEM_KEY_PERMISSION:
+		show_key_permission(c, ep);
+		break;
+	case TSEM_SB_MOUNT:
+		show_sb_mount(c, ep);
+		break;
+	case TSEM_SB_UMOUNT:
+		show_sb_umount(c, ep);
+		break;
+	case TSEM_SB_REMOUNT:
+		show_sb_remount(c, ep);
+		break;
+	case TSEM_SB_STATFS:
+		show_sb_statfs(c, ep);
+		break;
+	case TSEM_SB_PIVOTROOT:
+		show_move_path(c, ep, "old_path", "new_path");
+		break;
+	case TSEM_MOVE_MOUNT:
+		show_move_path(c, ep, "from_path", "to_path");
+		break;
+	case TSEM_QUOTACTL:
+		show_quotactl(c, ep);
+		break;
+	case TSEM_QUOTA_ON:
+		show_quotaon(c, ep);
+		break;
+	case TSEM_BPF:
+		show_bpf(c, ep);
+		break;
+	case TSEM_BPF_MAP:
+		show_bpf_map(c, ep);
+		break;
+	case TSEM_BPF_PROG:
+		show_bpf_prog(c, ep);
+		break;
+	default:
+		break;
+	}
+}
+
+/**
+ * tesm_fs_show_field() - Output a JSON field description
+ * @sf: A pointer to the seq_file structure that the field description
+ *	is to be written to.
+ * @f:  A pointer to null terminated character buffer containing the
+ *      name of the field to encode
+ *
+ * This function is used to generate a JSON field description that
+ * is used to name a sequence of key/value pairs describing the
+ * characteristcis of the field.
+ */
+void tsem_fs_show_field(struct seq_file *c, const char *field)
+{
+	seq_printf(c, "\"%s\": {", field);
+}
+
+/**
+ * tesm_fs_tsem_fs_show_key() - Output a JSON key/value pair
+ * @sf: A pointer to the seq_file structure that the field description
+ *	is to be written to.
+ * @key: A pointer to the null-terminated character buffer containing
+ *	 the key description.
+ * @term: A pointer to a null-terminated character buffer containing
+ *	  the string that is to be used for terminating the key/value
+ *	  pair.
+ * @fmt: The printf format that is to be used for formatting the
+ *	 value of the key.
+ *
+ * This function is a variadic function that is used to encode a
+ * JSON key/value pair that provides one of characteristics of an
+ * event description field.
+ */
+void tsem_fs_show_key(struct seq_file *c, char *key, char *term, char *fmt,
+		      ...)
+{
+	va_list args;
+
+	seq_printf(c, "\"%s\": \"", key);
+
+	va_start(args, fmt);
+	seq_vprintf(c, fmt, args);
+	va_end(args);
+
+	if (term[0] == ',')
+		seq_printf(c, "\"%s ", term);
+	else
+		seq_printf(c, "\"%s", term);
+}
+
+static bool _init_inode(struct dentry *dp)
+{
+	if (IS_ERR(dp))
+		return false;
+
+	tsem_inode(dp->d_inode)->status = TSEM_INODE_CONTROL_PLANE;
+	return true;
+}
+
+/**
+ * tesm_fs_init() - Initialize the TSEM control filesystem heirarchy
+ *
+ * This function is called as part of the TSEM LSM initialization
+ * process.  The purpose of this function is to create the TSEM
+ * control plane, based on the securityfs filesystem, by creating the
+ * /sys/kernel/security/tsem directory and populating that directory
+ * with the control plane files and internal TMA model information
+ * files.  The /sys/kernel/security/tsem/ExternalTMA directory is
+ * also created.  This directory will be used to hold the modeling
+ * domain specific files that will emit the security event descriptions
+ * for the domain.
+ *
+ * Return: If filesystem initialization is successful a return code of 0
+ *	   is returned.  A negative return value is returned if an error
+ *	   is encountered.
+ */
+int __init tsem_fs_init(void)
+{
+	int retn = -1;
+
+	tsem_dir = securityfs_create_dir("tsem", NULL);
+	if (!_init_inode(tsem_dir))
+		goto done;
+
+	control = securityfs_create_file("control", 0200, tsem_dir, NULL,
+					 &control_ops);
+	if (!_init_inode(control))
+		goto err;
+
+	id = securityfs_create_file("id", 0400, tsem_dir, NULL, &id_ops);
+	if (!_init_inode(id))
+		goto err;
+
+	aggregate = securityfs_create_file("aggregate", 0400, tsem_dir, NULL,
+					   &aggregate_ops);
+	if (!_init_inode(aggregate))
+		goto err;
+
+	internal_tma = securityfs_create_dir("internal_tma", tsem_dir);
+	if (!_init_inode(internal_tma))
+		goto err;
+
+	model = securityfs_create_dir("model0", internal_tma);
+	if (!_init_inode(model))
+		goto err;
+
+	forensics = securityfs_create_file("forensics", 0400, model, NULL,
+					   &forensics_ops);
+	if (!_init_inode(forensics))
+		goto err;
+
+	forensics_counts = securityfs_create_file("forensics_counts", 0400,
+						 model, NULL,
+						 &forensics_count_ops);
+	if (!_init_inode(forensics_counts))
+		goto err;
+
+	forensics_coeff = securityfs_create_file("forensics_coefficients",
+						 0400, model, NULL,
+						 &forensics_point_ops);
+	if (!_init_inode(forensics_coeff))
+		goto err;
+
+	trajectory = securityfs_create_file("trajectory", 0400, model, NULL,
+					     &trajectory_ops);
+	if (!_init_inode(trajectory))
+		goto err;
+
+	trajectory_counts = securityfs_create_file("trajectory_counts", 0400,
+						   model, NULL,
+						   &trajectory_count_ops);
+	if (!_init_inode(trajectory_counts))
+		goto err;
+
+	trajectory_coeff = securityfs_create_file("trajectory_coefficients",
+						  0400, model, NULL,
+						  &trajectory_point_ops);
+	if (!_init_inode(trajectory_coeff))
+		goto err;
+
+	measurement = securityfs_create_file("measurement", 0400,
+						  model, NULL,
+						  &measurement_ops);
+	if (!_init_inode(measurement))
+		goto err;
+
+	state = securityfs_create_file("state", 0400, model, NULL,
+					&state_ops);
+	if (!_init_inode(state))
+		goto err;
+
+	external_tma = securityfs_create_dir("external_tma", tsem_dir);
+	if (!_init_inode(external_tma))
+		goto err;
+
+	retn = 0;
+
+ done:
+	return retn;
+
+ err:
+	securityfs_remove(tsem_dir);
+	securityfs_remove(control);
+	securityfs_remove(id);
+	securityfs_remove(aggregate);
+	securityfs_remove(internal_tma);
+	securityfs_remove(model);
+	securityfs_remove(forensics);
+	securityfs_remove(forensics_counts);
+	securityfs_remove(forensics_coeff);
+	securityfs_remove(trajectory);
+	securityfs_remove(trajectory_counts);
+	securityfs_remove(trajectory_coeff);
+	securityfs_remove(measurement);
+	securityfs_remove(state);
+	securityfs_remove(external_tma);
+
+	return retn;
+}
