aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorMimi Zohar <zohar@linux.vnet.ibm.com>2011-03-09 22:25:48 -0500
committerMimi Zohar <zohar@linux.vnet.ibm.com>2012-09-07 14:57:45 -0400
commit07f6a79415d7d502ee0c7d02ace6594a7be7429a (patch)
treeaf2a9b3bb84ab621cbf11ab609dd8cc3566f2b12 /security
parent2fe5d6def1672ae6635dd71867bf36dcfaa7434b (diff)
ima: add appraise action keywords and default rules
Unlike the IMA measurement policy, the appraise policy can not be dependent on runtime process information, such as the task uid, as the 'security.ima' xattr is written on file close and must be updated each time the file changes, regardless of the current task uid. This patch extends the policy language with 'fowner', defines an appraise policy, which appraises all files owned by root, and defines 'ima_appraise_tcb', a new boot command line option, to enable the appraise policy. Changelog v3: - separate the measure from the appraise rules in order to support measuring without appraising and appraising without measuring. - change appraisal default for filesystems without xattr support to fail - update default appraise policy for cgroups Changelog v1: - don't appraise RAMFS (Dmitry Kasatkin) - merged rest of "ima: ima_must_appraise_or_measure API change" commit (Dmtiry Kasatkin) ima_must_appraise_or_measure() called ima_match_policy twice, which searched the policy for a matching rule. Once for a matching measurement rule and subsequently for an appraisal rule. Searching the policy twice is unnecessary overhead, which could be noticeable with a large policy. The new version of ima_must_appraise_or_measure() does everything in a single iteration using a new version of ima_match_policy(). It returns IMA_MEASURE, IMA_APPRAISE mask. With the use of action mask only one efficient matching function is enough. Removed other specific versions of matching functions. Changelog: - change 'owner' to 'fowner' to conform to the new LSM conditions posted by Roberto Sassu. - fix calls to ima_log_string() Signed-off-by: Mimi Zohar <zohar@us.ibm.com> Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
Diffstat (limited to 'security')
-rw-r--r--security/integrity/ima/ima_appraise.c5
-rw-r--r--security/integrity/ima/ima_policy.c151
2 files changed, 116 insertions, 40 deletions
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 4865f61f9044..681cb6e72257 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -36,7 +36,10 @@ __setup("ima_appraise=", default_appraise_setup);
36 */ 36 */
37int ima_must_appraise(struct inode *inode, enum ima_hooks func, int mask) 37int ima_must_appraise(struct inode *inode, enum ima_hooks func, int mask)
38{ 38{
39 return 0; 39 if (!ima_appraise)
40 return 0;
41
42 return ima_match_policy(inode, func, mask, IMA_APPRAISE);
40} 43}
41 44
42static void ima_fix_xattr(struct dentry *dentry, 45static void ima_fix_xattr(struct dentry *dentry,
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 3e22e17da295..0d6d60b4ba6f 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -24,6 +24,7 @@
24#define IMA_MASK 0x0002 24#define IMA_MASK 0x0002
25#define IMA_FSMAGIC 0x0004 25#define IMA_FSMAGIC 0x0004
26#define IMA_UID 0x0008 26#define IMA_UID 0x0008
27#define IMA_FOWNER 0x0010
27 28
28#define UNKNOWN 0 29#define UNKNOWN 0
29#define MEASURE 1 /* same as IMA_MEASURE */ 30#define MEASURE 1 /* same as IMA_MEASURE */
@@ -38,7 +39,7 @@ enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
38 LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE 39 LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE
39}; 40};
40 41
41struct ima_measure_rule_entry { 42struct ima_rule_entry {
42 struct list_head list; 43 struct list_head list;
43 int action; 44 int action;
44 unsigned int flags; 45 unsigned int flags;
@@ -46,6 +47,7 @@ struct ima_measure_rule_entry {
46 int mask; 47 int mask;
47 unsigned long fsmagic; 48 unsigned long fsmagic;
48 uid_t uid; 49 uid_t uid;
50 uid_t fowner;
49 struct { 51 struct {
50 void *rule; /* LSM file metadata specific */ 52 void *rule; /* LSM file metadata specific */
51 int type; /* audit type */ 53 int type; /* audit type */
@@ -54,7 +56,7 @@ struct ima_measure_rule_entry {
54 56
55/* 57/*
56 * Without LSM specific knowledge, the default policy can only be 58 * Without LSM specific knowledge, the default policy can only be
57 * written in terms of .action, .func, .mask, .fsmagic, and .uid 59 * written in terms of .action, .func, .mask, .fsmagic, .uid, and .fowner
58 */ 60 */
59 61
60/* 62/*
@@ -63,7 +65,7 @@ struct ima_measure_rule_entry {
63 * normal users can easily run the machine out of memory simply building 65 * normal users can easily run the machine out of memory simply building
64 * and running executables. 66 * and running executables.
65 */ 67 */
66static struct ima_measure_rule_entry default_rules[] = { 68static struct ima_rule_entry default_rules[] = {
67 {.action = DONT_MEASURE,.fsmagic = PROC_SUPER_MAGIC,.flags = IMA_FSMAGIC}, 69 {.action = DONT_MEASURE,.fsmagic = PROC_SUPER_MAGIC,.flags = IMA_FSMAGIC},
68 {.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC}, 70 {.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC},
69 {.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC}, 71 {.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC},
@@ -81,19 +83,41 @@ static struct ima_measure_rule_entry default_rules[] = {
81 .flags = IMA_FUNC | IMA_MASK | IMA_UID}, 83 .flags = IMA_FUNC | IMA_MASK | IMA_UID},
82}; 84};
83 85
84static LIST_HEAD(measure_default_rules); 86static struct ima_rule_entry default_appraise_rules[] = {
85static LIST_HEAD(measure_policy_rules); 87 {.action = DONT_APPRAISE,.fsmagic = PROC_SUPER_MAGIC,.flags = IMA_FSMAGIC},
86static struct list_head *ima_measure; 88 {.action = DONT_APPRAISE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC},
89 {.action = DONT_APPRAISE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC},
90 {.action = DONT_APPRAISE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC},
91 {.action = DONT_APPRAISE,.fsmagic = RAMFS_MAGIC,.flags = IMA_FSMAGIC},
92 {.action = DONT_APPRAISE,.fsmagic = DEVPTS_SUPER_MAGIC,.flags = IMA_FSMAGIC},
93 {.action = DONT_APPRAISE,.fsmagic = BINFMTFS_MAGIC,.flags = IMA_FSMAGIC},
94 {.action = DONT_APPRAISE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC},
95 {.action = DONT_APPRAISE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC},
96 {.action = DONT_APPRAISE,.fsmagic = CGROUP_SUPER_MAGIC,.flags = IMA_FSMAGIC},
97 {.action = APPRAISE,.fowner = 0,.flags = IMA_FOWNER},
98};
99
100static LIST_HEAD(ima_default_rules);
101static LIST_HEAD(ima_policy_rules);
102static struct list_head *ima_rules;
87 103
88static DEFINE_MUTEX(ima_measure_mutex); 104static DEFINE_MUTEX(ima_rules_mutex);
89 105
90static bool ima_use_tcb __initdata; 106static bool ima_use_tcb __initdata;
91static int __init default_policy_setup(char *str) 107static int __init default_measure_policy_setup(char *str)
92{ 108{
93 ima_use_tcb = 1; 109 ima_use_tcb = 1;
94 return 1; 110 return 1;
95} 111}
96__setup("ima_tcb", default_policy_setup); 112__setup("ima_tcb", default_measure_policy_setup);
113
114static bool ima_use_appraise_tcb __initdata;
115static int __init default_appraise_policy_setup(char *str)
116{
117 ima_use_appraise_tcb = 1;
118 return 1;
119}
120__setup("ima_appraise_tcb", default_appraise_policy_setup);
97 121
98/** 122/**
99 * ima_match_rules - determine whether an inode matches the measure rule. 123 * ima_match_rules - determine whether an inode matches the measure rule.
@@ -104,7 +128,7 @@ __setup("ima_tcb", default_policy_setup);
104 * 128 *
105 * Returns true on rule match, false on failure. 129 * Returns true on rule match, false on failure.
106 */ 130 */
107static bool ima_match_rules(struct ima_measure_rule_entry *rule, 131static bool ima_match_rules(struct ima_rule_entry *rule,
108 struct inode *inode, enum ima_hooks func, int mask) 132 struct inode *inode, enum ima_hooks func, int mask)
109{ 133{
110 struct task_struct *tsk = current; 134 struct task_struct *tsk = current;
@@ -120,6 +144,8 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,
120 return false; 144 return false;
121 if ((rule->flags & IMA_UID) && rule->uid != cred->uid) 145 if ((rule->flags & IMA_UID) && rule->uid != cred->uid)
122 return false; 146 return false;
147 if ((rule->flags & IMA_FOWNER) && rule->fowner != inode->i_uid)
148 return false;
123 for (i = 0; i < MAX_LSM_RULES; i++) { 149 for (i = 0; i < MAX_LSM_RULES; i++) {
124 int rc = 0; 150 int rc = 0;
125 u32 osid, sid; 151 u32 osid, sid;
@@ -172,10 +198,10 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,
172int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, 198int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
173 int flags) 199 int flags)
174{ 200{
175 struct ima_measure_rule_entry *entry; 201 struct ima_rule_entry *entry;
176 int action = 0, actmask = flags | (flags << 1); 202 int action = 0, actmask = flags | (flags << 1);
177 203
178 list_for_each_entry(entry, ima_measure, list) { 204 list_for_each_entry(entry, ima_rules, list) {
179 205
180 if (!(entry->action & actmask)) 206 if (!(entry->action & actmask))
181 continue; 207 continue;
@@ -196,22 +222,31 @@ int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
196/** 222/**
197 * ima_init_policy - initialize the default measure rules. 223 * ima_init_policy - initialize the default measure rules.
198 * 224 *
199 * ima_measure points to either the measure_default_rules or the 225 * ima_rules points to either the ima_default_rules or the
200 * the new measure_policy_rules. 226 * the new ima_policy_rules.
201 */ 227 */
202void __init ima_init_policy(void) 228void __init ima_init_policy(void)
203{ 229{
204 int i, entries; 230 int i, measure_entries, appraise_entries;
205 231
206 /* if !ima_use_tcb set entries = 0 so we load NO default rules */ 232 /* if !ima_use_tcb set entries = 0 so we load NO default rules */
207 if (ima_use_tcb) 233 measure_entries = ima_use_tcb ? ARRAY_SIZE(default_rules) : 0;
208 entries = ARRAY_SIZE(default_rules); 234 appraise_entries = ima_use_appraise_tcb ?
209 else 235 ARRAY_SIZE(default_appraise_rules) : 0;
210 entries = 0; 236
211 237 for (i = 0; i < measure_entries + appraise_entries; i++) {
212 for (i = 0; i < entries; i++) 238 if (i < measure_entries)
213 list_add_tail(&default_rules[i].list, &measure_default_rules); 239 list_add_tail(&default_rules[i].list,
214 ima_measure = &measure_default_rules; 240 &ima_default_rules);
241 else {
242 int j = i - measure_entries;
243
244 list_add_tail(&default_appraise_rules[j].list,
245 &ima_default_rules);
246 }
247 }
248
249 ima_rules = &ima_default_rules;
215} 250}
216 251
217/** 252/**
@@ -228,8 +263,8 @@ void ima_update_policy(void)
228 int result = 1; 263 int result = 1;
229 int audit_info = 0; 264 int audit_info = 0;
230 265
231 if (ima_measure == &measure_default_rules) { 266 if (ima_rules == &ima_default_rules) {
232 ima_measure = &measure_policy_rules; 267 ima_rules = &ima_policy_rules;
233 cause = "complete"; 268 cause = "complete";
234 result = 0; 269 result = 0;
235 } 270 }
@@ -240,14 +275,17 @@ void ima_update_policy(void)
240enum { 275enum {
241 Opt_err = -1, 276 Opt_err = -1,
242 Opt_measure = 1, Opt_dont_measure, 277 Opt_measure = 1, Opt_dont_measure,
278 Opt_appraise, Opt_dont_appraise,
243 Opt_obj_user, Opt_obj_role, Opt_obj_type, 279 Opt_obj_user, Opt_obj_role, Opt_obj_type,
244 Opt_subj_user, Opt_subj_role, Opt_subj_type, 280 Opt_subj_user, Opt_subj_role, Opt_subj_type,
245 Opt_func, Opt_mask, Opt_fsmagic, Opt_uid 281 Opt_func, Opt_mask, Opt_fsmagic, Opt_uid, Opt_fowner
246}; 282};
247 283
248static match_table_t policy_tokens = { 284static match_table_t policy_tokens = {
249 {Opt_measure, "measure"}, 285 {Opt_measure, "measure"},
250 {Opt_dont_measure, "dont_measure"}, 286 {Opt_dont_measure, "dont_measure"},
287 {Opt_appraise, "appraise"},
288 {Opt_dont_appraise, "dont_appraise"},
251 {Opt_obj_user, "obj_user=%s"}, 289 {Opt_obj_user, "obj_user=%s"},
252 {Opt_obj_role, "obj_role=%s"}, 290 {Opt_obj_role, "obj_role=%s"},
253 {Opt_obj_type, "obj_type=%s"}, 291 {Opt_obj_type, "obj_type=%s"},
@@ -258,10 +296,11 @@ static match_table_t policy_tokens = {
258 {Opt_mask, "mask=%s"}, 296 {Opt_mask, "mask=%s"},
259 {Opt_fsmagic, "fsmagic=%s"}, 297 {Opt_fsmagic, "fsmagic=%s"},
260 {Opt_uid, "uid=%s"}, 298 {Opt_uid, "uid=%s"},
299 {Opt_fowner, "fowner=%s"},
261 {Opt_err, NULL} 300 {Opt_err, NULL}
262}; 301};
263 302
264static int ima_lsm_rule_init(struct ima_measure_rule_entry *entry, 303static int ima_lsm_rule_init(struct ima_rule_entry *entry,
265 char *args, int lsm_rule, int audit_type) 304 char *args, int lsm_rule, int audit_type)
266{ 305{
267 int result; 306 int result;
@@ -285,7 +324,7 @@ static void ima_log_string(struct audit_buffer *ab, char *key, char *value)
285 audit_log_format(ab, " "); 324 audit_log_format(ab, " ");
286} 325}
287 326
288static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) 327static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
289{ 328{
290 struct audit_buffer *ab; 329 struct audit_buffer *ab;
291 char *p; 330 char *p;
@@ -294,6 +333,7 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
294 ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE); 333 ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE);
295 334
296 entry->uid = -1; 335 entry->uid = -1;
336 entry->fowner = -1;
297 entry->action = UNKNOWN; 337 entry->action = UNKNOWN;
298 while ((p = strsep(&rule, " \t")) != NULL) { 338 while ((p = strsep(&rule, " \t")) != NULL) {
299 substring_t args[MAX_OPT_ARGS]; 339 substring_t args[MAX_OPT_ARGS];
@@ -322,11 +362,27 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
322 362
323 entry->action = DONT_MEASURE; 363 entry->action = DONT_MEASURE;
324 break; 364 break;
365 case Opt_appraise:
366 ima_log_string(ab, "action", "appraise");
367
368 if (entry->action != UNKNOWN)
369 result = -EINVAL;
370
371 entry->action = APPRAISE;
372 break;
373 case Opt_dont_appraise:
374 ima_log_string(ab, "action", "dont_appraise");
375
376 if (entry->action != UNKNOWN)
377 result = -EINVAL;
378
379 entry->action = DONT_APPRAISE;
380 break;
325 case Opt_func: 381 case Opt_func:
326 ima_log_string(ab, "func", args[0].from); 382 ima_log_string(ab, "func", args[0].from);
327 383
328 if (entry->func) 384 if (entry->func)
329 result = -EINVAL; 385 result = -EINVAL;
330 386
331 if (strcmp(args[0].from, "FILE_CHECK") == 0) 387 if (strcmp(args[0].from, "FILE_CHECK") == 0)
332 entry->func = FILE_CHECK; 388 entry->func = FILE_CHECK;
@@ -391,6 +447,23 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
391 entry->flags |= IMA_UID; 447 entry->flags |= IMA_UID;
392 } 448 }
393 break; 449 break;
450 case Opt_fowner:
451 ima_log_string(ab, "fowner", args[0].from);
452
453 if (entry->fowner != -1) {
454 result = -EINVAL;
455 break;
456 }
457
458 result = strict_strtoul(args[0].from, 10, &lnum);
459 if (!result) {
460 entry->fowner = (uid_t) lnum;
461 if (entry->fowner != lnum)
462 result = -EINVAL;
463 else
464 entry->flags |= IMA_FOWNER;
465 }
466 break;
394 case Opt_obj_user: 467 case Opt_obj_user:
395 ima_log_string(ab, "obj_user", args[0].from); 468 ima_log_string(ab, "obj_user", args[0].from);
396 result = ima_lsm_rule_init(entry, args[0].from, 469 result = ima_lsm_rule_init(entry, args[0].from,
@@ -442,7 +515,7 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
442} 515}
443 516
444/** 517/**
445 * ima_parse_add_rule - add a rule to measure_policy_rules 518 * ima_parse_add_rule - add a rule to ima_policy_rules
446 * @rule - ima measurement policy rule 519 * @rule - ima measurement policy rule
447 * 520 *
448 * Uses a mutex to protect the policy list from multiple concurrent writers. 521 * Uses a mutex to protect the policy list from multiple concurrent writers.
@@ -452,12 +525,12 @@ ssize_t ima_parse_add_rule(char *rule)
452{ 525{
453 const char *op = "update_policy"; 526 const char *op = "update_policy";
454 char *p; 527 char *p;
455 struct ima_measure_rule_entry *entry; 528 struct ima_rule_entry *entry;
456 ssize_t result, len; 529 ssize_t result, len;
457 int audit_info = 0; 530 int audit_info = 0;
458 531
459 /* Prevent installed policy from changing */ 532 /* Prevent installed policy from changing */
460 if (ima_measure != &measure_default_rules) { 533 if (ima_rules != &ima_default_rules) {
461 integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, 534 integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
462 NULL, op, "already exists", 535 NULL, op, "already exists",
463 -EACCES, audit_info); 536 -EACCES, audit_info);
@@ -490,9 +563,9 @@ ssize_t ima_parse_add_rule(char *rule)
490 return result; 563 return result;
491 } 564 }
492 565
493 mutex_lock(&ima_measure_mutex); 566 mutex_lock(&ima_rules_mutex);
494 list_add_tail(&entry->list, &measure_policy_rules); 567 list_add_tail(&entry->list, &ima_policy_rules);
495 mutex_unlock(&ima_measure_mutex); 568 mutex_unlock(&ima_rules_mutex);
496 569
497 return len; 570 return len;
498} 571}
@@ -500,12 +573,12 @@ ssize_t ima_parse_add_rule(char *rule)
500/* ima_delete_rules called to cleanup invalid policy */ 573/* ima_delete_rules called to cleanup invalid policy */
501void ima_delete_rules(void) 574void ima_delete_rules(void)
502{ 575{
503 struct ima_measure_rule_entry *entry, *tmp; 576 struct ima_rule_entry *entry, *tmp;
504 577
505 mutex_lock(&ima_measure_mutex); 578 mutex_lock(&ima_rules_mutex);
506 list_for_each_entry_safe(entry, tmp, &measure_policy_rules, list) { 579 list_for_each_entry_safe(entry, tmp, &ima_policy_rules, list) {
507 list_del(&entry->list); 580 list_del(&entry->list);
508 kfree(entry); 581 kfree(entry);
509 } 582 }
510 mutex_unlock(&ima_measure_mutex); 583 mutex_unlock(&ima_rules_mutex);
511} 584}