Re: [PATCH 1/2] audit: remove redundant data_len check

2022-06-08 Thread Shreenidhi Shedi
On 08/06/22 1:31 am, Paul Moore wrote:
> On Sun, May 15, 2022 at 7:35 PM Paul Moore  wrote:
>>
>> On Sun, May 15, 2022 at 3:31 AM Shreenidhi Shedi  wrote:
>>>
>>> data_len is already getting checked if it's less than 2 earlier in this
>>> function.
>>>
>>> Signed-off-by: Shreenidhi Shedi 
>>> ---
>>>  kernel/audit.c | 2 +-
>>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> Thanks, this patch looks okay, but since we are already at v5.18-rc7
>> this patch will have to wait until after the upcoming merge window as
>> it isn't a critical bug fix.
> 
> ... and it's now merged into audit/next, thanks!
> 

You are welcome and Thank you as well.

-- 
Shedi

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



[RFC PATCH v8 15/17] scripts: add boot policy generation program

2022-06-08 Thread Deven Bowers
Enables an IPE policy to be enforced from kernel start, enabling access
control based on trust from kernel startup. This is accomplished by
transforming an IPE policy indicated by CONFIG_IPE_BOOT_POLICY into a
c-string literal that is parsed at kernel startup as an unsigned policy.

Signed-off-by: Deven Bowers 
---
v2:
  + No Changes

v3:
  + No Changes

v4:
  + No Changes

v5:
  + No Changes

v6:
  + No Changes

v7:
  + Move from 01/11 to 14/16
  + Don't return errno directly.
  + Make output of script more user-friendly
  + Add escaping for tab and '?'
  + Mark argv pointer const
  + Invert return code check in the boot policy parsing code path.

v8:
  + No signfiicant chances.
---
 MAINTAINERS   |   1 +
 scripts/Makefile  |   1 +
 scripts/ipe/Makefile  |   2 +
 scripts/ipe/polgen/.gitignore |   1 +
 scripts/ipe/polgen/Makefile   |   6 ++
 scripts/ipe/polgen/polgen.c   | 145 ++
 security/ipe/.gitignore   |   1 +
 security/ipe/Kconfig  |  10 +++
 security/ipe/Makefile |  11 +++
 security/ipe/ctx.c|  18 +
 security/ipe/fs.c |  10 +++
 11 files changed, 206 insertions(+)
 create mode 100644 scripts/ipe/Makefile
 create mode 100644 scripts/ipe/polgen/.gitignore
 create mode 100644 scripts/ipe/polgen/Makefile
 create mode 100644 scripts/ipe/polgen/polgen.c
 create mode 100644 security/ipe/.gitignore

diff --git a/MAINTAINERS b/MAINTAINERS
index 965fdac6d609..f7333d07a9df 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9797,6 +9797,7 @@ INTEGRITY POLICY ENFORCEMENT (IPE)
 M: Deven Bowers 
 M: Fan Wu 
 S: Supported
+F: scripts/ipe/
 F: security/ipe/
 
 INTEL 810/815 FRAMEBUFFER DRIVER
diff --git a/scripts/Makefile b/scripts/Makefile
index f084f08ed176..4f1a8f37a83f 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -38,6 +38,7 @@ targets += module.lds
 subdir-$(CONFIG_GCC_PLUGINS) += gcc-plugins
 subdir-$(CONFIG_MODVERSIONS) += genksyms
 subdir-$(CONFIG_SECURITY_SELINUX) += selinux
+subdir-$(CONFIG_SECURITY_IPE) += ipe
 
 # Let clean descend into subdirs
 subdir-+= basic dtc gdb kconfig mod
