Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

audit,ipe: add IPE auditing support

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 systems with respect to IPE
itself.

This patch introduces 3 new audit events.

AUDIT_IPE_ACCESS(1420) indicates the result of an IPE policy evaluation
of a resource.
AUDIT_IPE_CONFIG_CHANGE(1421) indicates the current active IPE policy
has been changed to another loaded policy.
AUDIT_IPE_POLICY_LOAD(1422) indicates a new IPE policy has been loaded
into the kernel.

This patch also adds support for success auditing, allowing users to
identify why an allow decision was made for a resource. However, it is
recommended to use this option with caution, as it is quite noisy.

Here are some examples of the new audit record types:

AUDIT_IPE_ACCESS(1420):

audit: AUDIT1420 ipe_op=EXECUTE ipe_hook=BPRM_CHECK enforcing=1
pid=297 comm="sh" path="/root/vol/bin/hello" dev="tmpfs"
ino=3897 rule="op=EXECUTE boot_verified=TRUE action=ALLOW"

audit: AUDIT1420 ipe_op=EXECUTE ipe_hook=BPRM_CHECK enforcing=1
pid=299 comm="sh" path="/mnt/ipe/bin/hello" dev="dm-0"
ino=2 rule="DEFAULT action=DENY"

audit: AUDIT1420 ipe_op=EXECUTE ipe_hook=BPRM_CHECK enforcing=1
pid=300 path="/tmp/tmpdp2h1lub/deny/bin/hello" dev="tmpfs"
ino=131 rule="DEFAULT action=DENY"

The above three records were generated when the active IPE policy only
allows binaries from the initramfs to run. The three identical `hello`
binary were placed at different locations, only the first hello from
the rootfs(initramfs) was allowed.

Field ipe_op followed by the IPE operation name associated with the log.

Field ipe_hook followed by the name of the LSM hook that triggered the IPE
event.

Field enforcing followed by the enforcement state of IPE. (it will be
introduced in the next commit)

Field pid followed by the pid of the process that triggered the IPE
event.

Field comm followed by the command line program name of the process that
triggered the IPE event.

Field path followed by the file's path name.

Field dev followed by the device name as found in /dev where the file is
from.
Note that for device mappers it will use the name `dm-X` instead of
the name in /dev/mapper.
For a file in a temp file system, which is not from a device, it will use
`tmpfs` for the field.
The implementation of this part is following another existing use case
LSM_AUDIT_DATA_INODE in security/lsm_audit.c

Field ino followed by the file's inode number.

Field rule followed by the IPE rule made the access decision. The whole
rule must be audited because the decision is based on the combination of
all property conditions in the rule.

Along with the syscall audit event, user can know why a blocked
happened. For example:

audit: AUDIT1420 ipe_op=EXECUTE ipe_hook=BPRM_CHECK enforcing=1
pid=2138 comm="bash" path="/mnt/ipe/bin/hello" dev="dm-0"
ino=2 rule="DEFAULT action=DENY"
audit[1956]: SYSCALL arch=c000003e syscall=59
success=no exit=-13 a0=556790138df0 a1=556790135390 a2=5567901338b0
a3=ab2a41a67f4f1f4e items=1 ppid=147 pid=1956 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)

The above two records showed bash used execve to run "hello" and got
blocked by IPE. Note that the IPE records are always prior to a SYSCALL
record.

AUDIT_IPE_CONFIG_CHANGE(1421):

audit: AUDIT1421
old_active_pol_name="Allow_All" old_active_pol_version=0.0.0
old_policy_digest=sha256:E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649
new_active_pol_name="boot_verified" new_active_pol_version=0.0.0
new_policy_digest=sha256:820EEA5B40CA42B51F68962354BA083122A20BB846F
auid=4294967295 ses=4294967295 lsm=ipe res=1

The above record showed the current IPE active policy switch from
`Allow_All` to `boot_verified` along with the version and the hash
digest of the two policies. Note IPE can only have one policy active
at a time, all access decision evaluation is based on the current active
policy.
The normal procedure to deploy a policy is loading the policy to deploy
into the kernel first, then switch the active policy to it.

AUDIT_IPE_POLICY_LOAD(1422):

