Linux-audit Archive mirror
 help / color / mirror / Atom feed
From: Deven Bowers <deven.desai@linux.microsoft.com>
To: corbet@lwn.net, zohar@linux.ibm.com, jmorris@namei.org,
	serge@hallyn.com, tytso@mit.edu, ebiggers@kernel.org,
	axboe@kernel.dk, agk@redhat.com, snitzer@kernel.org,
	eparis@redhat.com, paul@paul-moore.com
Cc: dm-devel@redhat.com, linux-doc@vger.kernel.org,
	roberto.sassu@huawei.com, linux-security-module@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-block@vger.kernel.org,
	linux-fscrypt@vger.kernel.org, linux-audit@redhat.com,
	linux-integrity@vger.kernel.org
Subject: [RFC PATCH v8 05/17] ipe: add LSM hooks on execution and kernel read
Date: Wed,  8 Jun 2022 12:01:17 -0700	[thread overview]
Message-ID: <1654714889-26728-6-git-send-email-deven.desai@linux.microsoft.com> (raw)
In-Reply-To: <1654714889-26728-1-git-send-email-deven.desai@linux.microsoft.com>

IPE's initial goal is to control both execution and the loading of
kernel modules based on the system's definition of trust. It
accomplishes this by plugging into the security hooks for
bprm_check_security, file_mprotect, mmap_file, kernel_load_data,
and kernel_read_data.

Signed-off-by: Deven Bowers <deven.desai@linux.microsoft.com>
---
v2:
  + Split evaluation loop, access control hooks,
    and evaluation loop from policy parser and userspace
    interface to pass mailing list character limit

v3:
  + Move ipe_load_properties to patch 04.
  + Remove useless 0-initializations
  + Prefix extern variables with ipe_
  + Remove kernel module parameters, as these are
    exposed through sysctls.
  + Add more prose to the IPE base config option
    help text.
  + Use GFP_KERNEL for audit_log_start.
  + Remove unnecessary caching system.
  + Remove comments from headers
  + Use rcu_access_pointer for rcu-pointer null check
  + Remove usage of reqprot; use prot only.
  + Move policy load and activation audit event to 03/12

v4:
  + Remove sysctls in favor of securityfs nodes
  + Re-add kernel module parameters, as these are now
    exposed through securityfs.
  + Refactor property audit loop to a separate function.

v5:
  + fix minor grammatical errors
  + do not group rule by curly-brace in audit record,
    reconstruct the exact rule.

v6:
  + No changes

v7:
  + Further split lsm creation, the audit system, the evaluation loop
    and access control hooks into separate commits.

v8:
  + Rename hook functions to follow the lsmname_hook_name convention
  + Remove ipe_hook enumeration, can be derived from correlation with
    syscall audit record.
---
 security/ipe/hooks.c  | 150 ++++++++++++++++++++++++++++++++++++++++++
 security/ipe/hooks.h  |  16 +++++
 security/ipe/ipe.c    |   5 ++
 security/ipe/policy.c |  23 +++++++
 security/ipe/policy.h |  12 +++-
 5 files changed, 204 insertions(+), 2 deletions(-)

diff --git a/security/ipe/hooks.c b/security/ipe/hooks.c
index dd9606962fa5..d20de25bbd40 100644
--- a/security/ipe/hooks.c
+++ b/security/ipe/hooks.c
@@ -6,11 +6,15 @@
 #include "ipe.h"
 #include "ctx.h"
 #include "hooks.h"
+#include "eval.h"
 
+#include <linux/fs.h>
 #include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/refcount.h>
 #include <linux/rcupdate.h>
