[RFC PATCH v9 09/16] block|security: add LSM blob to block_device
From: 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 Signed-off-by: Fan Wu Reviewed-by: Casey Schaufler --- 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. v9: + Add Reviewed-by: Casey Schaufler + Remove unlikely when calling LSM hook + Make the security field dependent on CONFIG_SECURITY --- block/bdev.c | 7 include/linux/blk_types.h | 3 ++ 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, 119 insertions(+) diff --git a/block/bdev.c b/block/bdev.c index edc110d90df4..f8db53b47c00 100644 --- a/block/bdev.c +++ b/block/bdev.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -396,6 +397,11 @@ static struct inode *bdev_alloc_inode(struct super_block *sb) if (!ei) return NULL; memset(&ei->bdev, 0, sizeof(ei->bdev)); + + if (security_bdev_alloc(&ei->bdev)) { + kmem_cache_free(bdev_cachep, ei); + return NULL; + } return &ei->vfs_inode; } @@ -405,6 +411,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 99be590f952f..137a04f45c17 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -68,6 +68,9 @@ struct block_device { #ifdef CONFIG_FAIL_MAKE_REQUEST boolbd_make_it_fail; #endif +#ifdef CONFIG_SECURITY + void*security; +#endif } __randomize_layout; #define bdev_whole(_bdev) \ diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index ed6cb2ac55fa..1f79029c9e28 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -417,3 +417,8 @@ LSM_HOOK(int, 0, uring_override_creds, const struct cred *new) LSM_HOOK(int, 0, uring_sqpoll, void) LSM_HOOK(int, 0, uring_cmd, struct io_uring_cmd *ioucmd) #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 0a5ba81f7367..b622ceb57d83 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1618,6 +1618,17 @@ * @what: kernel feature being accessed. * Return 0 if permission is granted. * + * @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: @@ -1687,6 +1698,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 479e154a12b8..7dea630bff5f 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -487,6 +487,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 securit
[RFC PATCH v9 14/16] scripts: add boot policy generation program
From: 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 Signed-off-by: Fan Wu --- 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 significant changes. v9: + no changes --- 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/fs.c | 8 ++ security/ipe/ipe.c| 19 + 11 files changed, 205 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 5e27e84763cc..d5b4a6636b0d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10276,6 +10276,7 @@ F: security/integrity/ INTEGRITY POLICY ENFORCEMENT (IPE) 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 1575af84d557..5d1def33df82 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -41,6 +41,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"); +
[RFC PATCH v9 16/16] documentation: add ipe documentation
From: Deven Bowers Add IPE's admin and developer documentation to the kernel tree. Co-developed-by: Fan Wu Signed-off-by: Deven Bowers Signed-off-by: Fan Wu --- 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. v9: + Correct spelling of "pitfalls" + Update the docs w.r.t the new parser and new audit formats --- Documentation/admin-guide/LSM/index.rst | 1 + Documentation/admin-guide/LSM/ipe.rst | 729 ++ .../admin-guide/kernel-parameters.txt | 12 + Documentation/security/index.rst | 1 + Documentation/security/ipe.rst| 436 +++ MAINTAINERS | 2 + 6 files changed, 1181 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 ..b676cea62b2e --- /dev/null +++ b/Documentation/admin-guide/LSM/ipe.rst @@ -0,0 +1,729 @@ +.. 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 operati
[RFC PATCH v9 01/16] security: add ipe lsm
From: 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 defining a global policy to specify which resource can be trusted. Signed-off-by: Deven Bowers Signed-off-by: Fan Wu --- 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. v9: + Remove ipe_context for simplification --- MAINTAINERS | 5 + security/Kconfig | 11 ++- security/Makefile | 1 + security/ipe/Kconfig | 17 + security/ipe/Makefile | 10 ++ security/ipe/ipe.c| 40 security/ipe/ipe.h| 13 + 7 files changed, 92 insertions(+), 5 deletions(-) create mode 100644 security/ipe/Kconfig create mode 100644 security/ipe/Makefile create mode 100644 security/ipe/ipe.c create mode 100644 security/ipe/ipe.h diff --git a/MAINTAINERS b/MAINTAINERS index 8a5c25c20d00..5e27e84763cc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10273,6 +10273,11 @@ 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: 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 e6db09a779b7..9f59add2d16c 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -207,6 +207,7 @@ source "security/yama/Kconfig" source "security/safesetid/Kconfig" source "security/lockdown/Kconfig" source "security/landlock/Kconfig" +source "security/ipe/Kconfig" source "security/integrity/Kconfig" @@ -246,11 +247,11 @@ endchoice config LSM string "Ordered list of enabled LSMs" - default "landlock,lockdown,yama,loadpin,safesetid,integrity,smack,selinux,tomoyo,apparmor,bpf" if DEFAULT_SECURITY_SMACK - default "landlock,lockdown,yama,loadpin,safesetid,integrity,apparmor,selinux,smack,tomoyo,bpf" if DEFAULT_SECURITY_APPARMOR - default "landlock,lockdown,yama,loadpin,safesetid,integrity,tomoyo,bpf" if DEFAULT_SECURITY_TOMOYO - default "landlock,lockdown,yama,loadpin,safesetid,integrity,bpf" if DEFAULT_SECURITY_DAC - default "landlock,lockdown,yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor,bpf" + default "landlock,lockdown,yama,loadpin,safesetid,integrity,ipe,smack,selinux,tomoyo,apparmor,bpf" if DEFAULT_SECURITY_SMACK + default "landlock,lockdown,yama,loadpin,safesetid,integrity,ipe,apparmor,selinux,smack,tomoyo,bpf" if DEFAULT_SECURITY_APPARMOR + default "landlock,lockdown,yama,loadpin,safesetid,integrity,ipe,tomoyo,bpf" if DEFAULT_SECURITY_TOMOYO + default "landlock,lockdown,yama,loadpin,safesetid,integrity,ipe,bpf" if DEFAULT_SECURITY_DAC + default "landlock,lockdown,yama,loadpin,safesetid,integrity,ipe,selinux,smack,tomoyo,apparmor,bpf" help A comma-separated list of LSMs, in initialization order. Any LSMs left off this list will be ignored. This can be diff --git a/security/Makefile b/security/Makefile index 18121f8f85cd..527b1864d96c 100644 --- a/security/Makefile +++ b/security/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_SECURITY_LOCKDOW
[RFC PATCH v9 05/16] ipe: add userspace interface
From: 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 Signed-off-by: Fan Wu --- 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. v8: + Prevent securityfs initialization if the LSM is disabled v9: + Switch to securityfs_recursive_remove for policy folder deletion --- security/ipe/Makefile| 2 + security/ipe/fs.c| 101 + security/ipe/fs.h| 17 ++ security/ipe/ipe.c | 3 + security/ipe/ipe.h | 2 + security/ipe/policy.c| 135 security/ipe/policy.h| 7 + security/ipe/policy_fs.c | 459 +++ 8 files changed, 726 insertions(+) create mode 100644 security/ipe/fs.c create mode 100644 security/ipe/fs.h create mode 100644 security/ipe/policy_fs.c diff --git a/security/ipe/Makefile b/security/ipe/Makefile index d7f2870d7c09..8602d71250b4 100644 --- a/security/ipe/Makefile +++ b/security/ipe/Makefile @@ -7,7 +7,9 @@ obj-$(CONFIG_SECURITY_IPE) += \ eval.o \ + fs.o \ hooks.o \ ipe.o \ policy.o \ + policy_fs.o \ policy_parser.o \ diff --git a/security/ipe/fs.c b/security/ipe/fs.c new file mode 100644 index ..9f6a4867bec2 --- /dev/null +++ b/security/ipe/fs.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Microsoft Corporation. All rights reserved. + */ +#include "ipe.h" +#include "fs.h" +#include "policy.h" + +#include +#include + +static struct dentry *np __ro_after_init; +static struct dentry *root __ro_after_init; +struct dentry *policy_root __ro_after_init; + +/** + * new_policy - Write handler for the securityfs node, "ipe/new_policy". + * @f: Supplies a file structure representing the securityfs node. + * @data: Suppleis a buffer passed to the write syscall. + * @len: Supplies the length of @data. + * @offset: unused. + * + * Return: + * * >0- Success, Length of buffer written + * * <0- Error + */ +static ssize_t new_policy(struct file *f, const char __user *data, + size_t len, loff_t *offset) +{ + int rc = 0; + char *copy = NULL; + struct ipe_policy *p = NULL; + + if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN)) + return -EPERM; + + copy = memdup_user_nul(data, len); + if (IS_ERR(copy)) { + rc = PTR_ERR(copy); + goto err; + } + + p = ipe_new_policy(NULL, 0, copy, len); + if (IS_ERR(p)) { + rc = PTR_ERR(p); + goto err; + } + + rc = ipe_new_policyfs_node(p); + if (rc) + goto err; + +err: + return (rc < 0) ? rc : len; +} + +static const struct file_operations np_fops = { + .write = new_policy, +}; + +/** + * ipe_init_securityfs - Initialize IPE's securityfs tree at fsinit. + * + * Return: + * * !0- Error + * * 0 - OK + */ +static int __init ipe_init_securityfs(void) +{ + int rc = 0; + + if (!ipe_enabled) + return -EOPNOTSUPP; + + root = securityfs_create_dir("ipe
[RFC PATCH v9 11/16] ipe: add support for dm-verity as a trust provider
From: 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 Signed-off-by: Fan Wu --- 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. v9: + Adapt to the new parser --- security/ipe/Kconfig | 20 + security/ipe/Makefile| 2 + security/ipe/audit.c | 24 ++ security/ipe/digest.c| 144 +++ security/ipe/digest.h| 26 +++ security/ipe/eval.c | 103 + security/ipe/eval.h | 13 security/ipe/hooks.c | 51 + security/ipe/hooks.h | 8 ++ security/ipe/ipe.c | 15 security/ipe/ipe.h | 4 + security/ipe/policy.h| 3 + security/ipe/policy_parser.c | 16 13 files changed, 429 insertions(+) create mode 100644 security/ipe/digest.c create mode 100644 security/ipe/digest.h diff --git a/security/ipe/Kconfig b/security/ipe/Kconfig index ac4d558e69d5..16e835ce61b0 100644 --- a/security/ipe/Kconfig +++ b/security/ipe/Kconfig @@ -15,3 +15,23 @@ menuconfig SECURITY_IPE admins to reconfigure trust requirements on the fly. If unsure, answer N. + +if SECURITY_IPE +menu "IPE Trust Providers" + +config IPE_PROP_DM_VERITY + bool "Enable support for dm-verity volumes" + depends on DM_VERITY && DM_VERITY_VERIFY_ROOTHASH_SIG + default Y + help + This option enables the properties 'dmverity_signature' and + 'dmverity_roothash' in IPE policy. These properties evaluates + to TRUE when a file is evaluated against a dm-verity volume + that was mounted with a signed root-hash or the volume's + root hash matches the supplied value in the policy. + + If unsure, answer Y. + +endmenu + +endif diff --git a/security/ipe/Makefile b/security/ipe/Makefile index 89a76ad72301..90203daf0dbb 100644 --- a/security/ipe/Makefile +++ b/security/ipe/Makefile @@ -6,6 +6,7 @@ # obj-$(CONFIG_SECURITY_IPE) += \ + digest.o \ eval.o \ fs.o \ hooks.o \ @@ -13,4 +14,5 @@ obj-$(CONFIG_SECURITY_IPE) += \ policy.o \ policy_fs.o \ policy_parser.o \ + digest.o \ audit.o \ diff --git a/security/ipe/audit.c b/security/ipe/audit.c index ff74026a595f..769ba95d9b0d 100644 --- a/security/ipe/audit.c +++ b/security/ipe/audit.c @@ -41,8 +41,29 @@ static const char *const audit_op_names[ipe_op_max] = { static const char *const audit_prop_names[ipe_prop_max] = { "boot_verified=FALSE", "boot_verified=TRUE", +#ifdef CONFIG_IPE_PROP_DM_VERITY + "dmverity_roothash=", + "dmverity_signature=FALSE", + "dmverity_signature=TRUE", +#endif /* CONFIG_IPE_PROP_DM_VERITY */ }; +#ifdef CONFIG_IPE_PROP_DM_VERITY +/** + * audit_dmv_roothash - audit a roothash of a dmverity volume. + * @ab: Supplies a poniter to the audit_buffer to append to. + * @r: Supplies a pointer to the digest structure. + */ +static void audit_dmv_roothash(struct audit_buffer *ab, const void *rh) +{ + ipe_digest_audit(ab, rh); +} +#else +static void audit_dmv_roothash(struct audit_buffer *ab, const void *rh) +{ +} +#endif /* CONFIG_IPE_PROP_DM_VERITY */ + /** * audit_rule - audit an IPE policy rule approximation. * @ab: Supplies a poniter to the audit_buffer to append to. @@ -56,6 +77,9 @@ static void audit_rule(struct audit_buffer *ab, const struct ipe_rule *r) list_for_each_entry(ptr, &r->props, next) { audit_log_format(ab, "%s", audit_prop_names[ptr->type]); + if (ptr->type == ipe_prop_dmv_roothash) + audit_dmv_roothash(ab, ptr->value); + audit_log_format(ab, " "); } diff --git a/security/ipe/digest.c b/security/ipe/digest.c new file mode 100644 index ..9fdb091f329b --- /dev/null +++ b/security/ipe/digest.c @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Microsoft Corporation. All rights reserved. + */ + +#include "digest.h" + +/** + * ipe_digest_parse - parse a digest in IPE's policy. + * @valstr: Supplies the string parsed from the policy. + * @value: Supplies a pointer to be populated with the result. + * + * Digests in IPE are defined in a standard way: + * : + * + * Use this function to create a property to parse the digest + * consistently. The parsed dige
[RFC PATCH v9 03/16] ipe: add evaluation loop and introduce 'boot_verified' as a trust provider
From: Deven Bowers IPE must have a centralized function to evaluate incoming callers against IPE's policy. This iteration of the policy against the rules for that specific caller is known as the evaluation loop. In addition, 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 Signed-off-by: Fan Wu --- 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. v8: + Remove ipe_hook enumeration; hooks can be correlated via syscall record. v9: + Remove ipe_context related code and simplify the evaluation loop. + Merge the evaluation loop commit with the boot_verified commit. --- security/ipe/Makefile| 1 + security/ipe/eval.c | 180 +++ security/ipe/eval.h | 28 ++ security/ipe/hooks.c | 25 + security/ipe/hooks.h | 14 +++ security/ipe/ipe.c | 1 + security/ipe/policy.c| 20 security/ipe/policy.h| 3 + security/ipe/policy_parser.c | 8 +- 9 files changed, 279 insertions(+), 1 deletion(-) create mode 100644 security/ipe/eval.c create mode 100644 security/ipe/eval.h create mode 100644 security/ipe/hooks.c create mode 100644 security/ipe/hooks.h diff --git a/security/ipe/Makefile b/security/ipe/Makefile index 16bbe80991f1..d7f2870d7c09 100644 --- a/security/ipe/Makefile +++ b/security/ipe/Makefile @@ -6,6 +6,7 @@ # obj-$(CONFIG_SECURITY_IPE) += \ + eval.o \ hooks.o \ ipe.o \ policy.o \ diff --git a/security/ipe/eval.c b/security/ipe/eval.c new file mode 100644 index ..48b5104a3463 --- /dev/null +++ b/security/ipe/eval.c @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Microsoft Corporation. All rights reserved. + */ + +#include "ipe.h" +#include "eval.h" +#include "hooks.h" +#include "policy.h" + +#include +#include +#include +#include +#include +#include +#include + +struct ipe_policy __rcu *ipe_active_policy; + +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_eval_ctx - Build an evaluation context. + * @ctx: Supplies a pointer to the context to be populdated. + * @file: Supplies a pointer to the file to associated with the evaluation. + * @op: Supplies the IPE policy operation associated with the evaluation. + */
Re: [RFC PATCH v9 02/16] ipe: add policy parser
On Mon, 2023-01-30 at 14:57 -0800, Fan Wu wrote: > From: 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. > > Signed-off-by: Deven Bowers > Signed-off-by: Fan Wu > > --- > 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. > > v9: > + switch to match table to parse policy > > + remove quote syntax and KERNEL_READ operation > --- > security/ipe/Makefile| 2 + > security/ipe/policy.c| 99 +++ > security/ipe/policy.h| 77 ++ > security/ipe/policy_parser.c | 515 +++ > security/ipe/policy_parser.h | 11 + > 5 files changed, 704 insertions(+) > create mode 100644 security/ipe/policy.c > create mode 100644 security/ipe/policy.h > create mode 100644 security/ipe/policy_parser.c > create mode 100644 security/ipe/policy_parser.h > > diff --git a/security/ipe/Makefile b/security/ipe/Makefile > index 571648579991..16bbe80991f1 100644 > --- a/security/ipe/Makefile > +++ b/security/ipe/Makefile > @@ -8,3 +8,5 @@ > obj-$(CONFIG_SECURITY_IPE) += \ > hooks.o \ > ipe.o \ > + policy.o \ > + policy_parser.o \ > diff --git a/security/ipe/policy.c b/security/ipe/policy.c > new file mode 100644 > index ..e446f4b84152 > --- /dev/null > +++ b/security/ipe/policy.c > @@ -0,0 +1,99 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (C) Microsoft Corporation. All rights reserved. > + */ > + > +#include "ipe.h" > +#include "policy.h" > +#include "policy_parser.h" > +#include "digest.h" > + > +#include > + > +/** > + * ipe_free_policy - Deallocate a given IPE policy. > + * @p: Supplies the policy to free. > + * > + * Safe to call on IS_ERR/NULL. > + */ > +void ipe_free_policy(struct ipe_policy *p) > +{ > + if (IS_ERR_OR_NULL(p)) > + return; > + > + free_parsed_policy(p->parsed); > + if (!p->pkcs7) > + kfree(p->text); > + kfree(p->pkcs7); > + kfree(p); > +} > + > +static int set_pkcs7_data(void *ctx, const void *data, size_t len, > + size_t asn1hdrlen) > +{ > + struct ipe_policy *p = ctx; > + > + p->text = (const char *)data; > + p->textlen = len; > + > + return 0; > +} > + > +/** > + * ipe_new_policy - Allocate and parse an ipe_policy structure. > + * > + * @text: Supplies a pointer to the plain-text policy to parse. > + * @textlen: Supplies the length of @text. > + * @pkcs7: Supplies a pointer to a pkcs7-signed IPE policy. > + * @pkcs7len: Supplies the length of @pkcs7. > + * > + * @text/@textlen Should be NULL/0 if @pkcs7/@pkcs7len is set. > + * > + * The result will still need to be associated with a context via > + * ipe_add_policy. > + * > + * Return: > + * * !IS_ERR - Success > + * * -EBADMSG- Policy is invalid > + * * -ENOMEM - Out of memory > + */ > +struct ipe_policy *ipe_new_policy(const
[RFC PATCH v9 06/16] ipe: add LSM hooks on execution and kernel read
From: 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 Signed-off-by: Fan Wu --- 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. v9: + Minor changes for adapting to the new parser --- security/ipe/hooks.c | 169 +++ security/ipe/hooks.h | 13 security/ipe/ipe.c | 6 ++ 3 files changed, 188 insertions(+) diff --git a/security/ipe/hooks.c b/security/ipe/hooks.c index 335b773c7ae1..fd5109e29c76 100644 --- a/security/ipe/hooks.c +++ b/security/ipe/hooks.c @@ -23,3 +23,172 @@ void ipe_sb_free_security(struct super_block *mnt_sb) { ipe_invalidate_pinned_sb(mnt_sb); } + +/** + * ipe_bprm_check_security - ipe security hook function for bprm check. + * @bprm: Supplies a pointer to a linux_binprm structure to source the file + * being evaluated. + * + * This LSM hook is called when a binary is loaded through the exec + * family of system calls. + * Return: + * *0 - OK + * *!0 - Error + */ +int ipe_bprm_check_security(struct linux_binprm *bprm) +{ + struct ipe_eval_ctx ctx = { 0 }; + + build_eval_ctx(&ctx, bprm->file, ipe_op_exec); + return ipe_evaluate_event(&ctx); +} + +/** + * ipe_mmap_file - ipe security hook function for mmap check. + * @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. + * + * This hook is called when a file is loaded through the mmap + * family of system calls. + * + * Return: + * * 0 - OK + * * !0- Error + */ +int ipe_mmap_file(struct file *f, unsigned long reqprot, unsigned long prot, + unsigned long flags) +{ + struct ipe_eval_ctx ctx = { 0 }; + + if (prot & PROT_EXEC || reqprot & PROT_EXEC) { + build_eval_ctx(&ctx, f, ipe_op_exec); + return ipe_evaluate_event(&ctx); + } + + return 0; +} + +/** + * ipe_file_mprotect - ipe security hook function for mprotect check. + * @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. + * + * This LSM hook is called when a mmap'd region of memory is changing + * its protections via mprotect. + * + * Return: + * * 0 - OK + * * !0- Error + */ +int ipe_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, + unsigned long prot) +{ + struct ipe_eval_ctx ctx = { 0 }; + + /* Already Executable */ + if (vma->vm_flags & VM_EXEC) + return 0; + + if (prot & PROT_EXEC) { + build_eval_ctx(&ctx, vma->vm_file, ipe_op_exec); + return ipe_evaluate_event(&ctx); + } + + return 0; +} + +/** + * ipe_kernel_read_file - ipe security hook function for kernel read. + * @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. + * + * This LSM hook is called when a file is being read in from disk from + * the kernel. + * + * Return: + * 0 - OK + * !0 - Error + */ +int ipe_kernel_read_file(struct file *file, enum kernel_read_file_id id, +bool contents
Re: [RFC PATCH v9 16/16] documentation: add ipe documentation
On Mon, Jan 30, 2023 at 02:57:31PM -0800, Fan Wu wrote: > diff --git a/Documentation/admin-guide/LSM/ipe.rst > b/Documentation/admin-guide/LSM/ipe.rst > new file mode 100644 > index ..b676cea62b2e > --- /dev/null > +++ b/Documentation/admin-guide/LSM/ipe.rst > @@ -0,0 +1,729 @@ > +.. 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 of interpreted languages' programs when > +these scripts are invoked via `` ``. This is because > +the way interpreters execute these files, the scripts themselves are not > +evaluated as executable code through one of IPE's hooks, as they are merely > +files that are read (as opposed to executable code) [#interpreters]_. > + > +Threat Model > + > + > +The threat type addressed by IPE is tampering of executable userspace > +code beyond the initially booted kernel, and the initial verification of > +kernel modules that are loaded in userspace through ``modprobe`` or > +``insmod``. > + > +A bare-minimum example of a threat that should be mitigated by IPE, is > +a hostile binary is downloaded with all required binaries (including > +a loader, libc, etc). With IPE, this hostile binary should not able to > +be executed, nor any of the downloaded binaries. > + > +Tampering violates integrity, and being unable to verify the integrity, > +results in a lack of trust. IPE's role in mitigating this threat is to > +verify the integrity (and authenticity) of all executable code and to > +deny their use if they cannot be trusted (as integrity verification fails, > +or the authorization check fails against the reference value in the policy). > +IPE generates audit logs which may be utilized to detect failures resulting > +from failure to pass policy. > + > +Tampering threat scenarios include modification or replacement of > +executable code by a range of actors including: > + > +- Actors with physical acc
Re: [RFC PATCH v9 05/16] ipe: add userspace interface
On Mon, 2023-01-30 at 14:57 -0800, Fan Wu wrote: > From: 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 > Signed-off-by: Fan Wu > > --- > 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. > > v8: > + Prevent securityfs initialization if the LSM is disabled > > v9: > + Switch to securityfs_recursive_remove for policy folder deletion > --- > security/ipe/Makefile| 2 + > security/ipe/fs.c| 101 + > security/ipe/fs.h| 17 ++ > security/ipe/ipe.c | 3 + > security/ipe/ipe.h | 2 + > security/ipe/policy.c| 135 > security/ipe/policy.h| 7 + > security/ipe/policy_fs.c | 459 +++ > 8 files changed, 726 insertions(+) > create mode 100644 security/ipe/fs.c > create mode 100644 security/ipe/fs.h > create mode 100644 security/ipe/policy_fs.c > > diff --git a/security/ipe/Makefile b/security/ipe/Makefile > index d7f2870d7c09..8602d71250b4 100644 > --- a/security/ipe/Makefile > +++ b/security/ipe/Makefile > @@ -7,7 +7,9 @@ > > obj-$(CONFIG_SECURITY_IPE) += \ > eval.o \ > + fs.o \ > hooks.o \ > ipe.o \ > policy.o \ > + policy_fs.o \ > policy_parser.o \ > diff --git a/security/ipe/fs.c b/security/ipe/fs.c > new file mode 100644 > index ..9f6a4867bec2 > --- /dev/null > +++ b/security/ipe/fs.c > @@ -0,0 +1,101 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (C) Microsoft Corporation. All rights reserved. > + */ > +#include "ipe.h" > +#include "fs.h" > +#include "policy.h" > + > +#include > +#include > + > +static struct dentry *np __ro_after_init; > +static struct dentry *root __ro_after_init; > +struct dentry *policy_root __ro_after_init; > + > +/** > + * new_policy - Write handler for the securityfs node, "ipe/new_policy". > + * @f: Supplies a file structure representing the securityfs node. > + * @data: Suppleis a buffer passed to the write syscall. Typo: Suppleis. > + * @len: Supplies the length of @data. > + * @offset: unused. > + * > + * Return: > + * * >0 - Success, Length of buffer written > + * * <0 - Error > + */ > +static ssize_t new_policy(struct file *f, const char __user *data, > + size_t len, loff_t *offset) > +{ > + int rc = 0; > + char *copy = NULL; > + struct ipe_policy *p = NULL; > + > + if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN)) > + return -EPERM; > + > + copy = memdup_user_nul(data, len); > + if (IS_ERR(copy)) { > + rc = PTR_ERR(copy); > + goto err; > + } > + > + p = ipe_new_policy(NULL, 0, copy, len); > + if (IS_ERR(p)) { > + rc = PTR_ERR(p); > + goto err; > + } > + > + rc = ipe_new_policyfs_node(p); > + if (rc) > + goto err; Uhm, don't you need to do cleanup of allocated memory or revert the actions of ipe_new_policy()? > + > +err: > + ret
[RFC PATCH v9 13/16] ipe: enable support for fs-verity as a trust provider
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: Deven Bowers Signed-off-by: Fan Wu --- 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. v9: + Adapt to the new parser --- security/ipe/Kconfig | 11 security/ipe/audit.c | 23 +++ security/ipe/eval.c | 112 +++ security/ipe/eval.h | 10 security/ipe/hooks.c | 30 ++ security/ipe/hooks.h | 7 +++ security/ipe/ipe.c | 13 security/ipe/ipe.h | 3 + security/ipe/policy.h| 3 + security/ipe/policy_parser.c | 8 +++ 10 files changed, 220 insertions(+) diff --git a/security/ipe/Kconfig b/security/ipe/Kconfig index 16e835ce61b0..dd9a066dd35a 100644 --- a/security/ipe/Kconfig +++ b/security/ipe/Kconfig @@ -32,6 +32,17 @@ config IPE_PROP_DM_VERITY If unsure, answer Y. +config IPE_PROP_FS_VERITY + bool "Enable property for fs-verity files" + depends on FS_VERITY && FS_VERITY_BUILTIN_SIGNATURES + help + This option enables the usage of properties "fsverity_signature" + and "fsverity_digest". These properties evaluates to TRUE when + a file is fsverity enabled and with a signed digest or its + diegst matches the supplied value in the policy. + + if unsure, answer Y. + endmenu endif diff --git a/security/ipe/audit.c b/security/ipe/audit.c index 769ba95d9b0d..16d81645e53c 100644 --- a/security/ipe/audit.c +++ b/security/ipe/audit.c @@ -46,6 +46,11 @@ static const char *const audit_prop_names[ipe_prop_max] = { "dmverity_signature=FALSE", "dmverity_signature=TRUE", #endif /* CONFIG_IPE_PROP_DM_VERITY */ +#ifdef CONFIG_IPE_PROP_FS_VERITY + "fsverity_digest=", + "fsverity_signature=FALSE", + "fsverity_signature=TRUE" +#endif /* CONFIG_IPE_PROP_FS_VERITY */ }; #ifdef CONFIG_IPE_PROP_DM_VERITY @@ -64,6 +69,22 @@ static void audit_dmv_roothash(struct audit_buffer *ab, const void *rh) } #endif /* CONFIG_IPE_PROP_DM_VERITY */ +#ifdef CONFIG_IPE_PROP_FS_VERITY +/** + * audit_fsv_digest - audit a digest of a fsverity file. + * @ab: Supplies a poniter to the audit_buffer to append to. + * @d: Supplies a pointer to the digest structure. + */ +static void audit_fsv_digest(struct audit_buffer *ab, const void *d) +{ + ipe_digest_audit(ab, d); +} +#else +static void audit_fsv_digest(struct audit_buffer *ab, const void *d) +{ +} +#endif /* CONFIG_IPE_PROP_DM_VERITY */ + /** * audit_rule - audit an IPE policy rule approximation. * @ab: Supplies a poniter to the audit_buffer to append to. @@ -79,6 +100,8 @@ static void audit_rule(struct audit_buffer *ab, const struct ipe_rule *r) audit_log_format(ab, "%s", audit_prop_names[ptr->type]); if (ptr->type == ipe_prop_dmv_roothash) audit_dmv_roothash(ab, ptr->value); + if (ptr->type == ipe_prop_fsv_digest) + audit_fsv_digest(ab, ptr->value); audit_log_format(ab, " "); } diff --git a/security/ipe/eval.c b/security/ipe/eval.c index 538af4195ba7..210d3926c0a8 100644 --- a/security/ipe/eval.c +++ b/security/ipe/eval.c @@ -81,6 +81,23 @@ static void build_ipe_bdev_ctx(struct ipe_eval_ctx *ctx, const struct inode *con } #endif /* CONFIG_IPE_PROP_DM_VERITY */ +#ifdef CONFIG_IPE_PROP_FS_VERITY +/** + * build_ipe_inode_ctx - Build inode fields of an evaluation context. + * @ctx: Supplies a pointer to the context to be populdated. + * @ino: Supplies the inode struct of the file triggered IPE eve
Re: [RFC PATCH v9 09/16] block|security: add LSM blob to block_device
On Mon, Jan 30, 2023 at 02:57:24PM -0800, Fan Wu wrote: > From: Deven Bowers > > block_device structures can have valuable security properties, > based on how they are created, and what subsystem manages them. That's a lot of cloudy talk but no real explanation. -- Linux-audit mailing list Linux-audit@redhat.com https://listman.redhat.com/mailman/listinfo/linux-audit
Re: [RFC PATCH v9 03/16] ipe: add evaluation loop and introduce 'boot_verified' as a trust provider
On Mon, 2023-01-30 at 14:57 -0800, Fan Wu wrote: > From: Deven Bowers > > IPE must have a centralized function to evaluate incoming callers > against IPE's policy. This iteration of the policy against the rules > for that specific caller is known as the evaluation loop. > > In addition, 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. Uhm, I think it makes really sense to move the pinned logic in another patch. This patch is very important, as it contains the policy logic. It should be standalone. > Signed-off-by: Deven Bowers > Signed-off-by: Fan Wu > > --- > 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. > > v8: > + Remove ipe_hook enumeration; hooks can be correlated via syscall > record. > > v9: > + Remove ipe_context related code and simplify the evaluation loop. > + Merge the evaluation loop commit with the boot_verified commit. > --- > security/ipe/Makefile| 1 + > security/ipe/eval.c | 180 +++ > security/ipe/eval.h | 28 ++ > security/ipe/hooks.c | 25 + > security/ipe/hooks.h | 14 +++ > security/ipe/ipe.c | 1 + > security/ipe/policy.c| 20 > security/ipe/policy.h| 3 + > security/ipe/policy_parser.c | 8 +- > 9 files changed, 279 insertions(+), 1 deletion(-) > create mode 100644 security/ipe/eval.c > create mode 100644 security/ipe/eval.h > create mode 100644 security/ipe/hooks.c > create mode 100644 security/ipe/hooks.h > > diff --git a/security/ipe/Makefile b/security/ipe/Makefile > index 16bbe80991f1..d7f2870d7c09 100644 > --- a/security/ipe/Makefile > +++ b/security/ipe/Makefile > @@ -6,6 +6,7 @@ > # > > obj-$(CONFIG_SECURITY_IPE) += \ > + eval.o \ > hooks.o \ > ipe.o \ > policy.o \ > diff --git a/security/ipe/eval.c b/security/ipe/eval.c > new file mode 100644 > index ..48b5104a3463 > --- /dev/null > +++ b/security/ipe/eval.c > @@ -0,0 +1,180 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (C) Microsoft Corporation. All rights reserved. > + */ > + > +#include "ipe.h" > +#include "eval.h" > +#include "hooks.h" > +#include "policy.h" > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +struct ipe_policy __rcu *ipe_active_policy; > + > +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) > +{ > + b
[RFC PATCH v9 04/16] security: add new securityfs delete function
When deleting a directory in the security file system, the existing securityfs_remove requires the directory to be empty, otherwise it will do nothing. This leads to a potential risk that the security file system might be in an unclean state when the intentded deletion did not happen. This commit introduces a new function securityfs_recursive_remove to recursively delete a directory without leaving an unclean state. Co-developed-by: Christian Brauner (Microsoft) Signed-off-by: Fan Wu --- v1-v8: + Not present --- include/linux/security.h | 1 + security/inode.c | 25 + 2 files changed, 26 insertions(+) diff --git a/include/linux/security.h b/include/linux/security.h index 5b67f208f7de..479e154a12b8 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1985,6 +1985,7 @@ struct dentry *securityfs_create_symlink(const char *name, const char *target, const struct inode_operations *iops); extern void securityfs_remove(struct dentry *dentry); +extern void securityfs_recursive_remove(struct dentry *dentry); #else /* CONFIG_SECURITYFS */ diff --git a/security/inode.c b/security/inode.c index 6c326939750d..13358e8547e8 100644 --- a/security/inode.c +++ b/security/inode.c @@ -313,6 +313,31 @@ void securityfs_remove(struct dentry *dentry) } EXPORT_SYMBOL_GPL(securityfs_remove); +static void remove_one(struct dentry *victim) +{ + simple_release_fs(&mount, &mount_count); +} + +/** + * securityfs_recursive_remove - recursively removes a file or directory from the securityfs filesystem + * + * @dentry: a pointer to a the dentry of the file or directory to be removed. + * + * This function recursively removes a file or directory in securityfs that was + * previously created with a call to another securityfs function (like + * securityfs_create_file() or variants thereof.) + */ +void securityfs_recursive_remove(struct dentry *dentry) +{ + if (IS_ERR_OR_NULL(dentry)) + return; + + simple_pin_fs(&fs_type, &mount, &mount_count); + simple_recursive_removal(dentry, remove_one); + simple_release_fs(&mount, &mount_count); +} +EXPORT_SYMBOL_GPL(securityfs_recursive_remove); + #ifdef CONFIG_SECURITY static struct dentry *lsm_dentry; static ssize_t lsm_read(struct file *filp, char __user *buf, size_t count, -- 2.39.0 -- Linux-audit mailing list Linux-audit@redhat.com https://listman.redhat.com/mailman/listinfo/linux-audit
audit library license
Dear All members, We can find following lines in audit/README file LICENSE === The audit daemon is released as GPL'd code. The audit daemon's libraries libaudit.* and libauparse.* are released under LGPL so that it may be linked with 3rd party software. I found that latest audit library linked libaucommon.so. ./lib/Makefile.in:AM_CPPFLAGS = -I. -I${top_srcdir} -I${top_srcdir}/auparse -I${top_srcdir}/common ./lib/Makefile.in:libaudit_la_LIBADD = $(CAPNG_LDADD) ${top_builddir}/common/libaucommon.la ./lib/Makefile.in:libaudit_la_DEPENDENCIES = $(libaudit_la_SOURCES) ../config.h ${top_builddir}/common/libaucommon.la ./auparse/Makefile.am:AM_CPPFLAGS = -I. -I${top_srcdir} -I${top_srcdir}/src -I${top_srcdir}/lib -I${top_srcdir}/common ./auparse/Makefile.am:libauparse_la_LIBADD = ${top_builddir}/lib/libaudit.la ${top_builddir}/common/libaucommon.la ./auparse/Makefile.am:libauparse_la_DEPENDENCIES = $(libauparse_la_SOURCES) ${top_builddir}/config.h ${top_builddir}/common/libaucommon.la Libaucommo.so is created by following files ./common/Makefile.am:libaucommon_la_SOURCES = audit-fgets.c strsplit.c And the license of audit/common/audit-fgets.c is GPLv2 This mean the license of latest audit libraries are also GPLv2. Is my understanding correct? -- Linux-audit mailing list Linux-audit@redhat.com https://listman.redhat.com/mailman/listinfo/linux-audit
Re: [RFC PATCH v9 06/16] ipe: add LSM hooks on execution and kernel read
On Mon, 2023-01-30 at 14:57 -0800, Fan Wu wrote: > From: 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 > Signed-off-by: Fan Wu > --- > 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. > > v9: > + Minor changes for adapting to the new parser > --- > security/ipe/hooks.c | 169 +++ > security/ipe/hooks.h | 13 > security/ipe/ipe.c | 6 ++ > 3 files changed, 188 insertions(+) > > diff --git a/security/ipe/hooks.c b/security/ipe/hooks.c > index 335b773c7ae1..fd5109e29c76 100644 > --- a/security/ipe/hooks.c > +++ b/security/ipe/hooks.c > @@ -23,3 +23,172 @@ void ipe_sb_free_security(struct super_block *mnt_sb) > { > ipe_invalidate_pinned_sb(mnt_sb); > } > + > +/** > + * ipe_bprm_check_security - ipe security hook function for bprm check. > + * @bprm: Supplies a pointer to a linux_binprm structure to source the file > + * being evaluated. > + * > + * This LSM hook is called when a binary is loaded through the exec > + * family of system calls. > + * Return: > + * *0- OK > + * *!0 - Error > + */ > +int ipe_bprm_check_security(struct linux_binprm *bprm) > +{ > + struct ipe_eval_ctx ctx = { 0 }; > + > + build_eval_ctx(&ctx, bprm->file, ipe_op_exec); > + return ipe_evaluate_event(&ctx); > +} > + > +/** > + * ipe_mmap_file - ipe security hook function for mmap check. > + * @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. > + * > + * This hook is called when a file is loaded through the mmap > + * family of system calls. > + * > + * Return: > + * * 0 - OK > + * * !0 - Error > + */ > +int ipe_mmap_file(struct file *f, unsigned long reqprot, unsigned long prot, > + unsigned long flags) > +{ > + struct ipe_eval_ctx ctx = { 0 }; > + > + if (prot & PROT_EXEC || reqprot & PROT_EXEC) { Since the kernel only adds flags and doesn't clear them, isn't safe to just consider prot? Oh, you mentioned it in the changelog, maybe just for ipe_file_mprotect(). > + build_eval_ctx(&ctx, f, ipe_op_exec); > + return ipe_evaluate_event(&ctx); > + } Uhm, I think some considerations that IMA does for mmap() are relevant also for IPE. For example, look at mmap_violation_check(). It checks if there are writable mappings, and if yes, it denies the access. Similarly for mprotect(), is adding PROT_EXEC safe? > + > + return 0; > +} > + > +/** > + * ipe_file_mprotect - ipe security hook function for mprotect check. > + * @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. > + * > + * This LSM hook is called when a mmap'd region of memory is changing > + * its protections via mprotect. > + * > + * Return: > + * * 0 - OK > + * * !0 - Error > + */ > +int ipe_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, > + unsigned long prot) > +{ > + struct ipe_eval_ctx ctx = { 0 }; > + > + /* Already Executable */ > +
[RFC PATCH v9 12/16] fsverity: consume builtin signature via LSM hook
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. v9: + No changes --- 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 c7fcb855e068..3194a1f4a705 100644 --- a/fs/verity/fsverity_private.h +++ b/fs/verity/fsverity_private.h @@ -117,7 +117,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 40f14e5fed9d..29e9888287ba 100644 --- a/include/linux/fsverity.h +++ b/include/linux/fsverity.h @@ -254,4 +254,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.39.0 -- Linux-audit mailing list Linux-audit@redhat.com https://listman.redhat.com/mailman/listinfo/linux-audit
[RFC PATCH v9 08/16] ipe: add permissive toggle
From: 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 1404 AUDIT_MAC_STATUS be reported. This patch adds the following audit records: audit: MAC_STATUS permissive=1 auid=4294967295 ses=4294967295 lsm=ipe res=1 audit: MAC_STATUS permissive=0 auid=4294967295 ses=4294967295 lsm=ipe res=1 These records are emitted within the following events: audit: MAC_STATUS permissive=1 auid=4294967295 ses=4294967295 lsm=ipe res=1 audit[185]: SYSCALL arch=c03e syscall=1 success=yes exit=2 a0=1 a1=56308bb3ecc0 a2=2 a3=7f290fdc53e0 items=0 ppid=183 pid=185 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=4294967295 comm="bash" exe="/usr/bin/bash" key=(null) audit: PROCTITLE proctitle="-bash" audit: MAC_STATUS permissive=0 auid=4294967295 ses=4294967295 lsm=ipe res=1 audit[185]: SYSCALL arch=c03e syscall=1 success=yes exit=2 a0=1 a1=56308bb3ecc0 a2=2 a3=7f290fdc53e0 items=0 ppid=183 pid=185 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=4294967295 comm="bash" exe="/usr/bin/bash" key=(null) audit: PROCTITLE proctitle="-bash" Implying user used bash to toggle the switch. Signed-off-by: Deven Bowers Signed-off-by: Fan Wu --- 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. v9: + Clean up ipe_context related code --- security/ipe/audit.c | 36 +++ security/ipe/audit.h | 1 + security/ipe/eval.c | 9 ++ security/ipe/eval.h | 1 + security/ipe/fs.c| 69 ++-- 5 files changed, 114 insertions(+), 2 deletions(-) diff --git a/security/ipe/audit.c b/security/ipe/audit.c index 295e9f9f5146..ff74026a595f 100644 --- a/security/ipe/audit.c +++ b/security/ipe/audit.c @@ -194,3 +194,39 @@ 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. + */ +void ipe_audit_enforce(void) +{ + struct audit_buffer *ab; + + ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_MAC_STATUS); + if (!ab) + return; + + audit_log_format(ab, "permissive=%d", !READ_ONCE(enforce)); + audit_log_format(ab, " auid=%u ses=%u lsm=ipe res=1", +from_kuid(&init_user_ns, audit_get_loginuid(current)), +audit_get_sessionid(current)); + + audit_log_end(ab); +} + +/** + * emit_enforcement - Emit the enforcement state of IPE started with. + * + * Return: + * 0 - Always + */ +static int emit_enforcement(void) +{ + if (!ipe_enabled) + return -EOPNOTSUPP; + + ipe_audit_enforce(); + return 0; +} + +late_initcall(emit_enforcement); diff --git a/security/ipe/audit.h b/security/ipe/audit.h index 2e9b99737f97..4c676ed32846 100644 --- a/security/ipe/audit.h +++ b/security/ipe/audit.h @@ -14,5 +14,6 @@ void ipe_audit_match(const struct ipe_eval_ctx *const ctx, void ipe_audit_pol
[RFC PATCH v9 10/16] dm-verity: consume root hash digest and signature data via LSM hook
From: 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 higher 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 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 Signed-off-by: Fan Wu --- 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. v9: + No changes --- 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 ccf5b852fbf7..afea61eed4ec 100644 --- a/drivers/md/dm-verity-target.c +++ b/drivers/md/dm-verity-target.c @@ -13,6 +13,7 @@ * access behavior. */ +#include "dm-core.h" #include "dm-verity.h" #include "dm-verity-fec.h" #include "dm-verity-verify-sig.h" @@ -21,6 +22,9 @@ #include #include #include +#include +#include +#include #define DM_MSG_PREFIX "verity" @@ -1169,6 +1173,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) { @@ -1211,6 +1217,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"; @@ -1343,7 +1356,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); @@ -1428,12 +1441,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..5a73b91157d5 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"
[RFC PATCH v9 15/16] ipe: kunit test for parser
From: Deven Bowers Add various happy/unhappy unit tests for both IPE's parser. Signed-off-by: Deven Bowers Signed-off-by: Fan Wu --- 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. v9: + Remove the kunit tests related to ipe_context --- security/ipe/Kconfig| 17 +++ security/ipe/Makefile | 3 + security/ipe/policy_tests.c | 294 3 files changed, 314 insertions(+) create mode 100644 security/ipe/policy_tests.c diff --git a/security/ipe/Kconfig b/security/ipe/Kconfig index 691fdb9ae60e..79e4fd677c19 100644 --- a/security/ipe/Kconfig +++ b/security/ipe/Kconfig @@ -55,4 +55,21 @@ config IPE_PROP_FS_VERITY endmenu +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 e6d5176bc20b..285e0949db25 100644 --- a/security/ipe/Makefile +++ b/security/ipe/Makefile @@ -27,3 +27,6 @@ obj-$(CONFIG_SECURITY_IPE) += \ audit.o \ clean-files := boot-policy.c \ + +obj-$(CONFIG_SECURITY_IPE_KUNIT_TEST) += \ + policy_tests.o \ diff --git a/security/ipe/policy_tests.c b/security/ipe/policy_tests.c new file mode 100644 index ..d09a1aca863d --- /dev/null +++ b/security/ipe/policy_tests.c @@ -0,0 +1,294 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Microsoft Corporation. All rights reserved. + */ + +#include +#include +#include +#include +#include "policy.h" +struct policy_case { + const char *const policy; + interrno; + const char *const desc; +}; + +static const struct policy_case policy_cases[] = { + { + "policy_name=allowall policy_version=0.0.0\n" + "DEFAULT action=ALLOW", + 0, + "basic", + }, + { + "policy_name=trailing_comment policy_version=152.0.0 #This is comment\n" + "DEFAULT action=ALLOW", + 0, + "trailing comment", + }, + { + "policy_name=allowallnewline policy_version=0.2.0\n" + "DEFAULT action=ALLOW\n" + "\n", + 0, + "trailing newline", + }, + { + "policy_name=carriagereturnlinefeed policy_version=0.0.1\n" + "DEFAULT action=ALLOW\n" + "\r\n", + 0, + "clrf newline", + }, + { + "policy_name=whitespace policy_version=0.0.0\n" + "DEFAULT\taction=ALLOW\n" + " \t DEFAULT \top=EXECUTE action=DENY\n" + "op=EXECUTE boot_verified=TRUE action=ALLOW\n" + "# this is a\tcomment\t\t\t\t\n" + "DEFAULT \t op=KMODULE\t\t\t action=DENY\r\n" + "op=KMODULE boot_verified=TRUE action=ALLOW\n", + 0, + "various whitespaces and nested default", + }, + { + "policy_name=boot_verified policy_version=-1236.0.0\n" + "DEFAULT\taction=ALLOW\n", + -EINVAL, + "negative version", + }, + { + "policy_name=$@!*&^%%\\:;{}() policy_version=0.0.0\n" + "DEFAULT action=ALLOW", + 0, + "special characters", + }, + { + "policy_name=test policy_version=99.0.0\n" + "DEFAULT action=ALLOW", + -ERANGE, + "overflow version", + }, + { + "policy_name=test policy_version=255.0\n" + "DEFAULT action=ALLOW", + -EBADMSG, + "incomplete version", + }, + { + "policy_name=test policy_version=111.0.0.0\n" + "DEFAULT action=ALLOW", + -EBADMSG, + "extra version", + }, + { + "", + -EBADMSG, + "0-length policy", + }, + { + "policy_name=test\0policy_version=0.0.0\n" + "DEFAULT action=ALLOW", + -EBADMSG, + "random null in header", + }, + { + "policy_name=test policy_version=0.0.0\n" +
[RFC PATCH v9 02/16] ipe: add policy parser
From: 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. Signed-off-by: Deven Bowers Signed-off-by: Fan Wu --- 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. v9: + switch to match table to parse policy + remove quote syntax and KERNEL_READ operation --- security/ipe/Makefile| 2 + security/ipe/policy.c| 99 +++ security/ipe/policy.h| 77 ++ security/ipe/policy_parser.c | 515 +++ security/ipe/policy_parser.h | 11 + 5 files changed, 704 insertions(+) create mode 100644 security/ipe/policy.c create mode 100644 security/ipe/policy.h create mode 100644 security/ipe/policy_parser.c create mode 100644 security/ipe/policy_parser.h diff --git a/security/ipe/Makefile b/security/ipe/Makefile index 571648579991..16bbe80991f1 100644 --- a/security/ipe/Makefile +++ b/security/ipe/Makefile @@ -8,3 +8,5 @@ obj-$(CONFIG_SECURITY_IPE) += \ hooks.o \ ipe.o \ + policy.o \ + policy_parser.o \ diff --git a/security/ipe/policy.c b/security/ipe/policy.c new file mode 100644 index ..e446f4b84152 --- /dev/null +++ b/security/ipe/policy.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Microsoft Corporation. All rights reserved. + */ + +#include "ipe.h" +#include "policy.h" +#include "policy_parser.h" +#include "digest.h" + +#include + +/** + * ipe_free_policy - Deallocate a given IPE policy. + * @p: Supplies the policy to free. + * + * Safe to call on IS_ERR/NULL. + */ +void ipe_free_policy(struct ipe_policy *p) +{ + if (IS_ERR_OR_NULL(p)) + return; + + free_parsed_policy(p->parsed); + if (!p->pkcs7) + kfree(p->text); + kfree(p->pkcs7); + kfree(p); +} + +static int set_pkcs7_data(void *ctx, const void *data, size_t len, + size_t asn1hdrlen) +{ + struct ipe_policy *p = ctx; + + p->text = (const char *)data; + p->textlen = len; + + return 0; +} + +/** + * ipe_new_policy - Allocate and parse an ipe_policy structure. + * + * @text: Supplies a pointer to the plain-text policy to parse. + * @textlen: Supplies the length of @text. + * @pkcs7: Supplies a pointer to a pkcs7-signed IPE policy. + * @pkcs7len: Supplies the length of @pkcs7. + * + * @text/@textlen Should be NULL/0 if @pkcs7/@pkcs7len is set. + * + * The result will still need to be associated with a context via + * ipe_add_policy. + * + * Return: + * * !IS_ERR - Success + * * -EBADMSG - Policy is invalid + * * -ENOMEM - Out of memory + */ +struct ipe_policy *ipe_new_policy(const char *text, size_t textlen, + const char *pkcs7, size_t pkcs7len) +{ + int rc = 0; + struct ipe_policy *new = NULL; + + new = kzalloc(sizeof(*new), GFP_KERNEL); + if (!new) + return ERR_PTR(-ENOMEM); + + if (!text) { + new->pkcs7len = pkcs7len; +
[RFC PATCH v9 07/16] uapi|audit|ipe: add ipe auditing support
From: 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. This patch adds the following audit records: audit: AUDIT1420 path="/tmp/tmpwxmam366/deny/bin/hello" dev="tmpfs" ino=72 rule="DEFAULT op=EXECUTE action=DENY" The above audit record shows IPE blocked a file /tmp/tmpwxmam366/deny/bin/hello in the temp file system. audit: AUDIT1420 path="/tmp/tmpxkvb3d9x/deny/bin/hello" dev="tmpfs" ino=157 rule="DEFAULT action=DENY" The above audit record shows IPE blocked a file /tmp/tmpxkvb3d9x/deny/bin/hello in the temp file system via another rule. audit: MAC_POLICY_LOAD policy_name="dmverity_roothash" policy_version=0.0.0 sha256=DC67AC19E05894EFB3170A8E55DE529794E248C2 auid=4294967295 ses=4294967295 lsm=ipe res=1 The above audit record shows IPE loaded a new policy named "dmverity_roothash" with the sha256 hash of the policy. audit: MAC_CONFIG_CHANGE old_active_pol_name="Allow_All" old_active_pol_version=0.0.0 old_sha256=DA39A3EE5E6B4B0D3255BFEF95601890AFD80709 new_active_pol_name="dmverity_roothash" new_active_pol_version=0.0.0 new_sha256=DC67AC19E05894EFB3170A8E55DE529794E248C2 auid=4294967295 ses=4294967295 lsm=ipe res=1 The above audit record shows IPE's active policy switched from "Allow_All" to "dmverity_roothash". These result in the following events (the audit records are always prior to a SYSCALL record): audit: AUDIT1420 path="/tmp/tmpwxmam366/deny/bin/hello" dev="tmpfs" ino=72 rule="DEFAULT op=EXECUTE action=DENY" audit[476]: SYSCALL arch=c03e syscall=59 success=no exit=-13 a0=7f7d01b5e890 a1=7f7d01f80e80 a2=7ffde535f230 a3=0 items=0 ppid=229 pid=476 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=4294967295 comm="python3" exe="/usr/bin/python3.10" key=(null) audit: PROCTITLE proctitle=707974686F6E3300746573742F6D61696E2E7079002D66002E2E The above events shows IPE blocked the hello file which python was trying to execute. audit: AUDIT1420 path="/tmp/tmpxkvb3d9x/deny/bin/hello" dev="tmpfs" ino=157 rule="DEFAULT action=DENY" audit[1195]: SYSCALL arch=c03e syscall=9 success=no exit=-13 a0=0 a1=18020 a2=6 a3=2 items=0 ppid=997 pid=1195 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=4294967295 comm="mmap_test" exe="/tmp/ipe-test/bin/mmap_test" key=(null) audit: PROCTITLE proctitle=2F746D702F6970652D746573742F62696E2F6D6D61705F746573 The above events shows IPE blocked the hello file which /tmp/ipe-test/bin/mmap_test was trying to mmap. audit: MAC_POLICY_LOAD policy_name="dmverity_roothash" policy_version=0.0.0 sha256=DC67AC19E05894EFB3170A8E55DE529794E248C2 auid=4294967295 ses=4294967295 lsm=ipe res=1 audit[229]: SYSCALL arch=c03e syscall=1 success=yes exit=2567 a0=3 a1=5596fcae1fb0 a2=a07 a3=2 items=0 ppid=184 pid=229 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sg id=0 fsgid=0 tty=pts0 ses=4294967295 comm="python3" exe="/usr/bin/python3.10" key=(null) audit: PROCTITLE proctitle=707974686F6E3300746573742F6D61696E2E7079002D66002E2E The above events shows IPE loaded a new policy "dmverity_roothash" because python used write system call. audit: MAC_CONFIG_CHANGE old_active_pol_name="Allow_All" old_active_pol_version=0.0.0 old_sha256=DA39A3EE5E6B4B0D3255BFEF95601890AFD80709 new_active_pol_name="dmverity_roothash" new_active_pol_version=0.0.0 new_sha256=DC67AC19E05894EFB3170A8E55DE529794E248C2 auid=4294967295 ses=4294967295 lsm=ipe res=1 audit[229]: SYSCALL arch=c03e syscall=1 success=yes exit=2 a0=3 a1=5596fcae1fb0 a2=2 a3=2 items=0 ppid=184 pid=229 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=4294967295 comm="python3" exe="/usr/bin/python3.10" key=(null) audit: PROCTITLE proctitle=707974686F6E3300746573742F6D61696E2E7079002D66002E2 The above events shows IPE switched to a new active policy "dmverity_roothash" because python used write system call. Signed-off-by: Deven Bowers Signed-off-by: Fan Wu --- 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
Re: [RFC PATCH v9 07/16] uapi|audit|ipe: add ipe auditing support
On Mon, 2023-01-30 at 14:57 -0800, Fan Wu wrote: > From: 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. Not sure if this comment makes sense. When a new function is introduced, like ipe_update_policy(), I like to see it in only one patch, not with subsequent changes, unless it is really necessary. If it is possible, I would always introduce the dependencies before and then the new function. Roberto > This patch adds the following audit records: > > audit: AUDIT1420 path="/tmp/tmpwxmam366/deny/bin/hello" dev="tmpfs" > ino=72 rule="DEFAULT op=EXECUTE action=DENY" > > The above audit record shows IPE blocked a file > /tmp/tmpwxmam366/deny/bin/hello in the temp file system. > > audit: AUDIT1420 path="/tmp/tmpxkvb3d9x/deny/bin/hello" dev="tmpfs" > ino=157 rule="DEFAULT action=DENY" > > The above audit record shows IPE blocked a file > /tmp/tmpxkvb3d9x/deny/bin/hello in the temp file system via another > rule. > > audit: MAC_POLICY_LOAD policy_name="dmverity_roothash" > policy_version=0.0.0 sha256=DC67AC19E05894EFB3170A8E55DE529794E248C2 > auid=4294967295 ses=4294967295 lsm=ipe res=1 > > The above audit record shows IPE loaded a new policy named > "dmverity_roothash" with the sha256 hash of the policy. > > audit: MAC_CONFIG_CHANGE old_active_pol_name="Allow_All" > old_active_pol_version=0.0.0 > old_sha256=DA39A3EE5E6B4B0D3255BFEF95601890AFD80709 > new_active_pol_name="dmverity_roothash" new_active_pol_version=0.0.0 > new_sha256=DC67AC19E05894EFB3170A8E55DE529794E248C2 > auid=4294967295 ses=4294967295 lsm=ipe res=1 > > The above audit record shows IPE's active policy switched from > "Allow_All" to "dmverity_roothash". > > These result in the following events (the audit records are always > prior to a SYSCALL record): > > audit: AUDIT1420 path="/tmp/tmpwxmam366/deny/bin/hello" dev="tmpfs" > ino=72 rule="DEFAULT op=EXECUTE action=DENY" > audit[476]: SYSCALL arch=c03e syscall=59 success=no exit=-13 > a0=7f7d01b5e890 a1=7f7d01f80e80 a2=7ffde535f230 a3=0 items=0 ppid=229 > pid=476 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 > fsgid=0 tty=pts0 ses=4294967295 comm="python3" exe="/usr/bin/python3.10" > key=(null) > audit: PROCTITLE > proctitle=707974686F6E3300746573742F6D61696E2E7079002D66002E2E > > The above events shows IPE blocked the hello file which python was > trying to execute. > > audit: AUDIT1420 path="/tmp/tmpxkvb3d9x/deny/bin/hello" dev="tmpfs" > ino=157 rule="DEFAULT action=DENY" > audit[1195]: SYSCALL arch=c03e syscall=9 success=no > exit=-13 a0=0 a1=18020 a2=6 a3=2 items=0 ppid=997 pid=1195 > auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 > tty=pts0 ses=4294967295 comm="mmap_test" > exe="/tmp/ipe-test/bin/mmap_test" key=(null) > audit: PROCTITLE > proctitle=2F746D702F6970652D746573742F62696E2F6D6D61705F746573 > > The above events shows IPE blocked the hello file which > /tmp/ipe-test/bin/mmap_test was trying to mmap. > > audit: MAC_POLICY_LOAD policy_name="dmverity_roothash" > policy_version=0.0.0 sha256=DC67AC19E05894EFB3170A8E55DE529794E248C2 > auid=4294967295 ses=4294967295 lsm=ipe res=1 > audit[229]: SYSCALL arch=c03e syscall=1 success=yes exit=2567 a0=3 > a1=5596fcae1fb0 a2=a07 a3=2 items=0 ppid=184 pid=229 auid=4294967295 > uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sg > id=0 fsgid=0 tty=pts0 ses=4294967295 comm="python3" > exe="/usr/bin/python3.10" key=(null) > audit: PROCTITLE > proctitle=707974686F6E3300746573742F6D61696E2E7079002D66002E2E > > The above events shows IPE loaded a new policy "dmverity_roothash" > because python used write system call. > > audit: MAC_CONFIG_CHANGE old_active_pol_name="Allow_All" > old_active_pol_version=0.0.0 > old_sha256=DA39A3EE5E6B4B0D3255BFEF95601890AFD80709 > new_active_pol_name="dmverity_roothash" new_active_pol_version=0.0.0 > new_sha256=DC67AC19E05894EFB3170A8E55DE529794E248C2 > auid=4294967295 ses=4294967295 lsm=ipe res=1 > audit[229]: SYSCALL arch=c03e syscall=1 success=yes exit=2 a0=3 > a1=5596fcae1fb0 a2=2 a3=2 items=0 ppid=184 pid=229 auid=4294967295 uid=0 > gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 >
[RFC PATCH v9 00/16] Integrity Policy Enforcement LSM (IPE)
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, such as the case where a Linux distribution vendor trusts only their own keys, where IPE can successfully be used to enforce the trust requirement. 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. 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 rule will allow any execution. 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. 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. For example: op=EXECUTE dmverity_signature=FALSE action=DENY This rule with property dmverity_signature will deny any file not from a signed dmverity volume to be executed. All available properties for IPE described in the documentation patch of this series. 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. 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 userspace 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 config, SECURITY_IPE_BOOT_POLICY, which accepts a path to a plain-text version of the IPE policy to apply. This policy will be compiled into the kernel. If not specified, IPE will be disabled until a policy is deployed and activated through the method above. Policy Examples: Allow all: policy_name=Allow_All policy_version=0.0.0 DEFAULT action=ALLOW Allow only initial superblock: policy_name=Allow_All_Initial_SB policy_version=0.0.0 DEFAULT action=DENY op=EXECUTE boot_verified=TRUE act
Re: [RFC PATCH v9 10/16] dm-verity: consume root hash digest and signature data via LSM hook
On Mon, 2023-01-30 at 14:57 -0800, Fan Wu wrote: > From: 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 higher layers, including the filesystem > level. I think you could reuse most of is_trusted_verity_target(), in particular dm_verity_get_root_digest(). And probably, the previous patch is not necessary. Roberto > 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 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 > Signed-off-by: Fan Wu > --- > 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. > > v9: > + No changes > --- > 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 ccf5b852fbf7..afea61eed4ec 100644 > --- a/drivers/md/dm-verity-target.c > +++ b/drivers/md/dm-verity-target.c > @@ -13,6 +13,7 @@ > * access behavior. > */ > > +#include "dm-core.h" > #include "dm-verity.h" > #include "dm-verity-fec.h" > #include "dm-verity-verify-sig.h" > @@ -21,6 +22,9 @@ > #include > #include > #include > +#include > +#include > +#include > > #define DM_MSG_PREFIX"verity" > > @@ -1169,6 +1173,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) { > @@ -1211,6 +1217,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"; > @@ -1343,7 +1356,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); > @@ -1428,12 +1441,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_cle
Re: [RFC PATCH v9 00/16] Integrity Policy Enforcement LSM (IPE)
On Mon, 2023-01-30 at 14:57 -0800, Fan Wu wrote: > 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, such as the case where a Linux distribution > vendor trusts only their own keys, where IPE can successfully be used > to enforce the trust requirement. > > 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. 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 rule will allow any execution. 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. > > 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. > > For example: > > op=EXECUTE dmverity_signature=FALSE action=DENY > > This rule with property dmverity_signature will deny any file not from > a signed dmverity volume to be executed. > > All available properties for IPE described in the documentation patch of > this series. > > 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. > > 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 userspace 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 config, SECURITY_IPE_BOOT_POLICY, which accepts a path > to a plain-text version of the IPE policy to apply. This policy will be > compiled into the kernel. If not specified, IPE will be disabled until a > policy is deployed and activated through th
Re: [RFC PATCH v9 13/16] ipe: enable support for fs-verity as a trust provider
On Mon, 2023-01-30 at 14:57 -0800, Fan Wu wrote: > 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: Deven Bowers > Signed-off-by: Fan Wu > --- > 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. > > v9: > + Adapt to the new parser > --- > security/ipe/Kconfig | 11 > security/ipe/audit.c | 23 +++ > security/ipe/eval.c | 112 +++ > security/ipe/eval.h | 10 > security/ipe/hooks.c | 30 ++ > security/ipe/hooks.h | 7 +++ > security/ipe/ipe.c | 13 > security/ipe/ipe.h | 3 + > security/ipe/policy.h| 3 + > security/ipe/policy_parser.c | 8 +++ > 10 files changed, 220 insertions(+) > > diff --git a/security/ipe/Kconfig b/security/ipe/Kconfig > index 16e835ce61b0..dd9a066dd35a 100644 > --- a/security/ipe/Kconfig > +++ b/security/ipe/Kconfig > @@ -32,6 +32,17 @@ config IPE_PROP_DM_VERITY > > If unsure, answer Y. > > +config IPE_PROP_FS_VERITY > + bool "Enable property for fs-verity files" > + depends on FS_VERITY && FS_VERITY_BUILTIN_SIGNATURES > + help > + This option enables the usage of properties "fsverity_signature" > + and "fsverity_digest". These properties evaluates to TRUE when > + a file is fsverity enabled and with a signed digest or its > + diegst matches the supplied value in the policy. > + > + if unsure, answer Y. > + > endmenu > > endif > diff --git a/security/ipe/audit.c b/security/ipe/audit.c > index 769ba95d9b0d..16d81645e53c 100644 > --- a/security/ipe/audit.c > +++ b/security/ipe/audit.c > @@ -46,6 +46,11 @@ static const char *const audit_prop_names[ipe_prop_max] = { > "dmverity_signature=FALSE", > "dmverity_signature=TRUE", > #endif /* CONFIG_IPE_PROP_DM_VERITY */ > +#ifdef CONFIG_IPE_PROP_FS_VERITY > + "fsverity_digest=", > + "fsverity_signature=FALSE", > + "fsverity_signature=TRUE" > +#endif /* CONFIG_IPE_PROP_FS_VERITY */ > }; > > #ifdef CONFIG_IPE_PROP_DM_VERITY > @@ -64,6 +69,22 @@ static void audit_dmv_roothash(struct audit_buffer *ab, > const void *rh) > } > #endif /* CONFIG_IPE_PROP_DM_VERITY */ > > +#ifdef CONFIG_IPE_PROP_FS_VERITY > +/** > + * audit_fsv_digest - audit a digest of a fsverity file. > + * @ab: Supplies a poniter to the audit_buffer to append to. > + * @d: Supplies a pointer to the digest structure. > + */ > +static void audit_fsv_digest(struct audit_buffer *ab, const void *d) > +{ > + ipe_digest_audit(ab, d); > +} > +#else > +static void audit_fsv_digest(struct audit_buffer *ab, const void *d) > +{ > +} > +#endif /* CONFIG_IPE_PROP_DM_VERITY */ > + > /** > * audit_rule - audit an IPE policy rule approximation. > * @ab: Supplies a poniter to the audit_buffer to append to. > @@ -79,6 +100,8 @@ static void audit_rule(struct audit_buffer *ab, const > struct ipe_rule *r) > audit_log_format(ab, "%s", audit_prop_names[ptr->type]); > if (ptr->type == ipe_prop_dmv_roothash) > audit_dmv_roothash(ab, ptr->value); > + if (ptr->type == ipe_prop_fsv_digest) > + audit_fsv_digest(ab, ptr->value); > > audit_log_format(ab, " "); > } > diff --git a/security/ipe/eval.c b/security/ipe/eval.c > index 538af4195ba7..210d3926c0a8 100644 > --- a/security/ipe/eval.c > +++ b/security/ipe/eval.c > @@ -81,6 +81,23 @@ static void build_ipe_bdev_ctx(struct ipe_eval_ctx *ctx, > const struct inode *con > } > #endif
Re: audit library license
Hello, On Monday, January 30, 2023 7:55:20 PM EST hiroaki.f...@ymail.ne.jp wrote: > Dear All members, > > We can find following lines in audit/README file > > LICENSE > === > The audit daemon is released as GPL'd code. The audit daemon's libraries > libaudit.* and libauparse.* are released under LGPL so that it may be > linked with 3rd party software. > > I found that latest audit library linked libaucommon.so. > > ./lib/Makefile.in:AM_CPPFLAGS = -I. -I${top_srcdir} -I${top_srcdir}/auparse > -I${top_srcdir}/common ./lib/Makefile.in:libaudit_la_LIBADD = > $(CAPNG_LDADD) ${top_builddir}/common/libaucommon.la > ./lib/Makefile.in:libaudit_la_DEPENDENCIES = $(libaudit_la_SOURCES) > ../config.h ${top_builddir}/common/libaucommon.la > > ./auparse/Makefile.am:AM_CPPFLAGS = -I. -I${top_srcdir} -I${top_srcdir}/src > -I${top_srcdir}/lib -I${top_srcdir}/common > ./auparse/Makefile.am:libauparse_la_LIBADD = > ${top_builddir}/lib/libaudit.la ${top_builddir}/common/libaucommon.la > ./auparse/Makefile.am:libauparse_la_DEPENDENCIES = > $(libauparse_la_SOURCES) ${top_builddir}/config.h > ${top_builddir}/common/libaucommon.la > > Libaucommo.so is created by following files > > ./common/Makefile.am:libaucommon_la_SOURCES = audit-fgets.c strsplit.c > > And the license of audit/common/audit-fgets.c is GPLv2 > > This mean the license of latest audit libraries are also GPLv2. > > Is my understanding correct? The intention stated in the README file is correct. The code in question is only used by 3 plugins which are GPL and those functions are hidden from external users of libaudit. The code can be relicenced to make it LGPL so everything matches the intentions. -Steve -- Linux-audit mailing list Linux-audit@redhat.com https://listman.redhat.com/mailman/listinfo/linux-audit
Re: [RFC PATCH v9 03/16] ipe: add evaluation loop and introduce 'boot_verified' as a trust provider
On Mon, 2023-01-30 at 14:57 -0800, Fan Wu wrote: > From: Deven Bowers > > IPE must have a centralized function to evaluate incoming callers > against IPE's policy. This iteration of the policy against the rules > for that specific caller is known as the evaluation loop. Not sure if you check the properties at every access. >From my previous comments (also for previous versions of the patches) you could evaluate the property once, by calling the respective functions in the other subsystems. Then, you reserve space in the security blob for inodes and superblocks to cache the decision. The format could be a policy sequence number, to ensure that the cache is valid only for the current policy, and a bit for every hook you enforce. Also, currently you rely on the fact that the properties you defined are immutable and the immutability is guaranteed by the other subsystems, so no write can occur. But if you remove this limitation, the immutability is not guaranteed anymore by the other subsystems (for example if a file is in an ext4 filesystem), the LSM needs to take extra care to ensure that the properties are still verified. This would be required for example if IPE is used in conjuction with DIGLIM. In my opinion, IPE value would increase if the generic enforcement mechanism is property-agnostic. Roberto > In addition, 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 > Signed-off-by: Fan Wu > > --- > 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. > > v8: > + Remove ipe_hook enumeration; hooks can be correlated via syscall > record. > > v9: > + Remove ipe_context related code and simplify the evaluation loop. > + Merge the evaluation loop commit with the boot_verified commit. > --- > security/ipe/Makefile| 1 + > security/ipe/eval.c | 180 +++ > security/ipe/eval.h | 28 ++ > security/ipe/hooks.c | 25 + > security/ipe/hooks.h | 14 +++ > security/ipe/ipe.c | 1 + > security/ipe/policy.c| 20 > security/ipe/policy.h| 3 + > security/ipe/policy_parser.c | 8 +- > 9 files changed, 279 insertions(+), 1 deletion(-) > create mode 100644 security/ipe/eval.c > create mode 100644 security/ipe/eval.h > create mode 100644 security/ipe/hooks.c > create mode 100644 security/ipe/hooks.h > > diff --git a/security/ipe/Makefile b/security/ipe/Makefile > index 16bbe80991f1..d7f2870d7c09 100644 > --- a/security/ipe/Makefile > +++ b/security/ipe/Makefile > @@ -6,6 +6,7 @@ > # > > obj-$(CONFIG_SECURITY_IPE) += \ > + eval.o \ > hooks.o \ > ipe.o \ > policy.o \ > diff --git a/security/ipe/eval.c b/security/ipe/eval.c > new file mode 100644 > index ..48b5104a3463 > --- /dev/null > +++ b/security/ipe/eval.c > @@ -0,0 +1,180 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (C) Microsoft Corporation. All rights reserved. > + */ > + > +#include "ipe.h" > +#include "eval.h" > +#include "hooks.h" > +#include "policy.h" > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +struct ipe_policy __rcu *ipe_active_policy; > + > +static struct super_block *pinned_sb
Re: [RFC PATCH v9 07/16] uapi|audit|ipe: add ipe auditing support
Hello, On Monday, January 30, 2023 5:57:22 PM EST Fan Wu wrote: > From: 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. Typically when you reuse an existing record type, it is expected to maintain the same fields in the same order. Also, it is expect that fields that are common across diferent records have the same meaning. To aid in this, we have a field dictionary here: https://github.com/linux-audit/audit-documentation/blob/main/specs/fields/ field-dictionary.csv For example, dev is expected to be 2 hex numbers separated by a colon which are the device major and minor numbers. But down a couple lines from here, we find dev="tmpfs". But isn't that a filesystem type? > 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. > > This patch adds the following audit records: > > audit: AUDIT1420 path="/tmp/tmpwxmam366/deny/bin/hello" dev="tmpfs" > ino=72 rule="DEFAULT op=EXECUTE action=DENY" Do we really need to log the whole rule? > The above audit record shows IPE blocked a file > /tmp/tmpwxmam366/deny/bin/hello in the temp file system. > > audit: AUDIT1420 path="/tmp/tmpxkvb3d9x/deny/bin/hello" dev="tmpfs" > ino=157 rule="DEFAULT action=DENY" > > The above audit record shows IPE blocked a file > /tmp/tmpxkvb3d9x/deny/bin/hello in the temp file system via another > rule. > > audit: MAC_POLICY_LOAD policy_name="dmverity_roothash" > policy_version=0.0.0 sha256=DC67AC19E05894EFB3170A8E55DE529794E248C2 > auid=4294967295 ses=4294967295 lsm=ipe res=1 The MAC_POLICY_LOAD record type simply states the lsm that had it's policy loaded. There isn't name, version, and hash information. I'd prefer to see all users of this record type decide if it should be extended because they also have that information available to record. > The above audit record shows IPE loaded a new policy named > "dmverity_roothash" with the sha256 hash of the policy. > > audit: MAC_CONFIG_CHANGE old_active_pol_name="Allow_All" > old_active_pol_version=0.0.0 > old_sha256=DA39A3EE5E6B4B0D3255BFEF95601890AFD80709 > new_active_pol_name="dmverity_roothash" new_active_pol_version=0.0.0 > new_sha256=DC67AC19E05894EFB3170A8E55DE529794E248C2 > auid=4294967295 ses=4294967295 lsm=ipe res=1 > > The above audit record shows IPE's active policy switched from > "Allow_All" to "dmverity_roothash". Shouldn't this just be another MAC_POLICY_LOAD? That would match other LSM's. The MAC_CONFIG_CHANGE is to denote that a changeable option was modified from one value to another. But it is still operating under the same policy. -Steve > These result in the following events (the audit records are always > prior to a SYSCALL record): > > audit: AUDIT1420 path="/tmp/tmpwxmam366/deny/bin/hello" dev="tmpfs" > ino=72 rule="DEFAULT op=EXECUTE action=DENY" > audit[476]: SYSCALL arch=c03e syscall=59 success=no exit=-13 > a0=7f7d01b5e890 a1=7f7d01f80e80 a2=7ffde535f230 a3=0 items=0 ppid=229 > pid=476 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 > fsgid=0 tty=pts0 ses=4294967295 comm="python3" exe="/usr/bin/python3.10" > key=(null) > audit: PROCTITLE > proctitle=707974686F6E3300746573742F6D61696E2E7079002D66002E2E > > The above events shows IPE blocked the hello file which python was > trying to execute. > > audit: AUDIT1420 path="/tmp/tmpxkvb3d9x/deny/bin/hello" dev="tmpfs" > ino=157 rule="DEFAULT action=DENY" > audit[1195]: SYSCALL arch=c03e syscall=9 success=no > exit=-13 a0=0 a1=18020 a2=6 a3=2 items=0 ppid=997 pid=1195 > auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 > tty=pts0 ses=4294967295 comm="mmap_test" > exe="/tmp/ipe-test/bin/mmap_test" key=(null) > audit: PROCTITLE > proctitle=2F746D702F6970652D746573742F62696E2F6D6D61705F746573 > > The above events shows IPE blocked the hello file which > /tmp/ipe-test/bin/mmap_test was trying to mmap. > > audit: MAC_POLICY_LOAD policy_name="dmverity_roothash" > policy_version=0.0.0 sha256=DC67AC19E05894EFB3170A8E55DE529794E248C2 > auid=4294967295 ses=4294967295 lsm=ipe res=1 > audit[229]: SYSCALL arch=c03e syscall=1 success=yes exit=2567 a0=3 > a1=5596fcae1fb0 a2=a07 a3=2 items=0 ppid=184 pid=229 auid=4294967295 > uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sg > id=0 fsgid=0 tty=pts0 ses=4294
Upstream kernel development and the linux-audit mailing list
Hello all, Those of you who have been following the linux-audit mailing list closely over the past several years have likely seen some issues relating to upstream Linux Kernel development and the mailing list: disagreements on the focus of the list (upstream vs upstream+distro), and a moderated vs open posting policy. In general the disagreements around the focus of the list, while annoying at times, tended not to be significant issues. Unfortunately, the issue of list moderation has been a problem with other subsystem maintainers and developers dropping the audit list from their discussions due to the moderation settings. While I had hoped that we might change the list to an open list, just like most of the upstream kernel mailing lists, Steve has mentioned that he does not want to make the change due to concerns over SPAM. With that in mind, I'm going to suggest moving the development of audit in the upstream Linux Kernel to a new mailing list hosted on vger.kernel.org. Many of you who participate, or at least monitor, kernel development are no doubt already subscribed to at least one mailing list hosted on vger as it is one of the most common (*the* most common?) list host for Linux Kernel related development. I don't want to make any statements with respect to Steve's audit userspace, that is up to him, but I don't have any problem if he wants to move upstream discussion of his audit userspace tools to the same vger-based list. I'll hold off on list creation for a couple of days in case anyone has a well reasoned argument against moving upstream kernel development to a new list. However, I want to underscore that any argument to keep upstream discussions on a moderated list will need to be strong enough to counter potentially excluding other subsystems from the discussion. -- paul-moore.com -- Linux-audit mailing list Linux-audit@redhat.com https://listman.redhat.com/mailman/listinfo/linux-audit
Re: Re: audit library license
Hello, Thank you for the comment. I also find following commit. - https://github.com/linux-audit/audit-userspace/commit/e63a8b1628170151016470075396e3697dd57a9b BTW, I found another license question. The libauparse.so are created following source codes. In 'auparse/Makefile.am' AM_CPPFLAGS = -I. -I${top_srcdir} -I${top_srcdir}/src -I${top_srcdir}/lib -I${top_srcdir}/common : libauparse_la_SOURCES = lru.c interpret.c nvlist.c ellist.c \ auparse.c auditd-config.c message.c data_buf.c \ auparse-defs.h auparse-idata.h data_buf.h \ nvlist.h auparse.h ellist.h \ internal.h lru.h rnode.h interpret.h\ private.h expression.c expression.h tty_named_keys.h\ normalize.c normalize-llist.c normalize-llist.h \ normalize-internal.h normalize_obj_kind_map.h \ normalize_record_map.h normalize_syscall_map.h We can find following line in internal.h #include "auditd-config.h" I can find src/auditd-config.h file which is GPLv2. The "src/auditd-config.h" should be also LGPLv2.1 Regardss, > - Original Message - > > From: "Steve Grubb" > To: "linux-audit@redhat.com" > Cc: "hiroaki.f...@ymail.ne.jp" > Date: 2023/02/01 水 00:53 > Subject: Re: audit library license > > > Hello, > > On Monday, January 30, 2023 7:55:20 PM EST hiroaki.f...@ymail.ne.jp wrote: > > Dear All members, > > > > We can find following lines in audit/README file > > > > LICENSE > > === > > The audit daemon is released as GPL'd code. The audit daemon's libraries > > libaudit.* and libauparse.* are released under LGPL so that it may be > > linked with 3rd party software. > > > > I found that latest audit library linked libaucommon.so. > > > > ./lib/Makefile.in:AM_CPPFLAGS = -I. -I${top_srcdir} -I${top_srcdir}/auparse > > -I${top_srcdir}/common ./lib/Makefile.in:libaudit_la_LIBADD = > > $(CAPNG_LDADD) ${top_builddir}/common/libaucommon.la > > ./lib/Makefile.in:libaudit_la_DEPENDENCIES = $(libaudit_la_SOURCES) > > ../config.h ${top_builddir}/common/libaucommon.la > > > > ./auparse/Makefile.am:AM_CPPFLAGS = -I. -I${top_srcdir} -I${top_srcdir}/src > > -I${top_srcdir}/lib -I${top_srcdir}/common > > ./auparse/Makefile.am:libauparse_la_LIBADD = > > ${top_builddir}/lib/libaudit.la ${top_builddir}/common/libaucommon.la > > ./auparse/Makefile.am:libauparse_la_DEPENDENCIES = > > $(libauparse_la_SOURCES) ${top_builddir}/config.h > > ${top_builddir}/common/libaucommon.la > > > > Libaucommo.so is created by following files > > > > ./common/Makefile.am:libaucommon_la_SOURCES = audit-fgets.c strsplit.c > > > > And the license of audit/common/audit-fgets.c is GPLv2 > > > > This mean the license of latest audit libraries are also GPLv2. > > > > Is my understanding correct? > > The intention stated in the README file is correct. The code in question is > only used by 3 plugins which are GPL and those functions are hidden from > external users of libaudit. The code can be relicenced to make it LGPL so > everything matches the intentions. > > -Steve > > > -- > Linux-audit mailing list > Linux-audit@redhat.com > https://listman.redhat.com/mailman/listinfo/linux-audit > > -- Linux-audit mailing list Linux-audit@redhat.com https://listman.redhat.com/mailman/listinfo/linux-audit