audit: AUDIT1422 policy_name="boot_verified" policy_version=0.0.0
policy_digest=sha256:820EEA5B40CA42B51F68962354BA083122A20BB846F2676
auid=4294967295 ses=4294967295 lsm=ipe res=1

The above record showed a new policy has been loaded into the kernel
with the policy name, policy version and policy hash.

Signed-off-by: Deven Bowers <deven.desai@linux.microsoft.com>
Signed-off-by: Fan Wu <wufan@linux.microsoft.com>
[PM: subject line tweak]
Signed-off-by: Paul Moore <paul@paul-moore.com>

authored by

Deven Bowers and committed by
Paul Moore
f44554b5 2261306f

+384 -18
+3
include/uapi/linux/audit.h
··· 143 143 #define AUDIT_MAC_UNLBL_STCDEL 1417 /* NetLabel: del a static label */ 144 144 #define AUDIT_MAC_CALIPSO_ADD 1418 /* NetLabel: add CALIPSO DOI entry */ 145 145 #define AUDIT_MAC_CALIPSO_DEL 1419 /* NetLabel: del CALIPSO DOI entry */ 146 + #define AUDIT_IPE_ACCESS 1420 /* IPE denial or grant */ 147 + #define AUDIT_IPE_CONFIG_CHANGE 1421 /* IPE config change */ 148 + #define AUDIT_IPE_POLICY_LOAD 1422 /* IPE policy load */ 146 149 147 150 #define AUDIT_FIRST_KERN_ANOM_MSG 1700 148 151 #define AUDIT_LAST_KERN_ANOM_MSG 1799
+1 -1
security/ipe/Kconfig
··· 5 5 6 6 menuconfig SECURITY_IPE 7 7 bool "Integrity Policy Enforcement (IPE)" 8 - depends on SECURITY && SECURITYFS 8 + depends on SECURITY && SECURITYFS && AUDIT && AUDITSYSCALL 9 9 select PKCS7_MESSAGE_PARSER 10 10 select SYSTEM_DATA_VERIFICATION 11 11 help
+1
security/ipe/Makefile
··· 13 13 policy.o \ 14 14 policy_fs.o \ 15 15 policy_parser.o \ 16 + audit.o \
+227
security/ipe/audit.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved. 4 + */ 5 + 6 + #include <linux/slab.h> 7 + #include <linux/audit.h> 8 + #include <linux/types.h> 9 + #include <crypto/hash.h> 10 + 11 + #include "ipe.h" 12 + #include "eval.h" 13 + #include "hooks.h" 14 + #include "policy.h" 15 + #include "audit.h" 16 + 17 + #define ACTSTR(x) ((x) == IPE_ACTION_ALLOW ? "ALLOW" : "DENY") 18 + 19 + #define IPE_AUDIT_HASH_ALG "sha256" 20 + 21 + #define AUDIT_POLICY_LOAD_FMT "policy_name=\"%s\" policy_version=%hu.%hu.%hu "\ 22 + "policy_digest=" IPE_AUDIT_HASH_ALG ":" 23 + #define AUDIT_OLD_ACTIVE_POLICY_FMT "old_active_pol_name=\"%s\" "\ 24 + "old_active_pol_version=%hu.%hu.%hu "\ 25 + "old_policy_digest=" IPE_AUDIT_HASH_ALG ":" 26 + #define AUDIT_OLD_ACTIVE_POLICY_NULL_FMT "old_active_pol_name=? "\ 27 + "old_active_pol_version=? "\ 28 + "old_policy_digest=?" 29 + #define AUDIT_NEW_ACTIVE_POLICY_FMT "new_active_pol_name=\"%s\" "\ 30 + "new_active_pol_version=%hu.%hu.%hu "\ 31 + "new_policy_digest=" IPE_AUDIT_HASH_ALG ":" 32 + 33 + static const char *const audit_op_names[__IPE_OP_MAX + 1] = { 34 + "EXECUTE", 35 + "FIRMWARE", 36 + "KMODULE", 37 + "KEXEC_IMAGE", 38 + "KEXEC_INITRAMFS", 39 + "POLICY", 40 + "X509_CERT", 41 + "UNKNOWN", 42 + }; 43 + 44 + static const char *const audit_hook_names[__IPE_HOOK_MAX] = { 45 + "BPRM_CHECK", 46 + "MMAP", 47 + "MPROTECT", 48 + "KERNEL_READ", 49 + "KERNEL_LOAD", 50 + }; 51 + 52 + static const char *const audit_prop_names[__IPE_PROP_MAX] = { 53 + "boot_verified=FALSE", 54 + "boot_verified=TRUE", 55 + }; 56 + 57 + /** 58 + * audit_rule() - audit an IPE policy rule. 59 + * @ab: Supplies a pointer to the audit_buffer to append to. 60 + * @r: Supplies a pointer to the ipe_rule to approximate a string form for. 61 + */ 62 + static void audit_rule(struct audit_buffer *ab, const struct ipe_rule *r) 63 + { 64 + const struct ipe_prop *ptr; 65 + 66 + audit_log_format(ab, " rule=\"op=%s ", audit_op_names[r->op]); 67 + 68 + list_for_each_entry(ptr, &r->props, next) 69 + audit_log_format(ab, "%s ", audit_prop_names[ptr->type]); 70 + 71 + audit_log_format(ab, "action=%s\"", ACTSTR(r->action)); 72 + } 73 + 74 + /** 75 + * ipe_audit_match() - Audit a rule match in a policy evaluation. 76 + * @ctx: Supplies a pointer to the evaluation context that was used in the 77 + * evaluation. 78 + * @match_type: Supplies the scope of the match: rule, operation default, 79 + * global default. 80 + * @act: Supplies the IPE's evaluation decision, deny or allow. 81 + * @r: Supplies a pointer to the rule that was matched, if possible. 82 + */ 83 + void ipe_audit_match(const struct ipe_eval_ctx *const ctx, 84 + enum ipe_match match_type, 85 + enum ipe_action_type act, const struct ipe_rule *const r) 86 + { 87 + const char *op = audit_op_names[ctx->op]; 88 + char comm[sizeof(current->comm)]; 89 + struct audit_buffer *ab; 90 + struct inode *inode; 91 + 92 + if (act != IPE_ACTION_DENY && !READ_ONCE(success_audit)) 93 + return; 94 + 95 + ab = audit_log_start(audit_context(), GFP_ATOMIC | __GFP_NOWARN, 96 + AUDIT_IPE_ACCESS); 97 + if (!ab) 98 + return; 99 + 100 + audit_log_format(ab, "ipe_op=%s ipe_hook=%s pid=%d comm=", 101 + op, audit_hook_names[ctx->hook], 102 + task_tgid_nr(current)); 103 + audit_log_untrustedstring(ab, get_task_comm(comm, current)); 104 + 105 + if (ctx->file) { 106 + audit_log_d_path(ab, " path=", &ctx->file->f_path); 107 + inode = file_inode(ctx->file); 108 + if (inode) { 109 + audit_log_format(ab, " dev="); 110 + audit_log_untrustedstring(ab, inode->i_sb->s_id); 111 + audit_log_format(ab, " ino=%lu", inode->i_ino); 112 + } else { 113 + audit_log_format(ab, " dev=? ino=?"); 114 + } 115 + } else { 116 + audit_log_format(ab, " path=? dev=? ino=?"); 117 + } 118 + 119 + if (match_type == IPE_MATCH_RULE) 120 + audit_rule(ab, r); 121 + else if (match_type == IPE_MATCH_TABLE) 122 + audit_log_format(ab, " rule=\"DEFAULT op=%s action=%s\"", op, 123 + ACTSTR(act)); 124 + else 125 + audit_log_format(ab, " rule=\"DEFAULT action=%s\"", 126 + ACTSTR(act)); 127 + 128 + audit_log_end(ab); 129 + } 130 + 131 + /** 132 + * audit_policy() - Audit a policy's name, version and thumbprint to @ab. 133 + * @ab: Supplies a pointer to the audit buffer to append to. 134 + * @audit_format: Supplies a pointer to the audit format string 135 + * @p: Supplies a pointer to the policy to audit. 136 + */ 137 + static void audit_policy(struct audit_buffer *ab, 138 + const char *audit_format, 139 + const struct ipe_policy *const p) 140 + { 141 + SHASH_DESC_ON_STACK(desc, tfm); 142 + struct crypto_shash *tfm; 143 + u8 *digest = NULL; 144 + 145 + tfm = crypto_alloc_shash(IPE_AUDIT_HASH_ALG, 0, 0); 146 + if (IS_ERR(tfm)) 147 + return; 148 + 149 + desc->tfm = tfm; 150 + 151 + digest = kzalloc(crypto_shash_digestsize(tfm), GFP_KERNEL); 152 + if (!digest) 153 + goto out; 154 + 155 + if (crypto_shash_init(desc)) 156 + goto out; 157 + 158 + if (crypto_shash_update(desc, p->pkcs7, p->pkcs7len)) 159 + goto out; 160 + 161 + if (crypto_shash_final(desc, digest)) 162 + goto out; 163 + 164 + audit_log_format(ab, audit_format, p->parsed->name, 165 + p->parsed->version.major, p->parsed->version.minor, 166 + p->parsed->version.rev); 167 + audit_log_n_hex(ab, digest, crypto_shash_digestsize(tfm)); 168 + 169 + out: 170 + kfree(digest); 171 + crypto_free_shash(tfm); 172 + } 173 + 174 + /** 175 + * ipe_audit_policy_activation() - Audit a policy being activated. 176 + * @op: Supplies a pointer to the previously activated policy to audit. 177 + * @np: Supplies a pointer to the newly activated policy to audit. 178 + */ 179 + void ipe_audit_policy_activation(const struct ipe_policy *const op, 180 + const struct ipe_policy *const np) 181 + { 182 + struct audit_buffer *ab; 183 + 184 + ab = audit_log_start(audit_context(), GFP_KERNEL, 185 + AUDIT_IPE_CONFIG_CHANGE); 186 + if (!ab) 187 + return; 188 + 189 + if (op) { 190 + audit_policy(ab, AUDIT_OLD_ACTIVE_POLICY_FMT, op); 191 + audit_log_format(ab, " "); 192 + } else { 193 + /* 194 + * old active policy can be NULL if there is no kernel 195 + * built-in policy 196 + */ 197 + audit_log_format(ab, AUDIT_OLD_ACTIVE_POLICY_NULL_FMT); 198 + audit_log_format(ab, " "); 199 + } 200 + audit_policy(ab, AUDIT_NEW_ACTIVE_POLICY_FMT, np); 201 + audit_log_format(ab, " auid=%u ses=%u lsm=ipe res=1", 202 + from_kuid(&init_user_ns, audit_get_loginuid(current)), 203 + audit_get_sessionid(current)); 204 + 205 + audit_log_end(ab); 206 + } 207 + 208 + /** 209 + * ipe_audit_policy_load() - Audit a policy being loaded into the kernel. 210 + * @p: Supplies a pointer to the policy to audit. 211 + */ 212 + void ipe_audit_policy_load(const struct ipe_policy *const p) 213 + { 214 + struct audit_buffer *ab; 215 + 216 + ab = audit_log_start(audit_context(), GFP_KERNEL, 217 + AUDIT_IPE_POLICY_LOAD); 218 + if (!ab) 219 + return; 220 + 221 + audit_policy(ab, AUDIT_POLICY_LOAD_FMT, p); 222 + audit_log_format(ab, " auid=%u ses=%u lsm=ipe res=1", 223 + from_kuid(&init_user_ns, audit_get_loginuid(current)), 224 + audit_get_sessionid(current)); 225 + 226 + audit_log_end(ab); 227 + }
+18
security/ipe/audit.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved. 4 + */ 5 + 6 + #ifndef _IPE_AUDIT_H 7 + #define _IPE_AUDIT_H 8 + 9 + #include "policy.h" 10 + 11 + void ipe_audit_match(const struct ipe_eval_ctx *const ctx, 12 + enum ipe_match match_type, 13 + enum ipe_action_type act, const struct ipe_rule *const r); 14 + void ipe_audit_policy_load(const struct ipe_policy *const p); 15 + void ipe_audit_policy_activation(const struct ipe_policy *const op, 16 + const struct ipe_policy *const np); 17 + 18 + #endif /* _IPE_AUDIT_H */
+34 -11
security/ipe/eval.c
··· 9 9 #include <linux/file.h> 10 10 #include <linux/sched.h> 11 11 #include <linux/rcupdate.h> 12 + #include <linux/moduleparam.h> 12 13 13 14 #include "ipe.h" 14 15 #include "eval.h" 15 16 #include "policy.h" 17 + #include "audit.h" 16 18 17 19 struct ipe_policy __rcu *ipe_active_policy; 20 + bool success_audit; 18 21 19 22 #define FILE_SUPERBLOCK(f) ((f)->f_path.mnt->mnt_sb) 20 23 ··· 36 33 * @ctx: Supplies a pointer to the context to be populated. 37 34 * @file: Supplies a pointer to the file to associated with the evaluation. 38 35 * @op: Supplies the IPE policy operation associated with the evaluation. 36 + * @hook: Supplies the LSM hook associated with the evaluation. 39 37 */ 40 38 void ipe_build_eval_ctx(struct ipe_eval_ctx *ctx, 41 39 const struct file *file, 42 - enum ipe_op_type op) 40 + enum ipe_op_type op, 41 + enum ipe_hook_type hook) 43 42 { 44 43 ctx->file = file; 45 44 ctx->op = op; 45 + ctx->hook = hook; 46 46 47 47 if (file) 48 48 build_ipe_sb_ctx(ctx, file); ··· 106 100 struct ipe_policy *pol = NULL; 107 101 struct ipe_prop *prop = NULL; 108 102 enum ipe_action_type action; 103 + enum ipe_match match_type; 109 104 bool match = false; 110 105 111 106 rcu_read_lock(); ··· 118 111 } 119 112 120 113 if (ctx->op == IPE_OP_INVALID) { 121 - if (pol->parsed->global_default_action == IPE_ACTION_DENY) { 122 - rcu_read_unlock(); 123 - return -EACCES; 124 - } 125 - if (pol->parsed->global_default_action == IPE_ACTION_INVALID) 114 + if (pol->parsed->global_default_action == IPE_ACTION_INVALID) { 126 115 WARN(1, "no default rule set for unknown op, ALLOW it"); 127 - rcu_read_unlock(); 128 - return 0; 116 + action = IPE_ACTION_ALLOW; 117 + } else { 118 + action = pol->parsed->global_default_action; 119 + } 120 + match_type = IPE_MATCH_GLOBAL; 121 + goto eval; 129 122 } 130 123 131 124 rules = &pol->parsed->rules[ctx->op]; ··· 143 136 break; 144 137 } 145 138 146 - if (match) 139 + if (match) { 147 140 action = rule->action; 148 - else if (rules->default_action != IPE_ACTION_INVALID) 141 + match_type = IPE_MATCH_RULE; 142 + } else if (rules->default_action != IPE_ACTION_INVALID) { 149 143 action = rules->default_action; 150 - else 144 + match_type = IPE_MATCH_TABLE; 145 + } else { 151 146 action = pol->parsed->global_default_action; 147 + match_type = IPE_MATCH_GLOBAL; 148 + } 152 149 150 + eval: 151 + ipe_audit_match(ctx, match_type, action, rule); 153 152 rcu_read_unlock(); 153 + 154 154 if (action == IPE_ACTION_DENY) 155 155 return -EACCES; 156 156 157 157 return 0; 158 158 } 159 + 160 + /* Set the right module name */ 161 + #ifdef KBUILD_MODNAME 162 + #undef KBUILD_MODNAME 163 + #define KBUILD_MODNAME "ipe" 164 + #endif 165 + 166 + module_param(success_audit, bool, 0400); 167 + MODULE_PARM_DESC(success_audit, "Start IPE with success auditing enabled");
+12 -1
security/ipe/eval.h
··· 10 10 #include <linux/types.h> 11 11 12 12 #include "policy.h" 13 + #include "hooks.h" 13 14 14 15 #define IPE_EVAL_CTX_INIT ((struct ipe_eval_ctx){ 0 }) 15 16 16 17 extern struct ipe_policy __rcu *ipe_active_policy; 18 + extern bool success_audit; 17 19 18 20 struct ipe_superblock { 19 21 bool initramfs; ··· 23 21 24 22 struct ipe_eval_ctx { 25 23 enum ipe_op_type op; 24 + enum ipe_hook_type hook; 26 25 27 26 const struct file *file; 28 27 bool initramfs; 29 28 }; 30 29 30 + enum ipe_match { 31 + IPE_MATCH_RULE = 0, 32 + IPE_MATCH_TABLE, 33 + IPE_MATCH_GLOBAL, 34 + __IPE_MATCH_MAX 35 + }; 36 + 31 37 void ipe_build_eval_ctx(struct ipe_eval_ctx *ctx, 32 38 const struct file *file, 33 - enum ipe_op_type op); 39 + enum ipe_op_type op, 40 + enum ipe_hook_type hook); 34 41 int ipe_evaluate_event(const struct ipe_eval_ctx *const ctx); 35 42 36 43 #endif /* _IPE_EVAL_H */
+68
security/ipe/fs.c
··· 8 8 9 9 #include "ipe.h" 10 10 #include "fs.h" 11 + #include "eval.h" 11 12 #include "policy.h" 13 + #include "audit.h" 12 14 13 15 static struct dentry *np __ro_after_init; 14 16 static struct dentry *root __ro_after_init; 15 17 struct dentry *policy_root __ro_after_init; 18 + static struct dentry *audit_node __ro_after_init; 19 + 20 + /** 21 + * setaudit() - Write handler for the securityfs node, "ipe/success_audit" 22 + * @f: Supplies a file structure representing the securityfs node. 23 + * @data: Supplies a buffer passed to the write syscall. 24 + * @len: Supplies the length of @data. 25 + * @offset: unused. 26 + * 27 + * Return: 28 + * * Length of buffer written - Success 29 + * * %-EPERM - Insufficient permission 30 + */ 31 + static ssize_t setaudit(struct file *f, const char __user *data, 32 + size_t len, loff_t *offset) 33 + { 34 + int rc = 0; 35 + bool value; 36 + 37 + if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN)) 38 + return -EPERM; 39 + 40 + rc = kstrtobool_from_user(data, len, &value); 41 + if (rc) 42 + return rc; 43 + 44 + WRITE_ONCE(success_audit, value); 45 + 46 + return len; 47 + } 48 + 49 + /** 50 + * getaudit() - Read handler for the securityfs node, "ipe/success_audit" 51 + * @f: Supplies a file structure representing the securityfs node. 52 + * @data: Supplies a buffer passed to the read syscall. 53 + * @len: Supplies the length of @data. 54 + * @offset: unused. 55 + * 56 + * Return: Length of buffer written 57 + */ 58 + static ssize_t getaudit(struct file *f, char __user *data, 59 + size_t len, loff_t *offset) 60 + { 61 + const char *result; 62 + 63 + result = ((READ_ONCE(success_audit)) ? "1" : "0"); 64 + 65 + return simple_read_from_buffer(data, len, offset, result, 1); 66 + } 16 67 17 68 /** 18 69 * new_policy() - Write handler for the securityfs node, "ipe/new_policy". ··· 102 51 } 103 52 104 53 rc = ipe_new_policyfs_node(p); 54 + if (rc) 55 + goto out; 56 + 57 + ipe_audit_policy_load(p); 105 58 106 59 out: 107 60 if (rc < 0) ··· 116 61 117 62 static const struct file_operations np_fops = { 118 63 .write = new_policy, 64 + }; 65 + 66 + static const struct file_operations audit_fops = { 67 + .write = setaudit, 68 + .read = getaudit, 119 69 }; 120 70 121 71 /** ··· 142 82 goto err; 143 83 } 144 84 85 + audit_node = securityfs_create_file("success_audit", 0600, root, 86 + NULL, &audit_fops); 87 + if (IS_ERR(audit_node)) { 88 + rc = PTR_ERR(audit_node); 89 + goto err; 90 + } 91 + 145 92 policy_root = securityfs_create_dir("policies", root); 146 93 if (IS_ERR(policy_root)) { 147 94 rc = PTR_ERR(policy_root); ··· 165 98 err: 166 99 securityfs_remove(np); 167 100 securityfs_remove(policy_root); 101 + securityfs_remove(audit_node); 168 102 securityfs_remove(root); 169 103 return rc; 170 104 }
+5 -5
security/ipe/hooks.c
··· 29 29 { 30 30 struct ipe_eval_ctx ctx = IPE_EVAL_CTX_INIT; 31 31 32 - ipe_build_eval_ctx(&ctx, bprm->file, IPE_OP_EXEC); 32 + ipe_build_eval_ctx(&ctx, bprm->file, IPE_OP_EXEC, IPE_HOOK_BPRM_CHECK); 33 33 return ipe_evaluate_event(&ctx); 34 34 } 35 35 ··· 54 54 struct ipe_eval_ctx ctx = IPE_EVAL_CTX_INIT; 55 55 56 56 if (prot & PROT_EXEC) { 57 - ipe_build_eval_ctx(&ctx, f, IPE_OP_EXEC); 57 + ipe_build_eval_ctx(&ctx, f, IPE_OP_EXEC, IPE_HOOK_MMAP); 58 58 return ipe_evaluate_event(&ctx); 59 59 } 60 60 ··· 86 86 return 0; 87 87 88 88 if (prot & PROT_EXEC) { 89 - ipe_build_eval_ctx(&ctx, vma->vm_file, IPE_OP_EXEC); 89 + ipe_build_eval_ctx(&ctx, vma->vm_file, IPE_OP_EXEC, IPE_HOOK_MPROTECT); 90 90 return ipe_evaluate_event(&ctx); 91 91 } 92 92 ··· 135 135 WARN(1, "no rule setup for kernel_read_file enum %d", id); 136 136 } 137 137 138 - ipe_build_eval_ctx(&ctx, file, op); 138 + ipe_build_eval_ctx(&ctx, file, op, IPE_HOOK_KERNEL_READ); 139 139 return ipe_evaluate_event(&ctx); 140 140 } 141 141 ··· 180 180 WARN(1, "no rule setup for kernel_load_data enum %d", id); 181 181 } 182 182 183 - ipe_build_eval_ctx(&ctx, NULL, op); 183 + ipe_build_eval_ctx(&ctx, NULL, op, IPE_HOOK_KERNEL_LOAD); 184 184 return ipe_evaluate_event(&ctx); 185 185 } 186 186
+11
security/ipe/hooks.h
··· 9 9 #include <linux/binfmts.h> 10 10 #include <linux/security.h> 11 11 12 + enum ipe_hook_type { 13 + IPE_HOOK_BPRM_CHECK = 0, 14 + IPE_HOOK_MMAP, 15 + IPE_HOOK_MPROTECT, 16 + IPE_HOOK_KERNEL_READ, 17 + IPE_HOOK_KERNEL_LOAD, 18 + __IPE_HOOK_MAX 19 + }; 20 + 21 + #define IPE_HOOK_INVALID __IPE_HOOK_MAX 22 + 12 23 int ipe_bprm_check_security(struct linux_binprm *bprm); 13 24 14 25 int ipe_mmap_file(struct file *f, unsigned long reqprot, unsigned long prot,
+4
security/ipe/policy.c
··· 11 11 #include "fs.h" 12 12 #include "policy.h" 13 13 #include "policy_parser.h" 14 + #include "audit.h" 14 15 15 16 /* lock for synchronizing writers across ipe policy */ 16 17 DEFINE_MUTEX(ipe_policy_lock); ··· 113 112 114 113 root->i_private = new; 115 114 swap(new->policyfs, old->policyfs); 115 + ipe_audit_policy_load(new); 116 116 117 117 mutex_lock(&ipe_policy_lock); 118 118 ap = rcu_dereference_protected(ipe_active_policy, ··· 121 119 if (old == ap) { 122 120 rcu_assign_pointer(ipe_active_policy, new); 123 121 mutex_unlock(&ipe_policy_lock); 122 + ipe_audit_policy_activation(old, new); 124 123 } else { 125 124 mutex_unlock(&ipe_policy_lock); 126 125 } ··· 220 217 } 221 218 222 219 rcu_assign_pointer(ipe_active_policy, p); 220 + ipe_audit_policy_activation(ap, p); 223 221 mutex_unlock(&ipe_policy_lock); 224 222 225 223 return 0;