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

ipe: add permissive toggle

IPE, like SELinux, supports a permissive mode. This mode allows policy
authors to test and evaluate IPE policy without it affecting their
programs. When the mode is changed, a 1404 AUDIT_MAC_STATUS will
be reported.

This patch adds the following audit records:

audit: MAC_STATUS enforcing=0 old_enforcing=1 auid=4294967295
ses=4294967295 enabled=1 old-enabled=1 lsm=ipe res=1
audit: MAC_STATUS enforcing=1 old_enforcing=0 auid=4294967295
ses=4294967295 enabled=1 old-enabled=1 lsm=ipe res=1

The audit record only emit when the value from the user input is
different from the current enforce value.

Signed-off-by: Deven Bowers <deven.desai@linux.microsoft.com>
Signed-off-by: Fan Wu <wufan@linux.microsoft.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>

authored by

Deven Bowers and committed by
Paul Moore
a68916ea f44554b5

+102 -4
+25 -2
security/ipe/audit.c
··· 97 97 if (!ab) 98 98 return; 99 99 100 - audit_log_format(ab, "ipe_op=%s ipe_hook=%s pid=%d comm=", 101 - op, audit_hook_names[ctx->hook], 100 + audit_log_format(ab, "ipe_op=%s ipe_hook=%s enforcing=%d pid=%d comm=", 101 + op, audit_hook_names[ctx->hook], READ_ONCE(enforce), 102 102 task_tgid_nr(current)); 103 103 audit_log_untrustedstring(ab, get_task_comm(comm, current)); 104 104 ··· 222 222 audit_log_format(ab, " auid=%u ses=%u lsm=ipe res=1", 223 223 from_kuid(&init_user_ns, audit_get_loginuid(current)), 224 224 audit_get_sessionid(current)); 225 + 226 + audit_log_end(ab); 227 + } 228 + 229 + /** 230 + * ipe_audit_enforce() - Audit a change in IPE's enforcement state. 231 + * @new_enforce: The new value enforce to be set. 232 + * @old_enforce: The old value currently in enforce. 233 + */ 234 + void ipe_audit_enforce(bool new_enforce, bool old_enforce) 235 + { 236 + struct audit_buffer *ab; 237 + 238 + ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_MAC_STATUS); 239 + if (!ab) 240 + return; 241 + 242 + audit_log(audit_context(), GFP_KERNEL, AUDIT_MAC_STATUS, 243 + "enforcing=%d old_enforcing=%d auid=%u ses=%u" 244 + " enabled=1 old-enabled=1 lsm=ipe res=1", 245 + new_enforce, old_enforce, 246 + from_kuid(&init_user_ns, audit_get_loginuid(current)), 247 + audit_get_sessionid(current)); 225 248 226 249 audit_log_end(ab); 227 250 }
+1
security/ipe/audit.h
··· 14 14 void ipe_audit_policy_load(const struct ipe_policy *const p); 15 15 void ipe_audit_policy_activation(const struct ipe_policy *const op, 16 16 const struct ipe_policy *const np); 17 + void ipe_audit_enforce(bool new_enforce, bool old_enforce); 17 18 18 19 #endif /* _IPE_AUDIT_H */
+9 -2
security/ipe/eval.c
··· 18 18 19 19 struct ipe_policy __rcu *ipe_active_policy; 20 20 bool success_audit; 21 + bool enforce = true; 21 22 22 23 #define FILE_SUPERBLOCK(f) ((f)->f_path.mnt->mnt_sb) 23 24 ··· 109 108 enum ipe_action_type action; 110 109 enum ipe_match match_type; 111 110 bool match = false; 111 + int rc = 0; 112 112 113 113 rcu_read_lock(); 114 114 ··· 161 159 rcu_read_unlock(); 162 160 163 161 if (action == IPE_ACTION_DENY) 164 - return -EACCES; 162 + rc = -EACCES; 165 163 166 - return 0; 164 + if (!READ_ONCE(enforce)) 165 + rc = 0; 166 + 167 + return rc; 167 168 } 168 169 169 170 /* Set the right module name */ ··· 177 172 178 173 module_param(success_audit, bool, 0400); 179 174 MODULE_PARM_DESC(success_audit, "Start IPE with success auditing enabled"); 175 + module_param(enforce, bool, 0400); 176 + MODULE_PARM_DESC(enforce, "Start IPE in enforce or permissive mode");
+1
security/ipe/eval.h
··· 16 16 17 17 extern struct ipe_policy __rcu *ipe_active_policy; 18 18 extern bool success_audit; 19 + extern bool enforce; 19 20 20 21 struct ipe_superblock { 21 22 bool initramfs;
+66
security/ipe/fs.c
··· 16 16 static struct dentry *root __ro_after_init; 17 17 struct dentry *policy_root __ro_after_init; 18 18 static struct dentry *audit_node __ro_after_init; 19 + static struct dentry *enforce_node __ro_after_init; 19 20 20 21 /** 21 22 * setaudit() - Write handler for the securityfs node, "ipe/success_audit" ··· 62 61 const char *result; 63 62 64 63 result = ((READ_ONCE(success_audit)) ? "1" : "0"); 64 + 65 + return simple_read_from_buffer(data, len, offset, result, 1); 66 + } 67 + 68 + /** 69 + * setenforce() - Write handler for the securityfs node, "ipe/enforce" 70 + * @f: Supplies a file structure representing the securityfs node. 71 + * @data: Supplies a buffer passed to the write syscall. 72 + * @len: Supplies the length of @data. 73 + * @offset: unused. 74 + * 75 + * Return: 76 + * * Length of buffer written - Success 77 + * * %-EPERM - Insufficient permission 78 + */ 79 + static ssize_t setenforce(struct file *f, const char __user *data, 80 + size_t len, loff_t *offset) 81 + { 82 + int rc = 0; 83 + bool new_value, old_value; 84 + 85 + if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN)) 86 + return -EPERM; 87 + 88 + old_value = READ_ONCE(enforce); 89 + rc = kstrtobool_from_user(data, len, &new_value); 90 + if (rc) 91 + return rc; 92 + 93 + if (new_value != old_value) { 94 + ipe_audit_enforce(new_value, old_value); 95 + WRITE_ONCE(enforce, new_value); 96 + } 97 + 98 + return len; 99 + } 100 + 101 + /** 102 + * getenforce() - Read handler for the securityfs node, "ipe/enforce" 103 + * @f: Supplies a file structure representing the securityfs node. 104 + * @data: Supplies a buffer passed to the read syscall. 105 + * @len: Supplies the length of @data. 106 + * @offset: unused. 107 + * 108 + * Return: Length of buffer written 109 + */ 110 + static ssize_t getenforce(struct file *f, char __user *data, 111 + size_t len, loff_t *offset) 112 + { 113 + const char *result; 114 + 115 + result = ((READ_ONCE(enforce)) ? "1" : "0"); 65 116 66 117 return simple_read_from_buffer(data, len, offset, result, 1); 67 118 } ··· 176 123 .read = getaudit, 177 124 }; 178 125 126 + static const struct file_operations enforce_fops = { 127 + .write = setenforce, 128 + .read = getenforce, 129 + }; 130 + 179 131 /** 180 132 * ipe_init_securityfs() - Initialize IPE's securityfs tree at fsinit. 181 133 * ··· 207 149 goto err; 208 150 } 209 151 152 + enforce_node = securityfs_create_file("enforce", 0600, root, NULL, 153 + &enforce_fops); 154 + if (IS_ERR(enforce_node)) { 155 + rc = PTR_ERR(enforce_node); 156 + goto err; 157 + } 158 + 210 159 policy_root = securityfs_create_dir("policies", root); 211 160 if (IS_ERR(policy_root)) { 212 161 rc = PTR_ERR(policy_root); ··· 230 165 err: 231 166 securityfs_remove(np); 232 167 securityfs_remove(policy_root); 168 + securityfs_remove(enforce_node); 233 169 securityfs_remove(audit_node); 234 170 securityfs_remove(root); 235 171 return rc;