1 /* 2 * Copyright (C) 2008 IBM Corporation 3 * Author: Mimi Zohar <zohar@us.ibm.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, version 2 of the License. 8 * 9 * ima_policy.c 10 * - initialize default measure policy rules 11 * 12 */ 13 #include <linux/module.h> 14 #include <linux/list.h> 15 #include <linux/security.h> 16 #include <linux/magic.h> 17 #include <linux/parser.h> 18 19 #include "ima.h" 20 21 /* flags definitions */ 22 #define IMA_FUNC 0x0001 23 #define IMA_MASK 0x0002 24 #define IMA_FSMAGIC 0x0004 25 #define IMA_UID 0x0008 26 27 enum ima_action { UNKNOWN = -1, DONT_MEASURE = 0, MEASURE }; 28 29 #define MAX_LSM_RULES 6 30 enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE, 31 LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE 32 }; 33 34 struct ima_measure_rule_entry { 35 struct list_head list; 36 enum ima_action action; 37 unsigned int flags; 38 enum ima_hooks func; 39 int mask; 40 unsigned long fsmagic; 41 uid_t uid; 42 struct { 43 void *rule; /* LSM file metadata specific */ 44 int type; /* audit type */ 45 } lsm[MAX_LSM_RULES]; 46 }; 47 48 /* Without LSM specific knowledge, the default policy can only be 49 * written in terms of .action, .func, .mask, .fsmagic, and .uid 50 */ 51 static struct ima_measure_rule_entry default_rules[] = { 52 {.action = DONT_MEASURE,.fsmagic = PROC_SUPER_MAGIC, 53 .flags = IMA_FSMAGIC}, 54 {.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC}, 55 {.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC}, 56 {.action = DONT_MEASURE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC}, 57 {.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC, 58 .flags = IMA_FSMAGIC}, 59 {.action = DONT_MEASURE,.fsmagic = 0xF97CFF8C,.flags = IMA_FSMAGIC}, 60 {.action = MEASURE,.func = FILE_MMAP,.mask = MAY_EXEC, 61 .flags = IMA_FUNC | IMA_MASK}, 62 {.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC, 63 .flags = IMA_FUNC | IMA_MASK}, 64 {.action = MEASURE,.func = PATH_CHECK,.mask = MAY_READ,.uid = 0, 65 .flags = IMA_FUNC | IMA_MASK | IMA_UID} 66 }; 67 68 static LIST_HEAD(measure_default_rules); 69 static LIST_HEAD(measure_policy_rules); 70 static struct list_head *ima_measure; 71 72 static DEFINE_MUTEX(ima_measure_mutex); 73 74 /** 75 * ima_match_rules - determine whether an inode matches the measure rule. 76 * @rule: a pointer to a rule 77 * @inode: a pointer to an inode 78 * @func: LIM hook identifier 79 * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC) 80 * 81 * Returns true on rule match, false on failure. 82 */ 83 static bool ima_match_rules(struct ima_measure_rule_entry *rule, 84 struct inode *inode, enum ima_hooks func, int mask) 85 { 86 struct task_struct *tsk = current; 87 int i; 88 89 if ((rule->flags & IMA_FUNC) && rule->func != func) 90 return false; 91 if ((rule->flags & IMA_MASK) && rule->mask != mask) 92 return false; 93 if ((rule->flags & IMA_FSMAGIC) 94 && rule->fsmagic != inode->i_sb->s_magic) 95 return false; 96 if ((rule->flags & IMA_UID) && rule->uid != tsk->cred->uid) 97 return false; 98 for (i = 0; i < MAX_LSM_RULES; i++) { 99 int rc; 100 u32 osid, sid; 101 102 if (!rule->lsm[i].rule) 103 continue; 104 105 switch (i) { 106 case LSM_OBJ_USER: 107 case LSM_OBJ_ROLE: 108 case LSM_OBJ_TYPE: 109 security_inode_getsecid(inode, &osid); 110 rc = security_filter_rule_match(osid, 111 rule->lsm[i].type, 112 AUDIT_EQUAL, 113 rule->lsm[i].rule, 114 NULL); 115 break; 116 case LSM_SUBJ_USER: 117 case LSM_SUBJ_ROLE: 118 case LSM_SUBJ_TYPE: 119 security_task_getsecid(tsk, &sid); 120 rc = security_filter_rule_match(sid, 121 rule->lsm[i].type, 122 AUDIT_EQUAL, 123 rule->lsm[i].rule, 124 NULL); 125 default: 126 break; 127 } 128 if (!rc) 129 return false; 130 } 131 return true; 132 } 133 134 /** 135 * ima_match_policy - decision based on LSM and other conditions 136 * @inode: pointer to an inode for which the policy decision is being made 137 * @func: IMA hook identifier 138 * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC) 139 * 140 * Measure decision based on func/mask/fsmagic and LSM(subj/obj/type) 141 * conditions. 142 * 143 * (There is no need for locking when walking the policy list, 144 * as elements in the list are never deleted, nor does the list 145 * change.) 146 */ 147 int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask) 148 { 149 struct ima_measure_rule_entry *entry; 150 151 list_for_each_entry(entry, ima_measure, list) { 152 bool rc; 153 154 rc = ima_match_rules(entry, inode, func, mask); 155 if (rc) 156 return entry->action; 157 } 158 return 0; 159 } 160 161 /** 162 * ima_init_policy - initialize the default measure rules. 163 * 164 * ima_measure points to either the measure_default_rules or the 165 * the new measure_policy_rules. 166 */ 167 void ima_init_policy(void) 168 { 169 int i; 170 171 for (i = 0; i < ARRAY_SIZE(default_rules); i++) 172 list_add_tail(&default_rules[i].list, &measure_default_rules); 173 ima_measure = &measure_default_rules; 174 } 175 176 /** 177 * ima_update_policy - update default_rules with new measure rules 178 * 179 * Called on file .release to update the default rules with a complete new 180 * policy. Once updated, the policy is locked, no additional rules can be 181 * added to the policy. 182 */ 183 void ima_update_policy(void) 184 { 185 const char *op = "policy_update"; 186 const char *cause = "already exists"; 187 int result = 1; 188 int audit_info = 0; 189 190 if (ima_measure == &measure_default_rules) { 191 ima_measure = &measure_policy_rules; 192 cause = "complete"; 193 result = 0; 194 } 195 integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, 196 NULL, op, cause, result, audit_info); 197 } 198 199 enum { 200 Opt_err = -1, 201 Opt_measure = 1, Opt_dont_measure, 202 Opt_obj_user, Opt_obj_role, Opt_obj_type, 203 Opt_subj_user, Opt_subj_role, Opt_subj_type, 204 Opt_func, Opt_mask, Opt_fsmagic, Opt_uid 205 }; 206 207 static match_table_t policy_tokens = { 208 {Opt_measure, "measure"}, 209 {Opt_dont_measure, "dont_measure"}, 210 {Opt_obj_user, "obj_user=%s"}, 211 {Opt_obj_role, "obj_role=%s"}, 212 {Opt_obj_type, "obj_type=%s"}, 213 {Opt_subj_user, "subj_user=%s"}, 214 {Opt_subj_role, "subj_role=%s"}, 215 {Opt_subj_type, "subj_type=%s"}, 216 {Opt_func, "func=%s"}, 217 {Opt_mask, "mask=%s"}, 218 {Opt_fsmagic, "fsmagic=%s"}, 219 {Opt_uid, "uid=%s"}, 220 {Opt_err, NULL} 221 }; 222 223 static int ima_lsm_rule_init(struct ima_measure_rule_entry *entry, 224 char *args, int lsm_rule, int audit_type) 225 { 226 int result; 227 228 entry->lsm[lsm_rule].type = audit_type; 229 result = security_filter_rule_init(entry->lsm[lsm_rule].type, 230 AUDIT_EQUAL, args, 231 &entry->lsm[lsm_rule].rule); 232 return result; 233 } 234 235 static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) 236 { 237 struct audit_buffer *ab; 238 char *p; 239 int result = 0; 240 241 ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE); 242 243 entry->action = -1; 244 while ((p = strsep(&rule, " \n")) != NULL) { 245 substring_t args[MAX_OPT_ARGS]; 246 int token; 247 unsigned long lnum; 248 249 if (result < 0) 250 break; 251 if (!*p) 252 continue; 253 token = match_token(p, policy_tokens, args); 254 switch (token) { 255 case Opt_measure: 256 audit_log_format(ab, "%s ", "measure"); 257 entry->action = MEASURE; 258 break; 259 case Opt_dont_measure: 260 audit_log_format(ab, "%s ", "dont_measure"); 261 entry->action = DONT_MEASURE; 262 break; 263 case Opt_func: 264 audit_log_format(ab, "func=%s ", args[0].from); 265 if (strcmp(args[0].from, "PATH_CHECK") == 0) 266 entry->func = PATH_CHECK; 267 else if (strcmp(args[0].from, "FILE_MMAP") == 0) 268 entry->func = FILE_MMAP; 269 else if (strcmp(args[0].from, "BPRM_CHECK") == 0) 270 entry->func = BPRM_CHECK; 271 else 272 result = -EINVAL; 273 if (!result) 274 entry->flags |= IMA_FUNC; 275 break; 276 case Opt_mask: 277 audit_log_format(ab, "mask=%s ", args[0].from); 278 if ((strcmp(args[0].from, "MAY_EXEC")) == 0) 279 entry->mask = MAY_EXEC; 280 else if (strcmp(args[0].from, "MAY_WRITE") == 0) 281 entry->mask = MAY_WRITE; 282 else if (strcmp(args[0].from, "MAY_READ") == 0) 283 entry->mask = MAY_READ; 284 else if (strcmp(args[0].from, "MAY_APPEND") == 0) 285 entry->mask = MAY_APPEND; 286 else 287 result = -EINVAL; 288 if (!result) 289 entry->flags |= IMA_MASK; 290 break; 291 case Opt_fsmagic: 292 audit_log_format(ab, "fsmagic=%s ", args[0].from); 293 result = strict_strtoul(args[0].from, 16, 294 &entry->fsmagic); 295 if (!result) 296 entry->flags |= IMA_FSMAGIC; 297 break; 298 case Opt_uid: 299 audit_log_format(ab, "uid=%s ", args[0].from); 300 result = strict_strtoul(args[0].from, 10, &lnum); 301 if (!result) { 302 entry->uid = (uid_t) lnum; 303 if (entry->uid != lnum) 304 result = -EINVAL; 305 else 306 entry->flags |= IMA_UID; 307 } 308 break; 309 case Opt_obj_user: 310 audit_log_format(ab, "obj_user=%s ", args[0].from); 311 result = ima_lsm_rule_init(entry, args[0].from, 312 LSM_OBJ_USER, 313 AUDIT_OBJ_USER); 314 break; 315 case Opt_obj_role: 316 audit_log_format(ab, "obj_role=%s ", args[0].from); 317 result = ima_lsm_rule_init(entry, args[0].from, 318 LSM_OBJ_ROLE, 319 AUDIT_OBJ_ROLE); 320 break; 321 case Opt_obj_type: 322 audit_log_format(ab, "obj_type=%s ", args[0].from); 323 result = ima_lsm_rule_init(entry, args[0].from, 324 LSM_OBJ_TYPE, 325 AUDIT_OBJ_TYPE); 326 break; 327 case Opt_subj_user: 328 audit_log_format(ab, "subj_user=%s ", args[0].from); 329 result = ima_lsm_rule_init(entry, args[0].from, 330 LSM_SUBJ_USER, 331 AUDIT_SUBJ_USER); 332 break; 333 case Opt_subj_role: 334 audit_log_format(ab, "subj_role=%s ", args[0].from); 335 result = ima_lsm_rule_init(entry, args[0].from, 336 LSM_SUBJ_ROLE, 337 AUDIT_SUBJ_ROLE); 338 break; 339 case Opt_subj_type: 340 audit_log_format(ab, "subj_type=%s ", args[0].from); 341 result = ima_lsm_rule_init(entry, args[0].from, 342 LSM_SUBJ_TYPE, 343 AUDIT_SUBJ_TYPE); 344 break; 345 case Opt_err: 346 audit_log_format(ab, "UNKNOWN=%s ", p); 347 break; 348 } 349 } 350 if (entry->action == UNKNOWN) 351 result = -EINVAL; 352 353 audit_log_format(ab, "res=%d", !result ? 0 : 1); 354 audit_log_end(ab); 355 return result; 356 } 357 358 /** 359 * ima_parse_add_rule - add a rule to measure_policy_rules 360 * @rule - ima measurement policy rule 361 * 362 * Uses a mutex to protect the policy list from multiple concurrent writers. 363 * Returns 0 on success, an error code on failure. 364 */ 365 int ima_parse_add_rule(char *rule) 366 { 367 const char *op = "update_policy"; 368 struct ima_measure_rule_entry *entry; 369 int result = 0; 370 int audit_info = 0; 371 372 /* Prevent installed policy from changing */ 373 if (ima_measure != &measure_default_rules) { 374 integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, 375 NULL, op, "already exists", 376 -EACCES, audit_info); 377 return -EACCES; 378 } 379 380 entry = kzalloc(sizeof(*entry), GFP_KERNEL); 381 if (!entry) { 382 integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, 383 NULL, op, "-ENOMEM", -ENOMEM, audit_info); 384 return -ENOMEM; 385 } 386 387 INIT_LIST_HEAD(&entry->list); 388 389 result = ima_parse_rule(rule, entry); 390 if (!result) { 391 mutex_lock(&ima_measure_mutex); 392 list_add_tail(&entry->list, &measure_policy_rules); 393 mutex_unlock(&ima_measure_mutex); 394 } else { 395 kfree(entry); 396 integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, 397 NULL, op, "invalid policy", result, 398 audit_info); 399 } 400 return result; 401 } 402 403 /* ima_delete_rules called to cleanup invalid policy */ 404 void ima_delete_rules(void) 405 { 406 struct ima_measure_rule_entry *entry, *tmp; 407 408 mutex_lock(&ima_measure_mutex); 409 list_for_each_entry_safe(entry, tmp, &measure_policy_rules, list) { 410 list_del(&entry->list); 411 kfree(entry); 412 } 413 mutex_unlock(&ima_measure_mutex); 414 } 415