]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ipe: Add AT_EXECVE_CHECK support for script enforcement
authorYanzhu Huang <yanzhuhuang@linux.microsoft.com>
Wed, 5 Nov 2025 23:26:14 +0000 (23:26 +0000)
committerFan Wu <wufan@kernel.org>
Wed, 3 Dec 2025 03:37:01 +0000 (19:37 -0800)
This patch adds a new ipe_bprm_creds_for_exec() hook that integrates
with the AT_EXECVE_CHECK mechanism. To enable script enforcement,
interpreters need to incorporate the AT_EXECVE_CHECK flag when
calling execveat() on script files before execution.

When a userspace interpreter calls execveat() with the AT_EXECVE_CHECK
flag, this hook triggers IPE policy evaluation on the script file. The
hook only triggers IPE when bprm->is_check is true, ensuring it's
being called from an AT_EXECVE_CHECK context. It then builds an
evaluation context for an IPE_OP_EXEC operation and invokes IPE policy.
The kernel returns the policy decision to the interpreter, which can
then decide whether to proceed with script execution.

This extends IPE enforcement to indirectly executed scripts, permitting
trusted scripts to execute while denying untrusted ones.

Signed-off-by: Yanzhu Huang <yanzhuhuang@linux.microsoft.com>
Signed-off-by: Fan Wu <wufan@kernel.org>
security/ipe/audit.c
security/ipe/hooks.c
security/ipe/hooks.h
security/ipe/ipe.c

index de5fed62592e1d06089c3b078b5e4b73e24730ac..3f0deeb54912730d9acf5e021a4a0cb29a34e982 100644 (file)
@@ -46,6 +46,7 @@ static const char *const audit_op_names[__IPE_OP_MAX + 1] = {
 
 static const char *const audit_hook_names[__IPE_HOOK_MAX] = {
        "BPRM_CHECK",
+       "BPRM_CREDS_FOR_EXEC",
        "MMAP",
        "MPROTECT",
        "KERNEL_READ",
index 42857c2ea2a582ad32c484588234c7580da455e2..2e3dc4ab22aebf96e18de74404909110a1ad2e77 100644 (file)
@@ -35,6 +35,33 @@ int ipe_bprm_check_security(struct linux_binprm *bprm)
        return ipe_evaluate_event(&ctx);
 }
 
+/**
+ * ipe_bprm_creds_for_exec() - ipe security hook function for bprm creds check.
+ * @bprm: Supplies a pointer to a linux_binprm structure to source the file
+ *       being evaluated.
+ *
+ * This LSM hook is called when userspace signals the kernel to check a file
+ * for execution through the execveat syscall with the AT_EXECVE_CHECK flag.
+ * The hook triggers IPE policy evaluation on the script file and returns
+ * the policy decision to userspace. The userspace program receives the
+ * return code and can decide whether to proceed with script execution.
+ *
+ * Return:
+ * * %0                - Success
+ * * %-EACCES  - Did not pass IPE policy
+ */
+int ipe_bprm_creds_for_exec(struct linux_binprm *bprm)
+{
+       struct ipe_eval_ctx ctx = IPE_EVAL_CTX_INIT;
+
+       if (!bprm->is_check)
+               return 0;
+
+       ipe_build_eval_ctx(&ctx, bprm->file, IPE_OP_EXEC,
+                          IPE_HOOK_BPRM_CREDS_FOR_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.
index 38d4a387d039f99db46cc987e80ac3d9ff7664a0..07db373327402881b887d0ae25ab4c662f434478 100644 (file)
@@ -13,6 +13,7 @@
 
 enum ipe_hook_type {
        IPE_HOOK_BPRM_CHECK = 0,
+       IPE_HOOK_BPRM_CREDS_FOR_EXEC,
        IPE_HOOK_MMAP,
        IPE_HOOK_MPROTECT,
        IPE_HOOK_KERNEL_READ,
@@ -24,6 +25,8 @@ enum ipe_hook_type {
 
 int ipe_bprm_check_security(struct linux_binprm *bprm);
 
+int ipe_bprm_creds_for_exec(struct linux_binprm *bprm);
+
 int ipe_mmap_file(struct file *f, unsigned long reqprot, unsigned long prot,
                  unsigned long flags);
 
index 4317134cb0da1f03a98691f3f613db216a4cc934..845e3fd7a345da4639a89dd6a43a9a0df404ebbc 100644 (file)
@@ -47,6 +47,7 @@ struct ipe_inode *ipe_inode(const struct inode *inode)
 
 static struct security_hook_list ipe_hooks[] __ro_after_init = {
        LSM_HOOK_INIT(bprm_check_security, ipe_bprm_check_security),
+       LSM_HOOK_INIT(bprm_creds_for_exec, ipe_bprm_creds_for_exec),
        LSM_HOOK_INIT(mmap_file, ipe_mmap_file),
        LSM_HOOK_INIT(file_mprotect, ipe_file_mprotect),
        LSM_HOOK_INIT(kernel_read_file, ipe_kernel_read_file),