diff --git a/scripts/ipe/Makefile b/scripts/ipe/Makefile
new file mode 100644
index ..e87553fbb8d6
--- /dev/null
+++ b/scripts/ipe/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+subdir-y := polgen
diff --git a/scripts/ipe/polgen/.gitignore b/scripts/ipe/polgen/.gitignore
new file mode 100644
index ..80f32f25d200
--- /dev/null
+++ b/scripts/ipe/polgen/.gitignore
@@ -0,0 +1 @@
+polgen
diff --git a/scripts/ipe/polgen/Makefile b/scripts/ipe/polgen/Makefile
new file mode 100644
index ..066060c22b4a
--- /dev/null
+++ b/scripts/ipe/polgen/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+hostprogs-always-y := polgen
+HOST_EXTRACFLAGS += \
+   -I$(srctree)/include \
+   -I$(srctree)/include/uapi \
+
diff --git a/scripts/ipe/polgen/polgen.c b/scripts/ipe/polgen/polgen.c
new file mode 100644
index ..40b6fe07f47b
--- /dev/null
+++ b/scripts/ipe/polgen/polgen.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Microsoft Corporation. All rights reserved.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static void usage(const char *const name)
+{
+   printf("Usage: %s OutputFile (PolicyFile)\n", name);
+   exit(EINVAL);
+}
+
+static int policy_to_buffer(const char *pathname, char **buffer, size_t *size)
+{
+   int rc = 0;
+   FILE *fd;
+   char *lbuf;
+   size_t fsize;
+   size_t read;
+
+   fd = fopen(pathname, "r");
+   if (!fd) {
+   rc = errno;
+   goto out;
+   }
+
+   fseek(fd, 0, SEEK_END);
+   fsize = ftell(fd);
+   rewind(fd);
+
+   lbuf = malloc(fsize);
+   if (!lbuf) {
+   rc = ENOMEM;
+   goto out_close;
+   }
+
+   read = fread((void *)lbuf, sizeof(*lbuf), fsize, fd);
+   if (read != fsize) {
+   rc = -1;
+   goto out_free;
+   }
+
+   *buffer = lbuf;
+   *size = fsize;
+   fclose(fd);
+
+   return rc;
+
+out_free:
+   free(lbuf);
+out_close:
+   fclose(fd);
+out:
+   return rc;
+}
+
+static int write_boot_policy(const char *pathname, const char *buf, size_t 
size)
+{
+   int rc = 0;
+   FILE *fd;
+   size_t i;
+
+   fd = fopen(pathname, "w");
+   if (!fd) {
+   rc = errno;
+   goto err;
+   }
+
+   fprintf(fd, "/* This file is automatically generated.");
+   fprintf(fd, " Do not edit. */\n");
+   fprintf(fd, "#include \n");
+   fprintf(fd, "\nextern const char *const ipe_boot_policy;\n\n");
+   fprintf(fd, "const char *const ipe_boot_policy =\n");
+
+   if (!buf || size == 0) {
+   fprintf(fd, "\tNULL;\n");
+   fclose(fd);
+   return 0;
+   }
+
+   fprintf(fd,

[RFC PATCH v8 10/17] block|security: add LSM blob to block_device

2022-06-08 Thread Deven Bowers
block_device structures can have valuable security properties,
based on how they are created, and what subsystem manages them.

By adding LSM storage to this structure, this data can be accessed
at the LSM layer.

Signed-off-by: Deven Bowers 

---
v2:
  + No Changes

v3:
  + Minor style changes from checkpatch --strict

v4:
  + No Changes

v5:
  + Allow multiple callers to call security_bdev_setsecurity

v6:
  + Simplify security_bdev_setsecurity break condition

v7:
  + Squash all dm-verity related patches to two patches,
the additions to dm-verity/fs, and the consumption of
the additions.

v8:
  + Split dm-verity related patches squashed in v7 to 3 commits based on
topic:
  + New LSM hook
  + Consumption of hook outside LSM
  + Consumption of hook inside LSM.

  + change return of security_bdev_alloc / security_bdev_setsecurity
to LSM_RET_DEFAULT instead of 0.

  + Change return code to -EOPNOTSUPP, bring inline with other
setsecurity hooks.
---
 block/bdev.c  |  7 
 include/linux/blk_types.h |  1 +
 include/linux/lsm_hook_defs.h |  5 +++
 include/linux/lsm_hooks.h | 12 ++
 include/linux/security.h  | 22 +++
 security/security.c   | 70 +++
 6 files changed, 117 insertions(+)

diff --git a/block/bdev.c b/block/bdev.c
index 5fe06c1f2def..e7ef2c7a22c9 100644
--- a/block/bdev.c
+++ b/block/bdev.c
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include "../fs/internal.h"
@@ -397,6 +398,11 @@ static struct inode *bdev_alloc_inode(struct super_block 
*sb)
if (!ei)
return NULL;
memset(&ei->bdev, 0, sizeof(ei->bdev));
+
+   if (unlikely(security_bdev_alloc(&ei->bdev))) {
+   kmem_cache_free(bdev_cachep, ei);
+   return NULL;
+   }
return &ei->vfs_inode;
 }
 
@@ -406,6 +412,7 @@ static void bdev_free_inode(struct inode *inode)
 
free_percpu(bdev->bd_stats);
kfree(bdev->bd_meta_info);
+   security_bdev_free(bdev);
 
if (!bdev_is_partition(bdev)) {
if (bdev->bd_disk && bdev->bd_disk->bdi)
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index a24d4078fb21..a014ffa14b2d 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -68,6 +68,7 @@ struct block_device {
 #ifdef CONFIG_FAIL_MAKE_REQUEST
boolbd_make_it_fail;
 #endif
+   void*security;
 } __randomize_layout;
 
 #define bdev_whole(_bdev) \
diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
index eafa1d2489fd..3449c004bd84 100644
--- a/include/linux/lsm_hook_defs.h
+++ b/include/linux/lsm_hook_defs.h
@@ -407,3 +407,8 @@ LSM_HOOK(int, 0, perf_event_write, struct perf_event *event)
 LSM_HOOK(int, 0, uring_override_creds, const struct cred *new)
 LSM_HOOK(int, 0, uring_sqpoll, void)
 #endif /* CONFIG_IO_URING */
+
+LSM_HOOK(int, 0, bdev_alloc_security, struct block_device *bdev)
+LSM_HOOK(void, LSM_RET_VOID, bdev_free_security, struct block_device *bdev)
+LSM_HOOK(int, 0, bdev_setsecurity, struct block_device *bdev, const char *name,
+const void *value, size_t size)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 91c8146649f5..9f011d705ea8 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1550,6 +1550,17 @@
  *
  * @what: kernel feature being accessed
  *
+ * @bdev_alloc_security:
+ * Initialize the security field inside a block_device structure.
+ *
+ * @bdev_free_security:
+ * Cleanup the security information stored inside a block_device structure.
+ *
+ * @bdev_setsecurity:
+ * Set a security property associated with @name for @bdev with
+ * value @value. @size indicates the size of @value in bytes.
+ * If a @name is not implemented, return -EOPNOTSUPP.
+ *
  * Security hooks for perf events
  *
  * @perf_event_open:
@@ -1610,6 +1621,7 @@ struct lsm_blob_sizes {
int lbs_ipc;
int lbs_msg_msg;
int lbs_task;
+   int lbs_bdev;
 };
 
 /*
diff --git a/include/linux/security.h b/include/linux/security.h
index 7fc4e9f49f54..30b663de301f 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -473,6 +473,11 @@ int security_inode_notifysecctx(struct inode *inode, void 
*ctx, u32 ctxlen);
 int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
 int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
 int security_locked_down(enum lockdown_reason what);
+int security_bdev_alloc(struct block_device *bdev);
+void security_bdev_free(struct block_device *bdev);
+int security_bdev_setsecurity(struct block_device *bdev,
+ const char *name, const void *value,
+ size_t size);
 #else /* CONFIG_SECURITY */
 
 static inline int call_blocking_lsm_notifier(enum lsm_event event, v

[RFC PATCH v8 14/17] ipe: enable support for fs-verity as a trust provider

2022-06-08 Thread Deven Bowers
From: Fan Wu 

Enable IPE policy authors to indicate trust for a singular fsverity
file, identified by the digest information, through "fsverity_digest"
and all files using fsverity's builtin signatures via
"fsverity_signature".

This enables file-level integrity claims to be expressed in IPE,
allowing individual files to be authorized, giving some flexibility
for policy authors. Such file-level claims are important to be expressed
for enforcing the integrity of packages, as well as address some of the
scalability issues in a sole dm-verity based solution (# of loop back
devices, etc).

This solution cannot be done in userspace as the minimum threat that
IPE should mitigate is an attacker downloads malicious payload with
all required dependencies. These dependencies can lack the userspace
check, bypassing the protection entirely. A similar attack succeeds if
the userspace component is replaced with a version that does not
perform the check. As a result, this can only be done in the common
entry point - the kernel.

Signed-off-by: Fan Wu 
Signed-off-by: Deven Bowers 
---
v1-v6:
  + Not present

v7:
  Introduced

v8:
  * Undo squash of 08/12, 10/12 - separating drivers/md/ from security/
  * Use common-audit function for fsverity_signature.
  + Change fsverity implementation to use fsverity_get_digest
  + prevent unnecessary copy of fs-verity signature data, instead
just check for presence of signature data.
  + Remove free_inode_security hook, as the digest is now acquired
at runtime instead of via LSM blob.
---
 security/ipe/eval.c   |  1 +
 security/ipe/eval.h   |  5 +++
 security/ipe/hooks.c  | 29 +
 security/ipe/hooks.h  |  5 +++
 security/ipe/ipe.c|  7 
 security/ipe/ipe.h|  1 +
 security/ipe/modules/Kconfig  | 23 +
 security/ipe/modules/Makefile |  2 ++
 security/ipe/modules/fsverity_digest.c| 39 +++
 security/ipe/modules/fsverity_signature.c | 34 
 10 files changed, 146 insertions(+)
 create mode 100644 security/ipe/modules/fsverity_digest.c
 create mode 100644 security/ipe/modules/fsverity_signature.c

diff --git a/security/ipe/eval.c b/security/ipe/eval.c
index 9b29d83cd466..e8205a6fce44 100644
--- a/security/ipe/eval.c
+++ b/security/ipe/eval.c
@@ -95,6 +95,7 @@ static struct ipe_eval_ctx *build_ctx(const struct file *file,
ctx->ci_ctx = ipe_current_ctx();
ctx->from_init_sb = from_pinned(file);
if (file) {
+   ctx->ipe_inode = ipe_inode(file->f_inode);
if (FILE_BLOCK_DEV(file))
ctx->ipe_bdev = ipe_bdev(FILE_BLOCK_DEV(file));
}
diff --git a/security/ipe/eval.h b/security/ipe/eval.h
index 57b7b2b424f8..541251125e8e 100644
--- a/security/ipe/eval.h
+++ b/security/ipe/eval.h
@@ -22,6 +22,10 @@ struct ipe_bdev {
const char *digest_algo;
 };
 
+struct ipe_inode {
+   bool fs_verity_signed;
+};
+
 struct ipe_eval_ctx {
enum ipe_operation op;
 
@@ -29,6 +33,7 @@ struct ipe_eval_ctx {
struct ipe_context *ci_ctx;
 
const struct ipe_bdev *ipe_bdev;
+   const struct ipe_inode *ipe_inode;
 
bool from_init_sb;
 };
diff --git a/security/ipe/hooks.c b/security/ipe/hooks.c
index 1072ee5bb8f6..7c99afad4924 100644
--- a/security/ipe/hooks.c
+++ b/security/ipe/hooks.c
@@ -267,3 +267,32 @@ int ipe_bdev_setsecurity(struct block_device *bdev, const 
char *key,
 
return -EOPNOTSUPP;
 }
+
+/**
+ * ipe_inode_setsecurity: Sets the a certain field of a inode security
+ *  blob, based on @key.
+ * @inode: The inode to source the security blob from.
+ * @name: The name representing the information to be stored.
+ * @value: The value to be stored.
+ * @size: The size of @value.
+ * @flags: unused
+ *
+ * Saves fsverity signature & digest into inode security blob
+ *
+ * Return:
+ * 0 - OK
+ * !0 - Error
+ */
+int ipe_inode_setsecurity(struct inode *inode, const char *name,
+ const void *value, size_t size,
+ int flags)
+{
+   struct ipe_inode *inode_sec = ipe_inode(inode);
+
+   if (!strcmp(name, FS_VERITY_INODE_SEC_NAME)) {
+   inode_sec->fs_verity_signed = size > 0 && value;
+   return 0;
+   }
+
+   return -EOPNOTSUPP;
+}
diff --git a/security/ipe/hooks.h b/security/ipe/hooks.h
index 0d1589e47f8f..1edcc91d6d33 100644
--- a/security/ipe/hooks.h
+++ b/security/ipe/hooks.h
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 int ipe_task_alloc(struct task_struct *task,
@@ -37,4 +38,8 @@ void ipe_bdev_free_security(struct block_device *bdev);
 int ipe_bdev_setsecurity(struct block_device *bdev, const char *key,
 const void *value, size_t len);
 
+int ipe_inode_setsecurity(struct inode *inode, const char 

[RFC PATCH v8 05/17] ipe: add LSM hooks on execution and kernel read

2022-06-08 Thread Deven Bowers
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 
---
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 
 #include 
 #include 
 #include 
 #include 
+#include 
+#include 
 
 /**
  * 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_ker

[RFC PATCH v8 06/17] uapi|audit: add ipe audit message definitions

2022-06-08 Thread Deven Bowers
Introduce new definitions to audit.h centered around trust
decisions and policy loading and activation, as an extension
of the mandatory access control fields.

Signed-off-by: Deven Bowers 

---
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 audit system patch into two separate patches; one
for include/uapi, and the usage of the new defines.

  + Change audit records to MAC region (14XX) from
Integrity region (18XX), as IPE is an effectively a MAC system
around authenticity versus an extension to the integrity subsystem.

  + Generalize the #defines to support the class of trust-based
access-control LSMs.

v8:
  + Change audit type:
+ AUDIT_TRUST_RESULT -> AUDIT_IPE_ACCESS

  + Remove audit types (replaced by existing types):
+ AUDIT_TRUST_POLICY_LOAD
+ AUDIT_TRUST_POLICY_ACTIVATE
+ AUDIT_TRUST_STATUS
---
 include/uapi/linux/audit.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 7c1dc818b1d5..78b9a04d5b41 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -143,6 +143,7 @@
 #define AUDIT_MAC_UNLBL_STCDEL 1417/* NetLabel: del a static label */
 #define AUDIT_MAC_CALIPSO_ADD  1418/* NetLabel: add CALIPSO DOI entry */
 #define AUDIT_MAC_CALIPSO_DEL  1419/* NetLabel: del CALIPSO DOI entry */
+#define AUDIT_IPE_ACCESS   1420/* IPE Denial or Grant */
 
 #define AUDIT_FIRST_KERN_ANOM_MSG   1700
 #define AUDIT_LAST_KERN_ANOM_MSG1799
-- 
2.25.1

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



[RFC PATCH v8 01/17] security: add ipe lsm & initial context creation

2022-06-08 Thread Deven Bowers
Integrity Policy Enforcement (IPE) is an LSM that provides an
complimentary approach to Mandatory Access Control than existing LSMs
today.

Existing LSMs have centered around the concept of access to a resource
should be controlled by the current user's credentials. IPE's approach,
is that access to a resource should be controlled by the system's trust
of a current resource.

The basis of this approach is that every process in the kernel is
associated with a context that determines the policy for what is
trusted by said process and its descendents, starting with 'init'.

Signed-off-by: Deven Bowers 
---
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 into a separate commit from the
evaluation loop and audit system, for easier review.

  + Introduce the concept of an ipe_context, a scoped way to
introduce execution policies, used initially for allowing for
kunit tests in isolation.

v8:
  + Follow lsmname_hook_name convention for lsm hooks.
  + Move LSM blob accessors to ipe.c and mark LSM blobs as static.
---
 MAINTAINERS   |   6 ++
 security/Kconfig  |  11 ++--
 security/Makefile |   1 +
 security/ipe/Kconfig  |  17 +
 security/ipe/Makefile |  11 
 security/ipe/ctx.c| 145 ++
 security/ipe/ctx.h|  28 
 security/ipe/hooks.c  |  54 
 security/ipe/hooks.h  |  16 +
 security/ipe/ipe.c|  73 +
 security/ipe/ipe.h|  17 +
 11 files changed, 374 insertions(+), 5 deletions(-)
 create mode 100644 security/ipe/Kconfig
 create mode 100644 security/ipe/Makefile
 create mode 100644 security/ipe/ctx.c
 create mode 100644 security/ipe/ctx.h
 create mode 100644 security/ipe/hooks.c
 create mode 100644 security/ipe/hooks.h
 create mode 100644 security/ipe/ipe.c
 create mode 100644 security/ipe/ipe.h

diff --git a/MAINTAINERS b/MAINTAINERS
index a6d3bd9d2a8d..965fdac6d609 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9793,6 +9793,12 @@ T:   git 
git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git
 F: security/integrity/ima/
 F: security/integrity/
 
+INTEGRITY POLICY ENFORCEMENT (IPE)
+M: Deven Bowers 
+M: Fan Wu 
+S: Supported
+F: security/ipe/
+
 INTEL 810/815 FRAMEBUFFER DRIVER
 M: Antonino Daplas 
 L: linux-fb...@vger.kernel.org
diff --git a/security/Kconfig b/security/Kconfig
index f29e4c656983..7d4c641313ca 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -218,6 +218,7 @@ source "security/yama/Kconfig"
 source "security/safesetid/Kconfig"
 source "security/lockdown/Kconfig"
 source "security/landlock/Kconfig"
+source "security/ipe/Kconfig"
 
 source "security/integrity/Kconfig"
 
@@ -257,11 +258,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,ipe"
 if DEFAULT_SECURITY_SMACK
+   default 
"landlock,lockdown,yama,loadpin,safesetid,integrity,apparmor,selinux,smack,tomoyo,bpf,ipe"
 if DEFAULT_SECURITY_APPARMOR
+   default 
"landlock,lockdown,yama,loadpin,safesetid,integrity,tomoyo,bpf,ipe" if 
DEFAULT_SECURITY_TOMOYO
+   default "landlock,lockdown,yama,loadpin,safesetid,integrity,bpf,ipe" if 
DEFAULT_SECURITY_DAC
+   default 
"landlock,lockdown,yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor,bpf,i

[RFC PATCH v8 16/17] ipe: kunit tests

2022-06-08 Thread Deven Bowers
Add various happy/unhappy unit tests for both IPE's parser
and evaluation loop, testing the core of IPE. The missing
test gap remains the interface with userspace.

Signed-off-by: Deven Bowers 

---
v1-v6:
  + Not present

v7:
  Introduced

v8:
  + Remove the kunit tests with respect to the fsverity digest, as these
require significant changes to work with the new method of acquiring
the digest at runtime.
---
 security/ipe/Kconfig   |  17 +
 security/ipe/Makefile  |   3 +
 security/ipe/ctx_test.c| 718 +
 security/ipe/eval.c|   4 +
 security/ipe/policy_parser_tests.c | 313 +
 5 files changed, 1055 insertions(+)
 create mode 100644 security/ipe/ctx_test.c
 create mode 100644 security/ipe/policy_parser_tests.c

diff --git a/security/ipe/Kconfig b/security/ipe/Kconfig
index 619bf179af43..8746022f147b 100644
--- a/security/ipe/Kconfig
+++ b/security/ipe/Kconfig
@@ -81,4 +81,21 @@ config IPE_AUDIT_HASH_ALG
 
 source "security/ipe/modules/Kconfig"
 
+config SECURITY_IPE_KUNIT_TEST
+   bool "Build KUnit tests for IPE" if !KUNIT_ALL_TESTS
+   depends on KUNIT=y
+   default KUNIT_ALL_TESTS
+   help
+ This builds the IPE KUnit tests.
+
+ KUnit tests run during boot and output the results to the debug log
+ in TAP format (https://testanything.org/). Only useful for kernel devs
+ running KUnit test harness and are not for inclusion into a
+ production build.
+
+ For more information on KUnit and unit tests in general please refer
+ to the KUnit documentation in Documentation/dev-tools/kunit/.
+
+ If unsure, say N.
+
 endif
diff --git a/security/ipe/Makefile b/security/ipe/Makefile
index 1a1f7484caee..c91672a05d5f 100644
--- a/security/ipe/Makefile
+++ b/security/ipe/Makefile
@@ -31,4 +31,7 @@ obj-$(CONFIG_SECURITY_IPE) += \
 
 obj-$(CONFIG_IPE_AUDIT) += audit.o
 
+obj-$(CONFIG_SECURITY_IPE_KUNIT_TEST) += \
+   policy_parser_tests.o \
+
 clean-files := boot-policy.c \
diff --git a/security/ipe/ctx_test.c b/security/ipe/ctx_test.c
new file mode 100644
index ..1bbf5d5320e0
--- /dev/null
+++ b/security/ipe/ctx_test.c
@@ -0,0 +1,718 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Microsoft Corporation. All rights reserved.
+ */
+#include 
+#include 
+#include 
+#include 
+#include "ctx.h"
+#include "policy.h"
+#include "hooks.h"
+
+struct eval_case {
+   const char *const desc;
+   const char *const policy;
+   int   errno;
+
+   const struct file *fake_file;
+   const struct ipe_bdev *bdev_sec;
+   const struct ipe_inode *inode_sec;
+   bool initsb;
+};
+
+static const u8 fake_digest[] = { 0xDE, 0xAD, 0xBE, 0xEF };
+
+static const struct ipe_bdev fake_bdev_no_data = {};
+static const struct ipe_bdev fake_bdev_no_sig = {
+   .digest = fake_digest,
+   .digest_len = ARRAY_SIZE(fake_digest),
+   .digest_algo = "test",
+};
+
+static const struct ipe_bdev fake_bdev_signed = {
+   .dm_verity_signed = true,
+   .digest = fake_digest,
+   .digest_len = ARRAY_SIZE(fake_digest),
+   .digest_algo = "test",
+};
+
+static const struct ipe_inode fake_ino_no_data = {};
+static const struct ipe_inode fake_ino_signed = {
+   .fs_verity_signed = true,
+};
+
+static struct inode fake_inode = {
+   .i_flags = S_VERITY
+};
+
+static const struct file fake_verity = {
+   .f_inode = &fake_inode,
+};
+
+static const struct eval_case cases[] = {
+   {
+   "boot_verified_trust_no_source",
+   "policy_name='Test' policy_version=0.0.0\n"
+   "DEFAULT action=DENY\n"
+   "op=EXECUTE boot_verified=TRUE action=ALLOW\n"
+   "op=KERNEL_READ boot_verified=TRUE action=ALLOW\n",
+   -EACCES, NULL, NULL, NULL, false
+   },
+   {
+   "boot_verified_distrust",
+   "policy_name='Test' policy_version=0.0.0\n"
+   "DEFAULT action=DENY\n"
+   "op=EXECUTE boot_verified=FALSE action=ALLOW\n"
+   "op=KERNEL_READ boot_verified=FALSE action=ALLOW\n",
+   0, NULL, NULL, NULL, false
+   },
+   {
+   "boot_verified_trust",
+   "policy_name='Test' policy_version=0.0.0\n"
+   "DEFAULT action=DENY\n"
+   "op=EXECUTE boot_verified=TRUE action=ALLOW\n"
+   "op=KERNEL_READ boot_verified=TRUE action=ALLOW\n",
+   0, NULL, NULL, NULL, true
+   },
+   {
+   "boot_verified_trust",
+   "policy_name='Test' policy_version=0.0.0\n"
+   "DEFAULT action=DENY\n"
+   "op=EXECUTE boot_verified=FALSE action=ALLOW\n"
+   "op=KERNEL_READ boot_verified=FALSE action=ALLOW\n",
+   -EACCES, NULL, NULL, NULL, true
+   },
+   {
+   "dmverity_signature_trust_no_bdev",
+   "po

[RFC PATCH v8 11/17] dm-verity: consume root hash digest and signature data via LSM hook

2022-06-08 Thread Deven Bowers
dm-verity provides a strong guarantee of a block device's integrity. As
a generic way to check the integrity of a block device, it provides
those integrity guarantees to its lower layers, including the filesystem
level.

An LSM that control access to a resource on the system based on the
available integrity claims can use this transitive property of
dm-verity, by querying the underlying block_device of a particular
file.

The digest and signature information need to be stored in the block
device to fulfill the next requirement of authorization via LSM policy.
This will enable the LSM being able to perform revocation of devices
that are still mounted, prohibiting execution of files that are no
longer authorized by the LSM in question.

Signed-off-by: Deven Bowers 
---
v2:
  + No Changes

v3:
  + No changes

v4:
  + No changes

v5:
  + No changes

v6:
  + Fix an improper cleanup that can result in
a leak

v7:
  + Squash patch 08/12, 10/12 to [11/16]
  + Use part0 for block_device, to retrieve the block_device, when
calling security_bdev_setsecurity

v8:
  + Undo squash of 08/12, 10/12 - separating drivers/md/ from
security/ & block/
  + Use common-audit function for dmverity_signature.
  + Change implementation for storing the dm-verity digest to use the
newly introduced dm_verity_digest structure introduced in patch
14/20.
  + Create new structure, dm_verity_digest, containing digest algorithm,
size, and digest itself to pass to the LSM layer. V7 was missing the
algorithm.
  + Create an associated public header containing this new structure and
the key values for the LSM hook, specific to dm-verity.
  + Additional information added to commit, discussing the layering of
the changes and how the information passed will be used.
---
 drivers/md/dm-verity-target.c | 25 +++--
 drivers/md/dm-verity-verify-sig.c | 16 +---
 drivers/md/dm-verity-verify-sig.h | 10 ++
 include/linux/dm-verity.h | 19 +++
 4 files changed, 61 insertions(+), 9 deletions(-)
 create mode 100644 include/linux/dm-verity.h

diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c
index d6dbd47492a8..0d499441e780 100644
--- a/drivers/md/dm-verity-target.c
+++ b/drivers/md/dm-verity-target.c
@@ -13,12 +13,16 @@
  * access behavior.
  */
 
+#include "dm-core.h"
 #include "dm-verity.h"
 #include "dm-verity-fec.h"
 #include "dm-verity-verify-sig.h"
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 
 #define DM_MSG_PREFIX  "verity"
 
@@ -1060,6 +1064,8 @@ static int verity_ctr(struct dm_target *ti, unsigned 
argc, char **argv)
sector_t hash_position;
char dummy;
char *root_hash_digest_to_validate;
+   struct block_device *bdev;
+   struct dm_verity_digest root_digest;
 
v = kzalloc(sizeof(struct dm_verity), GFP_KERNEL);
if (!v) {
@@ -1093,6 +1099,13 @@ static int verity_ctr(struct dm_target *ti, unsigned 
argc, char **argv)
}
v->version = num;
 
+   bdev = dm_table_get_md(ti->table)->disk->part0;
+   if (!bdev) {
+   ti->error = "Mapped device lookup failed";
+   r = -ENOMEM;
+   goto bad;
+   }
+
r = dm_get_device(ti, argv[1], FMODE_READ, &v->data_dev);
if (r) {
ti->error = "Data device lookup failed";
@@ -1225,7 +1238,7 @@ static int verity_ctr(struct dm_target *ti, unsigned 
argc, char **argv)
}
 
/* Root hash signature is  a optional parameter*/
-   r = verity_verify_root_hash(root_hash_digest_to_validate,
+   r = verity_verify_root_hash(bdev, root_hash_digest_to_validate,
strlen(root_hash_digest_to_validate),
verify_args.sig,
verify_args.sig_size);
@@ -1298,12 +1311,20 @@ static int verity_ctr(struct dm_target *ti, unsigned 
argc, char **argv)
ti->per_io_data_size = roundup(ti->per_io_data_size,
   __alignof__(struct dm_verity_io));
 
+   root_digest.digest = v->root_digest;
+   root_digest.digest_len = v->digest_size;
+   root_digest.algo = v->alg_name;
+
+   r = security_bdev_setsecurity(bdev, DM_VERITY_ROOTHASH_SEC_NAME, 
&root_digest,
+ sizeof(root_digest));
+   if (r)
+   goto bad;
+
verity_verify_sig_opts_cleanup(&verify_args);
 
return 0;
 
 bad:
-
verity_verify_sig_opts_cleanup(&verify_args);
verity_dtr(ti);
 
diff --git a/drivers/md/dm-verity-verify-sig.c 
b/drivers/md/dm-verity-verify-sig.c
index db61a1f43ae9..06c15c555a4b 100644
--- a/drivers/md/dm-verity-verify-sig.c
+++ b/drivers/md/dm-verity-verify-sig.c
@@ -9,6 +9,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include "dm-core.h"
 #include "dm-verity.h"
 #include "dm-verity-verify-sig.h"
 
@@ -97,14 +

[RFC PATCH v8 09/17] ipe: introduce 'boot_verified' as a trust provider

2022-06-08 Thread Deven Bowers
IPE is designed to provide system level trust guarantees, this usually
implies that trust starts from bootup with a hardware root of trust,
which validates the bootloader. After this, the bootloader verifies the
kernel and the initramfs.

As there's no currently supported integrity method for initramfs, and
it's typically already verified by the bootloader, introduce a property
that causes the first superblock to have an execution to be "pinned",
which is typically initramfs.

Signed-off-by: Deven Bowers 

---
v2:
  + No Changes

v3:
  + Remove useless caching system
  + Move ipe_load_properties to this match
  + Minor changes from checkpatch --strict warnings

v4:
  + Remove comments from headers that was missed previously.
  + Grammatical corrections.

v5:
  + No significant changes

v6:
  + No changes

v7:
  + Reword and refactor patch 04/12 to [09/16],
based on changes in the underlying system.
  + Add common audit function for boolean values
  + Use common audit function as implementation.

v8:
  + No changes
---
 security/ipe/Kconfig |  2 +
 security/ipe/Makefile|  1 +
 security/ipe/eval.c  | 71 
 security/ipe/eval.h  |  5 ++
 security/ipe/hooks.c | 14 ++
 security/ipe/hooks.h |  2 +
 security/ipe/ipe.c   |  1 +
 security/ipe/modules.c   | 30 
 security/ipe/modules/Kconfig | 20 
 security/ipe/modules/Makefile|  8 
 security/ipe/modules/boot_verified.c | 26 ++
 security/ipe/modules/ipe_module.h|  3 ++
 12 files changed, 183 insertions(+)
 create mode 100644 security/ipe/modules/Kconfig
 create mode 100644 security/ipe/modules/Makefile
 create mode 100644 security/ipe/modules/boot_verified.c

diff --git a/security/ipe/Kconfig b/security/ipe/Kconfig
index 1ad2f34b98ec..69345fa49be5 100644
--- a/security/ipe/Kconfig
+++ b/security/ipe/Kconfig
@@ -69,4 +69,6 @@ config IPE_AUDIT_HASH_ALG
default "sha384" if IPE_AUDIT_HASH_SHA384
default "sha512" if IPE_AUDIT_HASH_SHA512
 
+source "security/ipe/modules/Kconfig"
+
 endif
diff --git a/security/ipe/Makefile b/security/ipe/Makefile
index 25a7d7c8f07c..0d970236efc4 100644
--- a/security/ipe/Makefile
+++ b/security/ipe/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_SECURITY_IPE) += \
fs.o \
hooks.o \
ipe.o \
+   modules/ \
modules.o \
parsers/ \
parsers.o \
diff --git a/security/ipe/eval.c b/security/ipe/eval.c
index eafa670558e3..ccf9b843040b 100644
--- a/security/ipe/eval.c
+++ b/security/ipe/eval.c
@@ -11,10 +11,62 @@
 #include "modules/ipe_module.h"
 #include "audit.h"
 
+#include 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
+
+static struct super_block *pinned_sb;
+static DEFINE_SPINLOCK(pin_lock);
+
+#define FILE_SUPERBLOCK(f) ((f)->f_path.mnt->mnt_sb)
+
+/**
+ * pin_sb: pin the underlying superblock of @f, marking it as trusted
+ * @f: Supplies a file structure to source the super_block from.
+ */
+static void pin_sb(const struct file *f)
+{
+   if (!f)
+   return;
+
+   spin_lock(&pin_lock);
+
+   if (pinned_sb)
+   goto out;
+
+   pinned_sb = FILE_SUPERBLOCK(f);
+
+out:
+   spin_unlock(&pin_lock);
+}
+
+/**
+ * from_pinned: determine whether @f is source from the pinned super_block.
+ * @f: Supplies a file structure to check against the pinned super_block.
+ *
+ * Return:
+ * true - @f is sourced from the pinned super_block
+ * false - @f is not sourced from the pinned super_block
+ */
+static bool from_pinned(const struct file *f)
+{
+   bool rv;
+
+   if (!f)
+   return false;
+
+   spin_lock(&pin_lock);
+
+   rv = !IS_ERR_OR_NULL(pinned_sb) && pinned_sb == FILE_SUPERBLOCK(f);
+
+   spin_unlock(&pin_lock);
+
+   return rv;
+}
 
 /**
  * build_ctx: Build an evaluation context.
@@ -40,6 +92,7 @@ static struct ipe_eval_ctx *build_ctx(const struct file *file,
ctx->file = file;
ctx->op = op;
ctx->ci_ctx = ipe_current_ctx();
+   ctx->from_init_sb = from_pinned(file);
 
return ctx;
 }
@@ -148,6 +201,9 @@ int ipe_process_event(const struct file *file, enum 
ipe_operation op)
int rc = 0;
struct ipe_eval_ctx *ctx = NULL;
 
+   if (op == ipe_operation_exec)
+   pin_sb(file);
+
ctx = build_ctx(file, op);
if (IS_ERR(ctx))
return PTR_ERR(ctx);
@@ -157,3 +213,18 @@ int ipe_process_event(const struct file *file, enum 
ipe_operation op)
free_ctx(ctx);
return rc;
 }
+
+/**
+ * ipe_invalidate_pinned_sb: if @mnt_sb is the pinned superblock, ensure
+ *  nothing can match it again.
+ * @mnt_sb: super_block to check against the pinned super_block
+ */
+void ipe_invalidate_pinned_sb(const struct super_block *mnt_sb)
+{
+   spin_lock(&pin_lock);
+
+   if (!IS_ERR_

[RFC PATCH v8 04/17] ipe: add userspace interface

2022-06-08 Thread Deven Bowers
As is typical with LSMs, IPE uses securityfs as its interface with
userspace. for a complete list of the interfaces and the respective
inputs/outputs, please see the documentation under
admin-guide/LSM/ipe.rst

Signed-off-by: Deven Bowers 

---
v2:
  + Split evaluation loop, access control hooks,
and evaluation loop from policy parser and userspace
interface to pass mailing list character limit

v3:
  + Move policy load and activation audit event to 03/12
  + Fix a potential panic when a policy failed to load.
  + use pr_warn for a failure to parse instead of an
audit record
  + Remove comments from headers
  + Add lockdep assertions to ipe_update_active_policy and
ipe_activate_policy
  + Fix up warnings with checkpatch --strict
  + Use file_ns_capable for CAP_MAC_ADMIN for securityfs
nodes.
  + Use memdup_user instead of kzalloc+simple_write_to_buffer.
  + Remove strict_parse command line parameter, as it is added
by the sysctl command line.
  + Prefix extern variables with ipe_

v4:
  + Remove securityfs to reverse-dependency
  + Add SHA1 reverse dependency.
  + Add versioning scheme for IPE properties, and associated
interface to query the versioning scheme.
  + Cause a parser to always return an error on unknown syntax.
  + Remove strict_parse option
  + Change active_policy interface from sysctl, to securityfs,
and change scheme.

v5:
  + Cause an error if a default action is not defined for each
operaiton.
  + Minor function renames

v6:
  + No changes

v7:
  + Propogating changes to support the new ipe_context structure in the
evaluation loop.

  + Further split the parser and userspace interface changes into
separate commits.

  + "raw" was renamed to "pkcs7" and made read only
  + "raw"'s write functionality (update a policy) moved to "update"
  + introduced "version", "policy_name" nodes.
  + "content" renamed to "policy"
  + changes to allow the compiled-in policy to be treated
identical to deployed-after-the-fact policies.

Introduced in v8:
  + Prevent securityfs initialization if the LSM is disabled
---
 security/ipe/Makefile   |   2 +
 security/ipe/ctx.c  | 121 +
 security/ipe/ctx.h  |   6 +
 security/ipe/fs.c   | 173 +
 security/ipe/fs.h   |  13 +
 security/ipe/ipe.c  |   3 +
 security/ipe/ipe.h  |   2 +
 security/ipe/policy.c   |  41 
 security/ipe/policy.h   |   4 +
 security/ipe/policyfs.c | 528 
 10 files changed, 893 insertions(+)
 create mode 100644 security/ipe/fs.c
 create mode 100644 security/ipe/fs.h
 create mode 100644 security/ipe/policyfs.c

diff --git a/security/ipe/Makefile b/security/ipe/Makefile
index 0db69f13e82a..d5660a17364c 100644
--- a/security/ipe/Makefile
+++ b/security/ipe/Makefile
@@ -10,9 +10,11 @@ ccflags-y := -I$(srctree)/security/ipe/modules
 obj-$(CONFIG_SECURITY_IPE) += \
ctx.o \
eval.o \
+   fs.o \
hooks.o \
ipe.o \
modules.o \
parsers/ \
parsers.o \
policy.o \
+   policyfs.o \
diff --git a/security/ipe/ctx.c b/security/ipe/ctx.c
index 97305ddc2ff7..177f60f02ed4 100644
--- a/security/ipe/ctx.c
+++ b/security/ipe/ctx.c
@@ -13,6 +13,29 @@
 #include 
 #include 
 
+/**
+ * ver_to_u64: convert an internal ipe_policy_version to a u64
+ * @p: Policy to extract the version from
+ *
+ * Bits (LSB is index 0):
+ * [48,32] -> Major
+ * [32,16] -> Minor
+ * [16, 0] -> Revision
+ *
+ * Return:
+ * u64 version of the embedded version structure.
+ */
+static inline u64 ver_to_u64(const struct ipe_policy *const p)
+{
+   u64 r = 0;
+
+   r = (((u64)p->parsed->version.major) << 32)
+ | (((u64)p->parsed->version.minor) << 16)
+ | ((u64)(p->parsed->version.rev));
+
+   return r;
+}
+
 /**
  * ipe_current_ctx: Helper to retrieve the ipe_context for the current task.
  *
@@ -80,6 +103,7 @@ static void free_ctx_work(struct work_struct *const work)
list_for_each_entry(p, &ctx->policies, next)
ipe_put_policy(p);
 
+   securityfs_remove(ctx->policy_root);
kfree(ctx);
 }
 
@@ -144,6 +168,9 @@ void ipe_remove_policy(struct ipe_policy *p)
  * ipe_add_policy: Associate @p with @ctx
  * @ctx: Supplies a pointer to the ipe_context structure to associate @p with.
  * @p: Supplies a pointer to the ipe_policy structure to associate.
+ *
+ * This will increase @p's reference count by one.
+ *
  */
 void ipe_add_policy(struct ipe_context *ctx, struct ipe_policy *p)
 {
@@ -152,7 +179,101 @@ void ipe_add_policy(struct ipe_context *ctx, struct 
ipe_policy *p)
list_add_tail(&p->next, &ctx->policies);
refcount_inc(&p->refcount);
spin_unlock(&ctx->lock);
+}
+
+/**
+ * ipe_replace_policy: Replace @old with @new in the list of policies in @ctx
+ * @ctx: Supplies the context object to manipulate.
+ * @old: Supplies a pointer to the ipe_policy to replace with @new
+ * @new: Supplies a pointer to the i

[RFC PATCH v8 08/17] ipe: add permissive toggle

2022-06-08 Thread Deven Bowers
IPE, like SELinux, supports a permissive mode. This mode allows policy
authors to test and evaluate IPE policy without it effecting their
programs. When the mode is changed, a 1423 AUDIT_TRUST_STATUS will
be reported.

Signed-off-by: Deven Bowers 

---

This patch adds the following audit records:

  type=1404 audit(1653425689.008:55): permissive=1
  type=1404 audit(1653425689.008:55): permissive=0

These records are emitted within the following events:

  type=1404 audit(1653425689.008:55): permissive=1
  type=1300 audit(1653425689.008:55): arch=c03e syscall=1
success=yes exit=2 a0=1 a1=55c1065e5c60 a2=2 a3=0 items=0 ppid=405
pid=441 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=)
  type=1327 audit(1653425689.008:55): proctitle="-bash"

---
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 into a separate commit from the
evaluation loop and audit system, for easier review.
  + Propogating changes to support the new ipe_context structure in the
evaluation loop.
  + Split out permissive functionality into a separate patch for easier
review.
  + Remove permissive switch compile-time configuration option - this
is trivial to add later.

v8:
  + Remove "IPE" prefix from permissive audit record
  + align fields to the linux-audit field dictionary. This causes the
following fields to change:
  enforce -> permissive

  + Remove duplicated information correlated with syscall record, that
will always be present in the audit event.
  + Change audit types:
+ AUDIT_TRUST_STATUS -> AUDIT_MAC_STATUS
  + There is no significant difference in meaning between
these types.
---
 security/ipe/audit.c | 43 
 security/ipe/audit.h |  5 +++
 security/ipe/ctx.c   |  6 
 security/ipe/ctx.h   |  1 +
 security/ipe/eval.c  |  6 
 security/ipe/fs.c| 78 
 6 files changed, 139 insertions(+)

diff --git a/security/ipe/audit.c b/security/ipe/audit.c
index 0442cc51a4bd..cf0ccea32c90 100644
--- a/security/ipe/audit.c
+++ b/security/ipe/audit.c
@@ -182,3 +182,46 @@ void ipe_audit_policy_load(const struct ipe_policy *const 
p)
 
audit_log_end(ab);
 }
+
+/**
+ * ipe_audit_enforce: Audit a change in IPE's enforcement state
+ * @ctx: Supplies a pointer to the contexts whose state changed.
+ */
+void ipe_audit_enforce(const struct ipe_context *const ctx)
+{
+   struct audit_buffer *ab;
+   bool enforcing = false;
+
+   ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_MAC_STATUS);
+   if (!ab)
+   return;
+
+   rcu_read_lock();
+   enforcing = READ_ONCE(ctx->enforce);
+   rcu_read_unlock();
+
+   audit_log_format(ab, "permissive=%d", !enforcing);
+
+   audit_log_end(ab);
+}
+
+/**
+ * emit_enforcement: Emit the enforcement state of IPE started with.
+ *
+ * Return:
+ * 0 - Always
+ */
+static int emit_enforcement(void)
+{
+   struct ipe_context *ctx = NULL;
+
+   if (!ipe_enabled)
+   return -EOPNOTSUPP;
+
+   ctx = ipe_current_ctx();
+   ipe_audit_enforce(ctx);
+   ipe_put_ctx(ctx);
+   return 0;
+}
+
+late_initcall(emit_enforcement);
diff --git a/security/ipe/audit.h b/security/ipe/audit.h
index bec03208042d..daff9c801a8e 100644
--- a/security/ipe/audit.h
+++ b/security/ipe/audit.h
@@ -15,6 +15,7 @@ void ipe_audit_match(const struct ipe_eval_ctx *const ctx,
 enum ipe_action act, const struct ipe_rule *const r);
 void ipe_audit_policy_load(const struct ipe_policy *const p);
 void ipe_audit_policy_activation(const struct ipe_policy *const p);
+void ipe_audit_enforce(const struct ipe_context *const ctx);
 #else
 static inline void ipe_audit_match(const struct ipe_eval_ctx *const ctx,
   enum ipe_match match_type,
@@ -29,6 +30,10 @@ static inline void ipe_audit_policy_load(const struct 
ipe_policy *const p)
 static inline void ipe_audit_policy_activation(const st

[RFC PATCH v8 17/17] documentation: add ipe documentation

2022-06-08 Thread Deven Bowers
Add IPE's admin and developer documentation to the kernel tree.

Co-developed-by: Fan Wu 
Signed-off-by: Fan Wu 
Signed-off-by: Deven Bowers 
---
v2:
  + No Changes

v3:
  + Add Acked-by
  + Fixup code block syntax
  + Fix a minor grammatical issue.

v4:
  + Update documentation with the results of other
code changes.

v5:
  + No changes

v6:
  + No changes

v7:
  + Add additional developer-level documentation
  + Update admin-guide docs to reflect changes.
  + Drop Acked-by due to significant changes
  + Added section about audit events in admin-guide

v8:
  + Correct terminology from "audit event" to "audit record"
  + Add associated documentation with the correct "audit event"
terminology.
  + Add some context to the historical motivation for IPE and design
philosophy.
  + Add some content about the securityfs layout in the policies
directory.
  + Various spelling and grammatical corrections.
---
 Documentation/admin-guide/LSM/index.rst   |   1 +
 Documentation/admin-guide/LSM/ipe.rst | 739 ++
 .../admin-guide/kernel-parameters.txt |  12 +
 Documentation/security/index.rst  |   1 +
 Documentation/security/ipe.rst| 559 +
 MAINTAINERS   |   2 +
 6 files changed, 1314 insertions(+)
 create mode 100644 Documentation/admin-guide/LSM/ipe.rst
 create mode 100644 Documentation/security/ipe.rst

diff --git a/Documentation/admin-guide/LSM/index.rst 
b/Documentation/admin-guide/LSM/index.rst
index a6ba95fbaa9f..ce63be6d64ad 100644
--- a/Documentation/admin-guide/LSM/index.rst
+++ b/Documentation/admin-guide/LSM/index.rst
@@ -47,3 +47,4 @@ subdirectories.
tomoyo
Yama
SafeSetID
+   ipe
diff --git a/Documentation/admin-guide/LSM/ipe.rst 
b/Documentation/admin-guide/LSM/ipe.rst
new file mode 100644
index ..58335ce4f85b
--- /dev/null
+++ b/Documentation/admin-guide/LSM/ipe.rst
@@ -0,0 +1,739 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Integrity Policy Enforcement (IPE)
+==
+
+.. NOTE::
+
+   This is the documentation for admins, system builders, or individuals
+   attempting to use IPE. If you're looking for more developer-focused
+   documentation about IPE please see `Documentation/security/ipe.rst`
+
+Overview
+
+
+IPE is a Linux Security Module which takes a complimentary approach to
+access control. Whereas existing mandatory access control mechanisms
+base their decisions on labels and paths, IPE instead determines
+whether or not an operation should be allowed based on immutable
+security properties of the system component the operation is being
+performed on.
+
+IPE itself does not mandate how the security property should be
+evaluated, but relies on an extensible set of external property providers
+to evaluate the component. IPE makes its decision based on reference
+values for the selected properties, specified in the IPE policy.
+
+The reference values represent the value that the policy writer and the
+local system administrator (based on the policy signature) trust for the
+system to accomplish the desired tasks.
+
+One such provider is for example dm-verity, which is able to represent
+the integrity property of a partition (its immutable state) with a digest.
+
+IPE is compiled under ``CONFIG_SECURITY_IPE`` (Security -> Integrity Policy 
Enforcement (IPE)).
+
+Use Cases
+-
+
+IPE works best in fixed-function devices: devices in which their purpose
+is clearly defined and not supposed to be changed (e.g. network firewall
+device in a data center, an IoT device, etcetera), where all software and
+configuration is built and provisioned by the system owner.
+
+IPE is a long-way off for use in general-purpose computing: the Linux
+community as a whole tends to follow a decentralized trust model,
+known as the web of trust, which IPE has no support for as of yet.
+
+IPE, instead of supporting web of trust, supports PKI, which generally
+designates a set of entities that provide a measure of absolute trust.
+
+Additionally, while most packages are signed today, the files inside
+the packages (for instance, the executables), tend to be unsigned. This
+makes it difficult to utilize IPE in systems where a package manager is
+expected to be functional, without major changes to the package manager
+and ecosystem behind it.
+
+DIGLIM [#diglim]_ is a system that when combined with IPE, could be used to
+enable general purpose computing scenarios.
+
+Known Gaps
+--
+
+IPE cannot verify the integrity of anonymous executable memory, such as
+the trampolines created by gcc closures and libffi (<3.4.2), or JIT'd code.
+Unfortunately, as this is dynamically generated code, there is no way
+for IPE to ensure the integrity of this code to form a trust basis. In all
+cases, the return result for these operations will be whatever the admin
+configures as the ``DEFAULT`` action for ``EXECUTE``.
+
+IPE cannot verify the integrity o

[RFC PATCH v8 00/17] Integrity Policy Enforcement LSM (IPE)

2022-06-08 Thread Deven Bowers
Overview:
-

IPE is a Linux Security Module which takes a complimentary approach to
access control. Whereas existing mandatory access control mechanisms
base their decisions on labels and paths, IPE instead determines
whether or not an operation should be allowed based on immutable
security properties of the system component the operation is being
performed on.

IPE itself does not mandate how the security property should be
evaluated, but relies on an extensible set of external property providers
to evaluate the component. IPE makes its decision based on reference
values for the selected properties, specified in the IPE policy.

The reference values represent the value that the policy writer and the
local system administrator (based on the policy signature) trust for the
system to accomplish the desired tasks.

One such provider is for example dm-verity, which is able to represent
the integrity property of a partition (its immutable state) with a digest.

IPE is compiled under CONFIG_SECURITY_IPE.

Use Cases
-

IPE works best in fixed-function devices: Devices in which their purpose
is clearly defined and not supposed to be changed (e.g. network firewall
device in a data center, an IoT device, etcetera), where all software and
configuration is built and provisioned by the system owner.

IPE is a long-way off for use in general-purpose computing: the Linux
community as a whole tends to follow a decentralized trust model,
known as the web of trust, which IPE has no support for as of yet.

There are exceptions, to this general-purpose computing rule; however,
such as the scenario, wherein Linux distribution vendors trust only
their own keys - in this case, IPE can be used to enforce the trust
reqiurement.

IPE, instead of supporting web of trust, supports PKI, which generally
designates a set of entities that provide a measure absolute trust.
Commonly used in embedded systems, 

Additionally, while most packages are signed today, the files inside
the packages (for instance, the executables), tend to be unsigned. This
makes it difficult to utilize IPE in systems where a package manager is
expected to be functional, without major changes to the package manager
and ecosystem behind it.

DIGLIM[1] is a system that when combined with IPE, could be used to
enable general purpose computing scenarios.

Policy:
---

IPE policy is a plain-text policy composed of multiple statements
over several lines. There is one required line, at the top of the
policy, indicating the policy name, and the policy version, for
instance:

  policy_name="Ex Policy" policy_version=0.0.0

The policy version indicates the current version of the policy (NOT the
policy syntax version). This is used to prevent roll-back of policy to
potentially insecure previous versions of the policy.

The next portion of IPE policy, are rules. Rules are formed by key=value
pairs, known as properties. IPE rules require two keys: "action", which
determines what IPE does when it encounters a match against the policy
 and "op", which determines when that rule should be evaluated.

Thus, a minimal rule is:

  op=EXECUTE action=ALLOW

This example will allow any execution. Additional properties are used to
restrict attributes about the files being evaluated. These properties are
intended to be deterministic attributes that are resident in the kernel.
Available properties for IPE described in the documentation patch of this
series.

A rule is required to have the "op" property as the first token of a rule,
and the "action" as the last token of the rule. Rules are evaluated
top-to-bottom. As a result, any revocation rules, or denies should be
placed early in the file to ensure that these rules are evaluated before
a rule with "action=ALLOW" is hit.

Any unknown syntax in IPE policy will result in a fatal error to parse
the policy. User mode can interrogate the kernel to understand what
properties and the associated versions through the securityfs node,
$securityfs/ipe/config, which will return a string of form:

  key1=version1
  key2=version2
  .
  .
  .
  keyN=versionN

User-mode should correlate these versions with the supported values
identified in the documentation to determine whether a policy should
be accepted by the system without actually trying to deploy the policy.

Additionally, a DEFAULT operation must be set for all understood
operations within IPE. For policies to remain completely forwards
compatible, it is recommended that users add a "DEFAULT action=ALLOW"
and override the defaults on a per-operation basis.

For more information about the policy syntax, see the kernel
documentation page.

Early Usermode Protection:
--

IPE can be provided with a policy at startup to load and enforce.
This is intended to be a minimal policy to get the system to a state
where userland is setup and ready to receive commands, at which
point a policy can be deployed via securityfs. This "boot policy" can be
specified via the 

[RFC PATCH v8 02/17] ipe: add policy parser

2022-06-08 Thread Deven Bowers
IPE's interpretation of the what the user trusts is accomplished through
its policy. IPE's design is to not provide support for a single trust
provider, but to support multiple providers to enable the end-user to
choose the best one to seek their needs.

This requires the policy to be rather flexible and modular so that
integrity providers, like fs-verity, dm-verity, dm-integrity, or
some other system, can plug into the policy with minimal code changes,
and IPE can

Signed-off-by: Deven Bowers 

---
v2:
  + Split evaluation loop, access control hooks,
and evaluation loop from policy parser and userspace
interface to pass mailing list character limit

v3:
  + Move policy load and activation audit event to 03/12
  + Fix a potential panic when a policy failed to load.
  + use pr_warn for a failure to parse instead of an
audit record
  + Remove comments from headers
  + Add lockdep assertions to ipe_update_active_policy and
ipe_activate_policy
  + Fix up warnings with checkpatch --strict
  + Use file_ns_capable for CAP_MAC_ADMIN for securityfs
nodes.
  + Use memdup_user instead of kzalloc+simple_write_to_buffer.
  + Remove strict_parse command line parameter, as it is added
by the sysctl command line.
  + Prefix extern variables with ipe_

v4:
  + Remove securityfs to reverse-dependency
  + Add SHA1 reverse dependency.
  + Add versioning scheme for IPE properties, and associated
interface to query the versioning scheme.
  + Cause a parser to always return an error on unknown syntax.
  + Remove strict_parse option
  + Change active_policy interface from sysctl, to securityfs,
and change scheme.

v5:
  + Cause an error if a default action is not defined for each
operaiton.
  + Minor function renames

v6:
  + No changes

v7:
  + Further split parser and userspace interface into two
separate commits, for easier review.

  + Refactor policy parser to make code cleaner via introducing a
more modular design, for easier extension of policy, and
easier review.

v8:
  + remove unnecessary pr_info emission on parser loading

  + add explicit newline to the pr_err emitted when a parser
fails to load.
---
 include/asm-generic/vmlinux.lds.h|  16 +
 security/ipe/Makefile|   6 +
 security/ipe/ipe.c   |  61 ++
 security/ipe/ipe.h   |   5 +
 security/ipe/ipe_parser.h|  59 ++
 security/ipe/modules.c   | 109 +++
 security/ipe/modules.h   |  17 +
 security/ipe/modules/ipe_module.h|  33 +
 security/ipe/parsers.c   | 143 
 security/ipe/parsers/Makefile|  12 +
 security/ipe/parsers/default.c   | 106 +++
 security/ipe/parsers/policy_header.c | 126 
 security/ipe/policy.c| 946 +++
 security/ipe/policy.h|  97 +++
 14 files changed, 1736 insertions(+)
 create mode 100644 security/ipe/ipe_parser.h
 create mode 100644 security/ipe/modules.c
 create mode 100644 security/ipe/modules.h
 create mode 100644 security/ipe/modules/ipe_module.h
 create mode 100644 security/ipe/parsers.c
 create mode 100644 security/ipe/parsers/Makefile
 create mode 100644 security/ipe/parsers/default.c
 create mode 100644 security/ipe/parsers/policy_header.c
 create mode 100644 security/ipe/policy.c
 create mode 100644 security/ipe/policy.h

diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 7515a465ec03..8549b98d0cf6 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -284,6 +284,20 @@
 #define EARLY_LSM_TABLE()
 #endif
 
+#ifdef CONFIG_SECURITY_IPE
+#define IPE_PARSER_TABLE() . = ALIGN(8);   \
+   __start_ipe_parsers = .;\
+   KEEP(*(.ipe_parsers))   \
+   __end_ipe_parsers = .;
+#define IPE_MODULE_TABLE() . = ALIGN(8);   \
+   __start_ipe_modules = .;\
+   KEEP(*(.ipe_modules))   \
+   __end_ipe_modules = .;
+#else
+#define IPE_PARSER_TABLE()
+#define IPE_MODULE_TABLE()
+#endif
+
 #define ___OF_TABLE(cfg, name) _OF_TABLE_##cfg(name)
 #define __OF_TABLE(cfg, name)  ___OF_TABLE(cfg, name)
 #define OF_TABLE(cfg, name)__OF_TABLE(IS_ENABLED(cfg), name)
@@ -436,6 +450,8 @@
KEEP(*(__tracepoints_ptrs)) /* Tracepoints: pointer array */ \
__stop___tracepoints_ptrs = .;  \
*(__tracepoints_strings)/* Tracepoints: strings */  \
+   IPE_PARSER_TABLE()  \
+   IPE_MODULE_TABLE()  \
}   \
\

[RFC PATCH v8 12/17] ipe: add support for dm-verity as a trust provider

2022-06-08 Thread Deven Bowers
Allows author of IPE policy to indicate trust for a singular dm-verity
volume, identified by roothash, through "dmverity_roothash" and all
signed dm-verity volumes, through "dmverity_signature".

Signed-off-by: Deven Bowers 
---
v2:
  + No Changes

v3:
  + No changes

v4:
  + No changes

v5:
  + No changes

v6:
  + Fix an improper cleanup that can result in
a leak

v7:
  + Squash patch 08/12, 10/12 to [11/16]

v8:
  + Undo squash of 08/12, 10/12 - separating drivers/md/ from security/ & block/
  + Use common-audit function for dmverity_signature.
  + Change implementation for storing the dm-verity digest to use the
newly introduced dm_verity_digest structure introduced in patch
14/20.
---
 security/ipe/eval.c   |   5 +
 security/ipe/eval.h   |  11 ++
 security/ipe/hooks.c  |  51 +
 security/ipe/hooks.h  |   6 +
 security/ipe/ipe.c|   9 ++
 security/ipe/ipe.h|   3 +
 security/ipe/modules.c| 133 ++
 security/ipe/modules/Kconfig  |  23 
 security/ipe/modules/Makefile |   2 +
 security/ipe/modules/dmverity_roothash.c  |  31 +
 security/ipe/modules/dmverity_signature.c |  26 +
 security/ipe/modules/ipe_module.h |   5 +
 12 files changed, 305 insertions(+)
 create mode 100644 security/ipe/modules/dmverity_roothash.c
 create mode 100644 security/ipe/modules/dmverity_signature.c

diff --git a/security/ipe/eval.c b/security/ipe/eval.c
index ccf9b843040b..9b29d83cd466 100644
--- a/security/ipe/eval.c
+++ b/security/ipe/eval.c
@@ -23,6 +23,7 @@ static struct super_block *pinned_sb;
 static DEFINE_SPINLOCK(pin_lock);
 
 #define FILE_SUPERBLOCK(f) ((f)->f_path.mnt->mnt_sb)
+#define FILE_BLOCK_DEV(f) (FILE_SUPERBLOCK(f)->s_bdev)
 
 /**
  * pin_sb: pin the underlying superblock of @f, marking it as trusted
@@ -93,6 +94,10 @@ static struct ipe_eval_ctx *build_ctx(const struct file 
*file,
ctx->op = op;
ctx->ci_ctx = ipe_current_ctx();
ctx->from_init_sb = from_pinned(file);
+   if (file) {
+   if (FILE_BLOCK_DEV(file))
+   ctx->ipe_bdev = ipe_bdev(FILE_BLOCK_DEV(file));
+   }
 
return ctx;
 }
diff --git a/security/ipe/eval.h b/security/ipe/eval.h
index f195671eaa8f..57b7b2b424f8 100644
--- a/security/ipe/eval.h
+++ b/security/ipe/eval.h
@@ -8,17 +8,28 @@
 
 #include 
 #include 
+#include 
 
 #include "ctx.h"
 #include "hooks.h"
 #include "policy.h"
 
+struct ipe_bdev {
+   bool dm_verity_signed;
+
+   const u8   *digest;
+   size_t  digest_len;
+   const char *digest_algo;
+};
+
 struct ipe_eval_ctx {
enum ipe_operation op;
 
const struct file *file;
struct ipe_context *ci_ctx;
 
+   const struct ipe_bdev *ipe_bdev;
+
bool from_init_sb;
 };
 
diff --git a/security/ipe/hooks.c b/security/ipe/hooks.c
index 4dc7b0c0fd31..1072ee5bb8f6 100644
--- a/security/ipe/hooks.c
+++ b/security/ipe/hooks.c
@@ -13,8 +13,11 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include 
+#include 
 
 /**
  * ipe_task_alloc: Assign a new context for an associated task structure.
@@ -216,3 +219,51 @@ void ipe_sb_free_security(struct super_block *mnt_sb)
 {
ipe_invalidate_pinned_sb(mnt_sb);
 }
+
+/**
+ * ipe_bdev_free_security: free nested structures within IPE's LSM blob
+ *in block_devices
+ * @bdev: Supplies a pointer to a block_device that contains the structure
+ *   to free.
+ */
+void ipe_bdev_free_security(struct block_device *bdev)
+{
+   struct ipe_bdev *blob = ipe_bdev(bdev);
+
+   kfree(blob->digest);
+   kfree(blob->digest_algo);
+}
+
+/**
+ * ipe_bdev_setsecurity: associate some data from the block device layer
+ *  with IPE's LSM blob.
+ * @bdev: Supplies a pointer to a block_device that contains the LSM blob.
+ * @key: Supplies the string key that uniquely identifies the value.
+ * @value: Supplies the value to store.
+ * @len: The length of @value.
+ */
+int ipe_bdev_setsecurity(struct block_device *bdev, const char *key,
+const void *value, size_t len)
+{
+   struct ipe_bdev *blob = ipe_bdev(bdev);
+
+   if (!strcmp(key, DM_VERITY_ROOTHASH_SEC_NAME)) {
+   const struct dm_verity_digest *digest = value;
+
+   blob->digest = kmemdup(digest->digest, digest->digest_len, 
GFP_KERNEL);
+   if (!blob->digest)
+   return -ENOMEM;
+
+   blob->digest_algo = kstrdup_const(digest->algo, GFP_KERNEL);
+   if (!blob->digest_algo)
+   return -ENOMEM;
+
+   blob->digest_len = digest->digest_len;
+   return 0;
+   } else if (!strcmp(key, DM_VERITY_SIGNATURE_SEC_NAME)) {
+   blob->dm_verity_signed = true;
+   return 

[RFC PATCH v8 03/17] ipe: add evaluation loop

2022-06-08 Thread Deven Bowers
IPE must have a centralized function to evaluate incoming callers
against IPE's policy. This iteration of the policy for against the rules
for that specific caller is known as the evaluation loop.

Signed-off-by: Deven Bowers 

---
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 into a separate commit from the
evaluation loop and audit system, for easier review.

  + Propogating changes to support the new ipe_context structure in the
evaluation loop.

Introduced in v8:
  + Remove ipe_hook enumeration; hooks can be correlated via syscall
record.
---
 security/ipe/Makefile |   1 +
 security/ipe/ctx.c|  59 +++-
 security/ipe/ctx.h|   6 ++
 security/ipe/eval.c   | 144 ++
 security/ipe/eval.h   |  24 +
 security/ipe/modules/ipe_module.h |   3 +
 security/ipe/policy.c |  27 ++
 security/ipe/policy.h |   4 +
 8 files changed, 267 insertions(+), 1 deletion(-)
 create mode 100644 security/ipe/eval.c
 create mode 100644 security/ipe/eval.h

diff --git a/security/ipe/Makefile b/security/ipe/Makefile
index 9a97efd8a190..0db69f13e82a 100644
--- a/security/ipe/Makefile
+++ b/security/ipe/Makefile
@@ -9,6 +9,7 @@ ccflags-y := -I$(srctree)/security/ipe/modules
 
 obj-$(CONFIG_SECURITY_IPE) += \
ctx.o \
+   eval.o \
hooks.o \
ipe.o \
modules.o \
diff --git a/security/ipe/ctx.c b/security/ipe/ctx.c
index d51fe2e13ad9..97305ddc2ff7 100644
--- a/security/ipe/ctx.c
+++ b/security/ipe/ctx.c
@@ -5,6 +5,7 @@
 
 #include "ipe.h"
 #include "ctx.h"
+#include "policy.h"
 
 #include 
 #include 
@@ -60,10 +61,25 @@ struct ipe_context *ipe_get_ctx_rcu(struct ipe_context 
__rcu *ctx)
  */
 static void free_ctx_work(struct work_struct *const work)
 {
+   struct ipe_policy *p = NULL;
struct ipe_context *ctx = NULL;
 
ctx = container_of(work, struct ipe_context, free_work);
 
+   /* Make p->ctx no longer have any references */
+   spin_lock(&ctx->lock);
+   list_for_each_entry(p, &ctx->policies, next)
+   rcu_assign_pointer(p->ctx, NULL);
+   spin_unlock(&ctx->lock);
+   synchronize_rcu();
+
+   /*
+* locking no longer necessary - nothing can get a reference to ctx,
+* so list is guaranteed stable.
+*/
+   list_for_each_entry(p, &ctx->policies, next)
+   ipe_put_policy(p);
+
kfree(ctx);
 }
 
@@ -88,6 +104,7 @@ static struct ipe_context *create_ctx(void)
}
 
INIT_WORK(&ctx->free_work, free_ctx_work);
+   INIT_LIST_HEAD(&ctx->policies);
refcount_set(&ctx->refcount, 1);
spin_lock_init(&ctx->lock);
 
@@ -98,9 +115,49 @@ static struct ipe_context *create_ctx(void)
return ERR_PTR(rc);
 }
 
+/**
+ * remove_policy: Remove a policy from its context
+ * @p: Supplies a pointer to a policy that will be removed from its context
+ *
+ * Decrements @p's reference by 1.
+ */
+void ipe_remove_policy(struct ipe_policy *p)
+{
+   struct ipe_context *ctx;
+
+   ctx = ipe_get_ctx_rcu(p->ctx);
+   if (!ctx)
+   return;
+
+   spin_lock(&ctx->lock);
+   list_del_init(&p->next);
+   rcu_assign_pointer(p->ctx, NULL);
+   spin_unlock(&ctx->lock);
+   synchronize_rcu();
+
+   ipe_put_ctx(ctx);
+   /* drop the reference representing the list */
+   ipe_put_policy(p);
+}
+
+/**
+ * ipe_add_policy: Associate @p with @ctx
+ * @ctx: Supplies a pointer to the ipe_context structure to associate @p with.
+ * @p: Supplies a pointer to the ipe_policy structure to associate.
+ */
+void ipe_add_policy(struct ipe_context *ctx, struct ipe_policy *p)
+{
+   spin_lock(&ctx->lock);
+   rcu_assign_pointer(p->ctx, ctx);
+   list_add_tail(&p->next, &ctx->policies);
+   refcount_inc(&p->refcount);
+   spin_unlock(&ctx->lock);
+   synchronize_rcu();
+}
+
 /**
  * ipe_put_ctx: Decremen

[RFC PATCH v8 13/17] fsverity: consume builtin signature via LSM hook

2022-06-08 Thread Deven Bowers
From: Fan Wu 

fsverity represents a mechanism to support both integrity and
authenticity protection of a file, supporting both signed and unsigned
digests.

An LSM which controls access to a resource based on authenticity and
integrity of said resource, can then use this data to make an informed
decision on the authorization (provided by the LSM's policy) of said
claim.

This effectively allows the extension of a policy enforcement layer in
LSM for fsverity, allowing for more granular control of how a
particular authenticity claim can be used. For example, "all (built-in)
signed fsverity files should be allowed to execute, but only these
hashes are allowed to be loaded as kernel modules".

This enforcement must be done in kernel space, as a userspace only
solution would fail a simple litmus test: Download a self-contained
malicious binary that never touches the userspace stack. This
binary would still be able to execute.

Signed-off-by: Fan Wu 
Signed-off-by: Deven Bowers 
---
v1-v6:
  + Not present

v7:
  Introduced

v8:
  + Split fs/verity/ changes and security/ changes into separate patches
  + Change signature of fsverity_create_info to accept non-const inode
  + Change signature of fsverity_verify_signature to accept non-const inode
  + Don't cast-away const from inode.
  + Digest functionality dropped in favor of:
("fs-verity: define a function to return the integrity protected
  file digest")
  + Reworded commit description and title to match changes.
  + Fix a bug wherein no LSM implements the particular fsverity @name
(or LSM is disabled), and returns -EOPNOTSUPP, causing errors.
---
 fs/verity/fsverity_private.h |  2 +-
 fs/verity/open.c | 13 -
 fs/verity/signature.c|  1 +
 include/linux/fsverity.h |  2 ++
 4 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/fs/verity/fsverity_private.h b/fs/verity/fsverity_private.h
index 629785c95007..e0d70235bbdc 100644
--- a/fs/verity/fsverity_private.h
+++ b/fs/verity/fsverity_private.h
@@ -114,7 +114,7 @@ int fsverity_init_merkle_tree_params(struct 
merkle_tree_params *params,
 unsigned int log_blocksize,
 const u8 *salt, size_t salt_size);
 
-struct fsverity_info *fsverity_create_info(const struct inode *inode,
+struct fsverity_info *fsverity_create_info(struct inode *inode,
   struct fsverity_descriptor *desc);
 
 void fsverity_set_info(struct inode *inode, struct fsverity_info *vi);
diff --git a/fs/verity/open.c b/fs/verity/open.c
index 81ff94442f7b..7e6fa52c0e9c 100644
--- a/fs/verity/open.c
+++ b/fs/verity/open.c
@@ -7,7 +7,9 @@
 
 #include "fsverity_private.h"
 
+#include 
 #include 
+#include 
 
 static struct kmem_cache *fsverity_info_cachep;
 
@@ -146,7 +148,7 @@ static int compute_file_digest(struct fsverity_hash_alg 
*hash_alg,
  * appended signature), and check the signature if present.  The
  * fsverity_descriptor must have already undergone basic validation.
  */
-struct fsverity_info *fsverity_create_info(const struct inode *inode,
+struct fsverity_info *fsverity_create_info(struct inode *inode,
   struct fsverity_descriptor *desc)
 {
struct fsverity_info *vi;
@@ -182,6 +184,15 @@ struct fsverity_info *fsverity_create_info(const struct 
inode *inode,
 
err = fsverity_verify_signature(vi, desc->signature,
le32_to_cpu(desc->sig_size));
+   if (err) {
+   fsverity_err(inode, "Error %d verifying signature", err);
+   goto out;
+   }
+
+   err = security_inode_setsecurity(inode, FS_VERITY_INODE_SEC_NAME, 
desc->signature,
+le32_to_cpu(desc->sig_size), 0);
+   if (err == -EOPNOTSUPP)
+   err = 0;
 out:
if (err) {
fsverity_free_info(vi);
diff --git a/fs/verity/signature.c b/fs/verity/signature.c
index 143a530a8008..5d7b9496f9c4 100644
--- a/fs/verity/signature.c
+++ b/fs/verity/signature.c
@@ -9,6 +9,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 
diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h
index 7af030fa3c36..f37936b56150 100644
--- a/include/linux/fsverity.h
+++ b/include/linux/fsverity.h
@@ -251,4 +251,6 @@ static inline bool fsverity_active(const struct inode 
*inode)
return fsverity_get_info(inode) != NULL;
 }
 
+#define FS_VERITY_INODE_SEC_NAME "fsverity.inode-info"
+
 #endif /* _LINUX_FSVERITY_H */
-- 
2.25.1

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



[RFC PATCH v8 07/17] ipe: add auditing support

2022-06-08 Thread Deven Bowers
Users of IPE require a way to identify when and why an operation fails,
allowing them to both respond to violations of policy and be notified
of potentially malicious actions on their systens with respect to IPE
itself.

The new 1420 audit, AUDIT_IPE_ACCESS indicates the result of a policy
evaulation of a resource. The other two events, AUDIT_MAC_POLICY_LOAD,
and AUDIT_MAC_CONFIG_CHANGE represent a new policy was loaded into the
kernel and the currently active policy changed, respectively.

This patch also adds support for success auditing, allowing users to
identify how a resource passed policy. It is recommended to use this
option with caution, as it is quite noisy.

Signed-off-by: Deven Bowers 
---

This patch adds the following audit records:

  type=1420 audit(1653364735.161:64):
rule="DEFAULT op=EXECUTE action=DENY"

  type=1420 audit(1653364370.067:61): path="/root/fs/rw/plain/execve"
dev="vdc1" ino=16 rule="DEFAULT op=EXECUTE action=DENY"

  type=1405 audit(1653425583.136:54): policy_name="dmverity_roothash"
policy_version=0.0.0 
sha256=A9C5803309F80D2B84D7C047534BE8B60EF121C8E1F351F2A8EFFA617B7F0686

  type=1403 audit(1653425529.927:53): policy_name="dmverity_roothash"
policy_version=0.0.0 
sha256=A9C5803309F80D2B84D7C047534BE8B60EF121C8E1F351F2A8EFFA617B7F0686

This results in the following events (the audit records are always
prior to a SYSCALL record):

  type=1420 audit(1653364735.161:64):
rule="DEFAULT op=EXECUTE action=DENY"
  type=1300 audit(1653364735.161:64): arch=c03e syscall=9
success=no exit=-13 a0=0 a1=1000 a2=4 a3=20 items=0 ppid=455 pid=774
auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0
tty=ttyS0 ses=3 comm="mmap" exe="/root/host/mmap" subj=kernel
key=(null)
  audit: type=1327 audit(1653364735.161:64):
proctitle=686F73742F6D6D617000410058

  type=1420 audit(1653364370.067:61): path="/root/fs/rw/plain/execve"
dev="vdc1" ino=16 rule="DEFAULT op=EXECUTE action=DENY"
  type=1300 audit(1653364370.067:61): arch=c03e syscall=10
success=no exit=-13 a0=7f0bf0644000 a1=4f80 a2=5 a3=7f0bf043d300
items=0 ppid=455 pid=737 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0
egid=0 sgid=0 fsgid=0 tty=ttyS0 ses=3 comm="mprotect"
exe="/root/host/mprotect" subj=kernel key=(null)
  type=1327 audit(1653364370.067:61):

proctitle=686F73742F6D70726F7465637400534800527C5700527C5800706C61696E2F657865637665

  type=1403 audit(1653425529.927:53): policy_name="dmverity_roothash"
policy_version=0.0.0 
sha256=A9C5803309F80D2B84D7C047534BE8B60EF121C8E1F351F2A8EFFA617B7F0686
  type=1300 audit(1653425529.927:53): arch=c03e syscall=1
success=yes exit=6215 a0=1 a1=7f07adfe4000 a2=1847 a3=22 items=0
ppid=441 pid=445 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=)
  type=1327 audit(1653425529.927:53):

proctitle=63617400706F6C69636965732F646D7665726974795F726F6F74686173682E706F6C2E703762

  type=1405 audit(1653425583.136:54): policy_name="dmverity_roothash"
policy_version=0.0.0 
sha256=A9C5803309F80D2B84D7C047534BE8B60EF121C8E1F351F2A8EFFA617B7F0686
  type=1300 audit(1653425583.136:54): arch=c03e syscall=1 success=yes
exit=2 a0=1 a1=55c1065e5c60 a2=2 a3=7fe683990020 items=0 ppid=405
pid=441 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 e)
  type=1327 audit(1653425583.136:54): proctitle="-bash"

---
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 patches.
  + Further split audit system patch into two separate patches; one
for include/uapi, and the usage of the new defines.
  + Split out the permissive functionality into another separate patch,
for easier review.
  + Correct misuse of audit_log_n_untrusted string to audit_log_format
  + Use get_task_comm instead of comm directly.
  + Quote certain audit values
  + Remove unnecessary help text on choice options - these were previously
idented at the wrong level
  + Corre

Re: [RFC PATCH v8 00/17] Integrity Policy Enforcement LSM (IPE)

2022-06-08 Thread Matthew Wilcox
On Wed, Jun 08, 2022 at 12:01:12PM -0700, Deven Bowers wrote:
> IPE is a Linux Security Module which takes a complimentary approach to

Hello, IPE.  You're looking exceptionally attractive today.  Have you
been working out?

(maybe you meant "complementary"?  ;-)

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



Re: [RFC PATCH v8 00/17] Integrity Policy Enforcement LSM (IPE)

2022-06-08 Thread Deven Bowers
On Wed, Jun 08, 2022 at 08:10:58PM +0100, Matthew Wilcox wrote:
> On Wed, Jun 08, 2022 at 12:01:12PM -0700, Deven Bowers wrote:
> > IPE is a Linux Security Module which takes a complimentary approach to
> 
> Hello, IPE.  You're looking exceptionally attractive today.  Have you
> been working out?

Not nearly as often as I'd like to :)

> 
> (maybe you meant "complementary"?  ;-)

Yes, thanks. Sorry for the misspelling.


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



Re: [RFC PATCH v8 10/17] block|security: add LSM blob to block_device

2022-06-08 Thread Casey Schaufler

On 6/8/2022 12:01 PM, Deven Bowers wrote:

block_device structures can have valuable security properties,
based on how they are created, and what subsystem manages them.

By adding LSM storage to this structure, this data can be accessed
at the LSM layer.

Signed-off-by: Deven Bowers 


Reviewed-by: Casey Schaufler 

Not everyone is going to appreciate the infrastructure allocation
of the block_device security blob, but I do.



---
v2:
   + No Changes

v3:
   + Minor style changes from checkpatch --strict

v4:
   + No Changes

v5:
   + Allow multiple callers to call security_bdev_setsecurity

v6:
   + Simplify security_bdev_setsecurity break condition

v7:
   + Squash all dm-verity related patches to two patches,
 the additions to dm-verity/fs, and the consumption of
 the additions.

v8:
   + Split dm-verity related patches squashed in v7 to 3 commits based on
 topic:
   + New LSM hook
   + Consumption of hook outside LSM
   + Consumption of hook inside LSM.

   + change return of security_bdev_alloc / security_bdev_setsecurity
 to LSM_RET_DEFAULT instead of 0.

   + Change return code to -EOPNOTSUPP, bring inline with other
 setsecurity hooks.
---
  block/bdev.c  |  7 
  include/linux/blk_types.h |  1 +
  include/linux/lsm_hook_defs.h |  5 +++
  include/linux/lsm_hooks.h | 12 ++
  include/linux/security.h  | 22 +++
  security/security.c   | 70 +++
  6 files changed, 117 insertions(+)

diff --git a/block/bdev.c b/block/bdev.c
index 5fe06c1f2def..e7ef2c7a22c9 100644
--- a/block/bdev.c
+++ b/block/bdev.c
@@ -24,6 +24,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include "../fs/internal.h"
@@ -397,6 +398,11 @@ static struct inode *bdev_alloc_inode(struct super_block 
*sb)
if (!ei)
return NULL;
memset(&ei->bdev, 0, sizeof(ei->bdev));
+
+   if (unlikely(security_bdev_alloc(&ei->bdev))) {
+   kmem_cache_free(bdev_cachep, ei);
+   return NULL;
+   }
return &ei->vfs_inode;
  }
  
@@ -406,6 +412,7 @@ static void bdev_free_inode(struct inode *inode)
  
  	free_percpu(bdev->bd_stats);

kfree(bdev->bd_meta_info);
+   security_bdev_free(bdev);
  
  	if (!bdev_is_partition(bdev)) {

if (bdev->bd_disk && bdev->bd_disk->bdi)
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index a24d4078fb21..a014ffa14b2d 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -68,6 +68,7 @@ struct block_device {
  #ifdef CONFIG_FAIL_MAKE_REQUEST
boolbd_make_it_fail;
  #endif
+   void*security;
  } __randomize_layout;
  
  #define bdev_whole(_bdev) \

diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
index eafa1d2489fd..3449c004bd84 100644
--- a/include/linux/lsm_hook_defs.h
+++ b/include/linux/lsm_hook_defs.h
@@ -407,3 +407,8 @@ LSM_HOOK(int, 0, perf_event_write, struct perf_event *event)
  LSM_HOOK(int, 0, uring_override_creds, const struct cred *new)
  LSM_HOOK(int, 0, uring_sqpoll, void)
  #endif /* CONFIG_IO_URING */
+
+LSM_HOOK(int, 0, bdev_alloc_security, struct block_device *bdev)
+LSM_HOOK(void, LSM_RET_VOID, bdev_free_security, struct block_device *bdev)
+LSM_HOOK(int, 0, bdev_setsecurity, struct block_device *bdev, const char *name,
+const void *value, size_t size)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 91c8146649f5..9f011d705ea8 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1550,6 +1550,17 @@
   *
   * @what: kernel feature being accessed
   *
+ * @bdev_alloc_security:
+ * Initialize the security field inside a block_device structure.
+ *
+ * @bdev_free_security:
+ * Cleanup the security information stored inside a block_device structure.
+ *
+ * @bdev_setsecurity:
+ * Set a security property associated with @name for @bdev with
+ * value @value. @size indicates the size of @value in bytes.
+ * If a @name is not implemented, return -EOPNOTSUPP.
+ *
   * Security hooks for perf events
   *
   * @perf_event_open:
@@ -1610,6 +1621,7 @@ struct lsm_blob_sizes {
int lbs_ipc;
int lbs_msg_msg;
int lbs_task;
+   int lbs_bdev;
  };
  
  /*

diff --git a/include/linux/security.h b/include/linux/security.h
index 7fc4e9f49f54..30b663de301f 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -473,6 +473,11 @@ int security_inode_notifysecctx(struct inode *inode, void 
*ctx, u32 ctxlen);
  int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
  int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
  int security_locked_down(enum lockdown_reason what);
+int security_bdev_alloc(struct block_device *bdev);
+void security_bdev_free(struct block_device *bdev);
+int security_bdev_setsecurity(