+#include <linux/binfmts.h>
+#include <linux/mman.h>
 
 /**
  * ipe_task_alloc: Assign a new context for an associated task structure.
@@ -52,3 +56,149 @@ void ipe_task_free(struct task_struct *task)
 	ipe_put_ctx(ctx);
 	rcu_read_unlock();
 }
+
+/**
+ * ipe_bprm_check_security: LSM hook called when a process is loaded through the exec
+ *		family of system calls.
+ * @bprm: Supplies a pointer to a linux_binprm structure to source the file
+ *	  being evaluated.
+ *
+ * Return:
+ * 0 - OK
+ * !0 - Error
+ */
+int ipe_bprm_check_security(struct linux_binprm *bprm)
+{
+	return ipe_process_event(bprm->file, ipe_operation_exec);
+}
+
+/**
+ * ipe_mmap_file: LSM hook called when a file is loaded through the mmap
+ *		  family of system calls.
+ * @f: File being mmap'd. Can be NULL in the case of anonymous memory.
+ * @reqprot: The requested protection on the mmap, passed from usermode.
+ * @prot: The effective protection on the mmap, resolved from reqprot and
+ *	  system configuration.
+ * @flags: Unused.
+ *
+ * Return:
+ * 0 - OK
+ * !0 - Error
+ */
+int ipe_mmap_file(struct file *f, unsigned long reqprot, unsigned long prot,
+		  unsigned long flags)
+{
+	if (prot & PROT_EXEC || reqprot & PROT_EXEC)
+		return ipe_process_event(f, ipe_operation_exec);
+
+	return 0;
+}
+
+/**
+ * ipe_file_mprotect: LSM hook called when a mmap'd region of memory is changing
+ *		      its protections via mprotect.
+ * @vma: Existing virtual memory area created by mmap or similar
+ * @reqprot: The requested protection on the mmap, passed from usermode.
+ * @prot: The effective protection on the mmap, resolved from reqprot and
+ *	  system configuration.
+ *
+ * Return:
+ * 0 - OK
+ * !0 - Error
+ */
+int ipe_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
+		      unsigned long prot)
+{
+	/* Already Executable */
+	if (vma->vm_flags & VM_EXEC)
+		return 0;
+
+	if (prot & PROT_EXEC)
+		return ipe_process_event(vma->vm_file, ipe_operation_exec);
+
+	return 0;
+}
+
+/**
+ * ipe_kernel_read_file: LSM hook called when a file is being read in from
+ *			 disk.
+ * @file: Supplies a pointer to the file structure being read in from disk
+ * @id: Supplies the enumeration identifying the purpose of the read.
+ * @contents: Unused.
+ *
+ * Return:
+ * 0 - OK
+ * !0 - Error
+ */
+int ipe_kernel_read_file(struct file *file, enum kernel_read_file_id id,
+			 bool contents)
+{
+	enum ipe_operation op;
+
+	switch (id) {
+	case READING_FIRMWARE:
+		op = ipe_operation_firmware;
+		break;
+	case READING_MODULE:
+		op = ipe_operation_kernel_module;
+		break;
+	case READING_KEXEC_INITRAMFS:
+		op = ipe_operation_kexec_initramfs;
+		break;
+	case READING_KEXEC_IMAGE:
+		op = ipe_operation_kexec_image;
+		break;
+	case READING_POLICY:
+		op = ipe_operation_ima_policy;
+		break;
+	case READING_X509_CERTIFICATE:
+		op = ipe_operation_ima_x509;
+		break;
+	default:
+		op = ipe_operation_max;
+	}
+
+	WARN(op == ipe_operation_max, "no rule setup for enum %d", id);
+	return ipe_process_event(file, op);
+}
+
+/**
+ * ipe_kernel_load_data: LSM hook called when a buffer is being read in from
+ *			 disk.
+ * @id: Supplies the enumeration identifying the purpose of the read.
+ * @contents: Unused.
+ *
+ * Return:
+ * 0 - OK
+ * !0 - Error
+ */
+int ipe_kernel_load_data(enum kernel_load_data_id id, bool contents)
+{
+	enum ipe_operation op;
+
+	switch (id) {
+	case LOADING_FIRMWARE:
+		op = ipe_operation_firmware;
+		break;
+	case LOADING_MODULE:
+		op = ipe_operation_kernel_module;
+		break;
+	case LOADING_KEXEC_INITRAMFS:
+		op = ipe_operation_kexec_initramfs;
+		break;
+	case LOADING_KEXEC_IMAGE:
+		op = ipe_operation_kexec_image;
+		break;
+	case LOADING_POLICY:
+		op = ipe_operation_ima_policy;
+		break;
+	case LOADING_X509_CERTIFICATE:
+		op = ipe_operation_ima_x509;
+		break;
+	default:
+		op = ipe_operation_max;
+	}
+
+	WARN(op == ipe_operation_max, "no rule setup for enum %d", id);
+	return ipe_process_event(NULL, op);
+}
diff --git a/security/ipe/hooks.h b/security/ipe/hooks.h
index e0ae3c7dfb5b..fa9e0657bd64 100644
--- a/security/ipe/hooks.h
+++ b/security/ipe/hooks.h
@@ -5,12 +5,28 @@
 #ifndef IPE_HOOKS_H
 #define IPE_HOOKS_H
 
+#include <linux/fs.h>
 #include <linux/types.h>
 #include <linux/sched.h>
+#include <linux/binfmts.h>
+#include <linux/security.h>
 
 int ipe_task_alloc(struct task_struct *task,
 		   unsigned long clone_flags);
 
 void ipe_task_free(struct task_struct *task);
 
+int ipe_bprm_check_security(struct linux_binprm *bprm);
+
+int ipe_mmap_file(struct file *f, unsigned long reqprot, unsigned long prot,
+		  unsigned long flags);
+
+int ipe_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
+		      unsigned long prot);
+
+int ipe_kernel_read_file(struct file *file, enum kernel_read_file_id id,
+			 bool contents);
+
+int ipe_kernel_load_data(enum kernel_load_data_id id, bool contents);
+
 #endif /* IPE_HOOKS_H */
diff --git a/security/ipe/ipe.c b/security/ipe/ipe.c
index edeb354765dd..fca7019ca53c 100644
--- a/security/ipe/ipe.c
+++ b/security/ipe/ipe.c
@@ -27,6 +27,11 @@ static struct lsm_blob_sizes ipe_blobs __lsm_ro_after_init = {
 static struct security_hook_list ipe_hooks[] __lsm_ro_after_init = {
 	LSM_HOOK_INIT(task_alloc, ipe_task_alloc),
 	LSM_HOOK_INIT(task_free, ipe_task_free),
+	LSM_HOOK_INIT(bprm_check_security, ipe_bprm_check_security),
+	LSM_HOOK_INIT(mmap_file, ipe_mmap_file),
+	LSM_HOOK_INIT(file_mprotect, ipe_file_mprotect),
+	LSM_HOOK_INIT(kernel_read_file, ipe_kernel_read_file),
+	LSM_HOOK_INIT(kernel_load_data, ipe_kernel_load_data),
 };
 
 /**
diff --git a/security/ipe/policy.c b/security/ipe/policy.c
index d4bd06e4a19b..8309f9270000 100644
--- a/security/ipe/policy.c
+++ b/security/ipe/policy.c
@@ -483,6 +483,14 @@ int ipe_parse_op(const struct ipe_policy_token *tok,
 {
 	substring_t match[MAX_OPT_ARGS] = { 0 };
 	const match_table_t ops = {
+		{ ipe_operation_exec,		 "EXECUTE" },
+		{ ipe_operation_firmware,	 "FIRMWARE" },
+		{ ipe_operation_kernel_module,	 "KMODULE" },
+		{ ipe_operation_kexec_image,	 "KEXEC_IMAGE" },
+		{ ipe_operation_kexec_initramfs, "KEXEC_INITRAMFS"},
+		{ ipe_operation_ima_policy,	 "IMA_POLICY" },
+		{ ipe_operation_ima_x509,	 "IMA_X509_CERT" },
+		{ ipe_op_alias_kernel_read,	 "KERNEL_READ" },
 		{ ipe_op_alias_max, NULL },
 	};
 
@@ -838,6 +846,15 @@ static int parse_policy(struct ipe_policy *p)
 	return rc;
 }
 
+static const enum ipe_operation alias_kread[] = {
+	ipe_operation_firmware,
+	ipe_operation_kernel_module,
+	ipe_operation_ima_policy,
+	ipe_operation_ima_x509,
+	ipe_operation_kexec_image,
+	ipe_operation_kexec_initramfs,
+};
+
 /**
  * ipe_is_op_alias: Determine if @op is an alias for one or more operations
  * @op: Supplies the operation to check. Should be either ipe_operation or
@@ -852,9 +869,15 @@ static int parse_policy(struct ipe_policy *p)
 bool ipe_is_op_alias(int op, const enum ipe_operation **map, size_t *size)
 {
 	switch (op) {
+	case ipe_op_alias_kernel_read:
+		*map = alias_kread;
+		*size = ARRAY_SIZE(alias_kread);
+		break;
 	default:
 		return false;
 	}
+
+	return true;
 }
 
 /**
diff --git a/security/ipe/policy.h b/security/ipe/policy.h
index 6818f6405dd0..ca37af46e5af 100644
--- a/security/ipe/policy.h
+++ b/security/ipe/policy.h
@@ -26,7 +26,14 @@ struct ipe_policy_line {
 struct ipe_module;
 
 enum ipe_operation {
-	ipe_operation_max = 0,
+	ipe_operation_exec = 0,
+	ipe_operation_firmware,
+	ipe_operation_kernel_module,
+	ipe_operation_kexec_image,
+	ipe_operation_kexec_initramfs,
+	ipe_operation_ima_policy,
+	ipe_operation_ima_x509,
+	ipe_operation_max
 };
 
 /*
@@ -34,7 +41,8 @@ enum ipe_operation {
  * that are just one or more operations under the hood
  */
 enum ipe_op_alias {
-	ipe_op_alias_max = ipe_operation_max,
+	ipe_op_alias_kernel_read = ipe_operation_max,
+	ipe_op_alias_max,
 };
 
 enum ipe_action {
-- 
2.25.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://listman.redhat.com/mailman/listinfo/linux-audit


  parent reply	other threads:[~2022-06-08 19:26 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-08 19:01 [RFC PATCH v8 00/17] Integrity Policy Enforcement LSM (IPE) Deven Bowers
2022-06-08 19:01 ` [RFC PATCH v8 01/17] security: add ipe lsm & initial context creation Deven Bowers
2022-06-08 19:01 ` [RFC PATCH v8 02/17] ipe: add policy parser Deven Bowers
2022-06-15 22:12   ` Paul Moore
2022-06-08 19:01 ` [RFC PATCH v8 03/17] ipe: add evaluation loop Deven Bowers
2022-06-08 19:01 ` [RFC PATCH v8 04/17] ipe: add userspace interface Deven Bowers
2022-06-08 19:01 ` Deven Bowers [this message]
2022-06-08 19:01 ` [RFC PATCH v8 06/17] uapi|audit: add ipe audit message definitions Deven Bowers
2022-06-08 19:01 ` [RFC PATCH v8 07/17] ipe: add auditing support Deven Bowers
2022-06-15 22:12   ` Paul Moore
2022-08-09 15:57   ` Tyler Hicks
2022-06-08 19:01 ` [RFC PATCH v8 08/17] ipe: add permissive toggle Deven Bowers
2022-06-08 19:01 ` [RFC PATCH v8 09/17] ipe: introduce 'boot_verified' as a trust provider Deven Bowers
2022-06-08 19:01 ` [RFC PATCH v8 10/17] block|security: add LSM blob to block_device Deven Bowers
2022-06-08 20:07   ` Casey Schaufler
2022-06-08 22:28     ` Deven Bowers
2022-06-08 19:01 ` [RFC PATCH v8 11/17] dm-verity: consume root hash digest and signature data via LSM hook Deven Bowers
2022-06-08 19:01 ` [RFC PATCH v8 12/17] ipe: add support for dm-verity as a trust provider Deven Bowers
2022-06-08 19:01 ` [RFC PATCH v8 13/17] fsverity: consume builtin signature via LSM hook Deven Bowers
2022-06-09 23:46   ` Eric Biggers
2022-06-08 19:01 ` [RFC PATCH v8 14/17] ipe: enable support for fs-verity as a trust provider Deven Bowers
2022-06-08 19:01 ` [RFC PATCH v8 15/17] scripts: add boot policy generation program Deven Bowers
2022-06-08 19:01 ` [RFC PATCH v8 16/17] ipe: kunit tests Deven Bowers
2022-06-08 19:01 ` [RFC PATCH v8 17/17] documentation: add ipe documentation Deven Bowers
2022-06-08 19:10 ` [RFC PATCH v8 00/17] Integrity Policy Enforcement LSM (IPE) Matthew Wilcox
2022-06-08 19:41   ` Deven Bowers

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1654714889-26728-6-git-send-email-deven.desai@linux.microsoft.com \
    --to=deven.desai@linux.microsoft.com \
    --cc=agk@redhat.com \
    --cc=axboe@kernel.dk \
    --cc=corbet@lwn.net \
    --cc=dm-devel@redhat.com \
    --cc=ebiggers@kernel.org \
    --cc=eparis@redhat.com \
    --cc=jmorris@namei.org \
    --cc=linux-audit@redhat.com \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-fscrypt@vger.kernel.org \
    --cc=linux-integrity@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=paul@paul-moore.com \
    --cc=roberto.sassu@huawei.com \
    --cc=serge@hallyn.com \
    --cc=snitzer@kernel.org \
    --cc=tytso@mit.edu \
    --cc=zohar@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).