aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Morris <james.l.morris@oracle.com>2015-06-18 09:28:40 -0400
committerJames Morris <james.l.morris@oracle.com>2015-06-18 09:28:40 -0400
commitb3bddffd35a0b77eee89760eb94cafa18dc431f5 (patch)
tree58c0f6c79c121dfbe91f2058210c79d7ee25acc2
parent49afd7289bd937401c5f7faa193054bc3c41dad6 (diff)
parent24fd03c87695a76f0517df42a37e51b1597d2c8a (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity into next
-rw-r--r--Documentation/ABI/testing/ima_policy6
-rw-r--r--Documentation/kernel-parameters.txt10
-rw-r--r--security/integrity/ima/ima.h2
-rw-r--r--security/integrity/ima/ima_fs.c4
-rw-r--r--security/integrity/ima/ima_policy.c112
-rw-r--r--security/integrity/ima/ima_template_lib.c3
6 files changed, 112 insertions, 25 deletions
diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
index 8ae3f57090d4..0a378a88217a 100644
--- a/Documentation/ABI/testing/ima_policy
+++ b/Documentation/ABI/testing/ima_policy
@@ -20,17 +20,19 @@ Description:
20 action: measure | dont_measure | appraise | dont_appraise | audit 20 action: measure | dont_measure | appraise | dont_appraise | audit
21 condition:= base | lsm [option] 21 condition:= base | lsm [option]
22 base: [[func=] [mask=] [fsmagic=] [fsuuid=] [uid=] 22 base: [[func=] [mask=] [fsmagic=] [fsuuid=] [uid=]
23 [fowner]] 23 [euid=] [fowner=]]
24 lsm: [[subj_user=] [subj_role=] [subj_type=] 24 lsm: [[subj_user=] [subj_role=] [subj_type=]
25 [obj_user=] [obj_role=] [obj_type=]] 25 [obj_user=] [obj_role=] [obj_type=]]
26 option: [[appraise_type=]] [permit_directio] 26 option: [[appraise_type=]] [permit_directio]
27 27
28 base: func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK] 28 base: func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
29 [FIRMWARE_CHECK] 29 [FIRMWARE_CHECK]
30 mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC] 30 mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
31 [[^]MAY_EXEC]
31 fsmagic:= hex value 32 fsmagic:= hex value
32 fsuuid:= file system UUID (e.g 8bcbe394-4f13-4144-be8e-5aa9ea2ce2f6) 33 fsuuid:= file system UUID (e.g 8bcbe394-4f13-4144-be8e-5aa9ea2ce2f6)
33 uid:= decimal value 34 uid:= decimal value
35 euid:= decimal value
34 fowner:=decimal value 36 fowner:=decimal value
35 lsm: are LSM specific 37 lsm: are LSM specific
36 option: appraise_type:= [imasig] 38 option: appraise_type:= [imasig]
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index abc496f95220..807b765087d4 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1398,7 +1398,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
1398 The list of supported hash algorithms is defined 1398 The list of supported hash algorithms is defined
1399 in crypto/hash_info.h. 1399 in crypto/hash_info.h.
1400 1400
1401 ima_tcb [IMA] 1401 ima_policy= [IMA]
1402 The builtin measurement policy to load during IMA
1403 setup. Specyfing "tcb" as the value, measures all
1404 programs exec'd, files mmap'd for exec, and all files
1405 opened with the read mode bit set by either the
1406 effective uid (euid=0) or uid=0.
1407 Format: "tcb"
1408
1409 ima_tcb [IMA] Deprecated. Use ima_policy= instead.
1402 Load a policy which meets the needs of the Trusted 1410 Load a policy which meets the needs of the Trusted
1403 Computing Base. This means IMA will measure all 1411 Computing Base. This means IMA will measure all
1404 programs exec'd, files mmap'd for exec, and all files 1412 programs exec'd, files mmap'd for exec, and all files
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index c996f7edff3a..e2a60c30df44 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -115,7 +115,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
115 const char *op, const char *cause); 115 const char *op, const char *cause);
116int ima_init_crypto(void); 116int ima_init_crypto(void);
117void ima_putc(struct seq_file *m, void *data, int datalen); 117void ima_putc(struct seq_file *m, void *data, int datalen);
118void ima_print_digest(struct seq_file *m, u8 *digest, int size); 118void ima_print_digest(struct seq_file *m, u8 *digest, u32 size);
119struct ima_template_desc *ima_template_desc_current(void); 119struct ima_template_desc *ima_template_desc_current(void);
120int ima_init_template(void); 120int ima_init_template(void);
121 121
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 461215e5fd31..816d175da79a 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -190,9 +190,9 @@ static const struct file_operations ima_measurements_ops = {
190 .release = seq_release, 190 .release = seq_release,
191}; 191};
192 192
193void ima_print_digest(struct seq_file *m, u8 *digest, int size) 193void ima_print_digest(struct seq_file *m, u8 *digest, u32 size)
194{ 194{
195 int i; 195 u32 i;
196 196
197 for (i = 0; i < size; i++) 197 for (i = 0; i < size; i++)
198 seq_printf(m, "%02x", *(digest + i)); 198 seq_printf(m, "%02x", *(digest + i));
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index f2421f7fa3c8..3997e206f82d 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -27,6 +27,8 @@
27#define IMA_UID 0x0008 27#define IMA_UID 0x0008
28#define IMA_FOWNER 0x0010 28#define IMA_FOWNER 0x0010
29#define IMA_FSUUID 0x0020 29#define IMA_FSUUID 0x0020
30#define IMA_INMASK 0x0040
31#define IMA_EUID 0x0080
30 32
31#define UNKNOWN 0 33#define UNKNOWN 0
32#define MEASURE 0x0001 /* same as IMA_MEASURE */ 34#define MEASURE 0x0001 /* same as IMA_MEASURE */
@@ -42,6 +44,8 @@ enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
42 LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE 44 LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE
43}; 45};
44 46
47enum policy_types { ORIGINAL_TCB = 1, DEFAULT_TCB };
48
45struct ima_rule_entry { 49struct ima_rule_entry {
46 struct list_head list; 50 struct list_head list;
47 int action; 51 int action;
@@ -70,7 +74,7 @@ struct ima_rule_entry {
70 * normal users can easily run the machine out of memory simply building 74 * normal users can easily run the machine out of memory simply building
71 * and running executables. 75 * and running executables.
72 */ 76 */
73static struct ima_rule_entry default_rules[] = { 77static struct ima_rule_entry dont_measure_rules[] = {
74 {.action = DONT_MEASURE, .fsmagic = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC}, 78 {.action = DONT_MEASURE, .fsmagic = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC},
75 {.action = DONT_MEASURE, .fsmagic = SYSFS_MAGIC, .flags = IMA_FSMAGIC}, 79 {.action = DONT_MEASURE, .fsmagic = SYSFS_MAGIC, .flags = IMA_FSMAGIC},
76 {.action = DONT_MEASURE, .fsmagic = DEBUGFS_MAGIC, .flags = IMA_FSMAGIC}, 80 {.action = DONT_MEASURE, .fsmagic = DEBUGFS_MAGIC, .flags = IMA_FSMAGIC},
@@ -81,13 +85,29 @@ static struct ima_rule_entry default_rules[] = {
81 {.action = DONT_MEASURE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC}, 85 {.action = DONT_MEASURE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
82 {.action = DONT_MEASURE, .fsmagic = CGROUP_SUPER_MAGIC, 86 {.action = DONT_MEASURE, .fsmagic = CGROUP_SUPER_MAGIC,
83 .flags = IMA_FSMAGIC}, 87 .flags = IMA_FSMAGIC},
84 {.action = DONT_MEASURE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC}, 88 {.action = DONT_MEASURE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC}
89};
90
91static struct ima_rule_entry original_measurement_rules[] = {
85 {.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC, 92 {.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC,
86 .flags = IMA_FUNC | IMA_MASK}, 93 .flags = IMA_FUNC | IMA_MASK},
87 {.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC, 94 {.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC,
88 .flags = IMA_FUNC | IMA_MASK}, 95 .flags = IMA_FUNC | IMA_MASK},
89 {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ, .uid = GLOBAL_ROOT_UID, 96 {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ,
90 .flags = IMA_FUNC | IMA_MASK | IMA_UID}, 97 .uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_MASK | IMA_UID},
98 {.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
99 {.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC},
100};
101
102static struct ima_rule_entry default_measurement_rules[] = {
103 {.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC,
104 .flags = IMA_FUNC | IMA_MASK},
105 {.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC,
106 .flags = IMA_FUNC | IMA_MASK},
107 {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ,
108 .uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_INMASK | IMA_EUID},
109 {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ,
110 .uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_INMASK | IMA_UID},
91 {.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC}, 111 {.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
92 {.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC}, 112 {.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC},
93}; 113};
@@ -119,14 +139,29 @@ static struct list_head *ima_rules;
119 139
120static DEFINE_MUTEX(ima_rules_mutex); 140static DEFINE_MUTEX(ima_rules_mutex);
121 141
122static bool ima_use_tcb __initdata; 142static int ima_policy __initdata;
123static int __init default_measure_policy_setup(char *str) 143static int __init default_measure_policy_setup(char *str)
124{ 144{
125 ima_use_tcb = 1; 145 if (ima_policy)
146 return 1;
147
148 ima_policy = ORIGINAL_TCB;
126 return 1; 149 return 1;
127} 150}
128__setup("ima_tcb", default_measure_policy_setup); 151__setup("ima_tcb", default_measure_policy_setup);
129 152
153static int __init policy_setup(char *str)
154{
155 if (ima_policy)
156 return 1;
157
158 if (strcmp(str, "tcb") == 0)
159 ima_policy = DEFAULT_TCB;
160
161 return 1;
162}
163__setup("ima_policy=", policy_setup);
164
130static bool ima_use_appraise_tcb __initdata; 165static bool ima_use_appraise_tcb __initdata;
131static int __init default_appraise_policy_setup(char *str) 166static int __init default_appraise_policy_setup(char *str)
132{ 167{
@@ -186,6 +221,9 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
186 if ((rule->flags & IMA_MASK) && 221 if ((rule->flags & IMA_MASK) &&
187 (rule->mask != mask && func != POST_SETATTR)) 222 (rule->mask != mask && func != POST_SETATTR))
188 return false; 223 return false;
224 if ((rule->flags & IMA_INMASK) &&
225 (!(rule->mask & mask) && func != POST_SETATTR))
226 return false;
189 if ((rule->flags & IMA_FSMAGIC) 227 if ((rule->flags & IMA_FSMAGIC)
190 && rule->fsmagic != inode->i_sb->s_magic) 228 && rule->fsmagic != inode->i_sb->s_magic)
191 return false; 229 return false;
@@ -194,6 +232,16 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
194 return false; 232 return false;
195 if ((rule->flags & IMA_UID) && !uid_eq(rule->uid, cred->uid)) 233 if ((rule->flags & IMA_UID) && !uid_eq(rule->uid, cred->uid))
196 return false; 234 return false;
235 if (rule->flags & IMA_EUID) {
236 if (has_capability_noaudit(current, CAP_SETUID)) {
237 if (!uid_eq(rule->uid, cred->euid)
238 && !uid_eq(rule->uid, cred->suid)
239 && !uid_eq(rule->uid, cred->uid))
240 return false;
241 } else if (!uid_eq(rule->uid, cred->euid))
242 return false;
243 }
244
197 if ((rule->flags & IMA_FOWNER) && !uid_eq(rule->fowner, inode->i_uid)) 245 if ((rule->flags & IMA_FOWNER) && !uid_eq(rule->fowner, inode->i_uid))
198 return false; 246 return false;
199 for (i = 0; i < MAX_LSM_RULES; i++) { 247 for (i = 0; i < MAX_LSM_RULES; i++) {
@@ -337,13 +385,27 @@ void __init ima_init_policy(void)
337{ 385{
338 int i, measure_entries, appraise_entries; 386 int i, measure_entries, appraise_entries;
339 387
340 /* if !ima_use_tcb set entries = 0 so we load NO default rules */ 388 /* if !ima_policy set entries = 0 so we load NO default rules */
341 measure_entries = ima_use_tcb ? ARRAY_SIZE(default_rules) : 0; 389 measure_entries = ima_policy ? ARRAY_SIZE(dont_measure_rules) : 0;
342 appraise_entries = ima_use_appraise_tcb ? 390 appraise_entries = ima_use_appraise_tcb ?
343 ARRAY_SIZE(default_appraise_rules) : 0; 391 ARRAY_SIZE(default_appraise_rules) : 0;
344 392
345 for (i = 0; i < measure_entries; i++) 393 for (i = 0; i < measure_entries; i++)
346 list_add_tail(&default_rules[i].list, &ima_default_rules); 394 list_add_tail(&dont_measure_rules[i].list, &ima_default_rules);
395
396 switch (ima_policy) {
397 case ORIGINAL_TCB:
398 for (i = 0; i < ARRAY_SIZE(original_measurement_rules); i++)
399 list_add_tail(&original_measurement_rules[i].list,
400 &ima_default_rules);
401 break;
402 case DEFAULT_TCB:
403 for (i = 0; i < ARRAY_SIZE(default_measurement_rules); i++)
404 list_add_tail(&default_measurement_rules[i].list,
405 &ima_default_rules);
406 default:
407 break;
408 }
347 409
348 for (i = 0; i < appraise_entries; i++) { 410 for (i = 0; i < appraise_entries; i++) {
349 list_add_tail(&default_appraise_rules[i].list, 411 list_add_tail(&default_appraise_rules[i].list,
@@ -373,7 +435,8 @@ enum {
373 Opt_audit, 435 Opt_audit,
374 Opt_obj_user, Opt_obj_role, Opt_obj_type, 436 Opt_obj_user, Opt_obj_role, Opt_obj_type,
375 Opt_subj_user, Opt_subj_role, Opt_subj_type, 437 Opt_subj_user, Opt_subj_role, Opt_subj_type,
376 Opt_func, Opt_mask, Opt_fsmagic, Opt_uid, Opt_fowner, 438 Opt_func, Opt_mask, Opt_fsmagic,
439 Opt_uid, Opt_euid, Opt_fowner,
377 Opt_appraise_type, Opt_fsuuid, Opt_permit_directio 440 Opt_appraise_type, Opt_fsuuid, Opt_permit_directio
378}; 441};
379 442
@@ -394,6 +457,7 @@ static match_table_t policy_tokens = {
394 {Opt_fsmagic, "fsmagic=%s"}, 457 {Opt_fsmagic, "fsmagic=%s"},
395 {Opt_fsuuid, "fsuuid=%s"}, 458 {Opt_fsuuid, "fsuuid=%s"},
396 {Opt_uid, "uid=%s"}, 459 {Opt_uid, "uid=%s"},
460 {Opt_euid, "euid=%s"},
397 {Opt_fowner, "fowner=%s"}, 461 {Opt_fowner, "fowner=%s"},
398 {Opt_appraise_type, "appraise_type=%s"}, 462 {Opt_appraise_type, "appraise_type=%s"},
399 {Opt_permit_directio, "permit_directio"}, 463 {Opt_permit_directio, "permit_directio"},
@@ -435,6 +499,7 @@ static void ima_log_string(struct audit_buffer *ab, char *key, char *value)
435static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) 499static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
436{ 500{
437 struct audit_buffer *ab; 501 struct audit_buffer *ab;
502 char *from;
438 char *p; 503 char *p;
439 int result = 0; 504 int result = 0;
440 505
@@ -525,18 +590,23 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
525 if (entry->mask) 590 if (entry->mask)
526 result = -EINVAL; 591 result = -EINVAL;
527 592
528 if ((strcmp(args[0].from, "MAY_EXEC")) == 0) 593 from = args[0].from;
594 if (*from == '^')
595 from++;
596
597 if ((strcmp(from, "MAY_EXEC")) == 0)
529 entry->mask = MAY_EXEC; 598 entry->mask = MAY_EXEC;
530 else if (strcmp(args[0].from, "MAY_WRITE") == 0) 599 else if (strcmp(from, "MAY_WRITE") == 0)
531 entry->mask = MAY_WRITE; 600 entry->mask = MAY_WRITE;
532 else if (strcmp(args[0].from, "MAY_READ") == 0) 601 else if (strcmp(from, "MAY_READ") == 0)
533 entry->mask = MAY_READ; 602 entry->mask = MAY_READ;
534 else if (strcmp(args[0].from, "MAY_APPEND") == 0) 603 else if (strcmp(from, "MAY_APPEND") == 0)
535 entry->mask = MAY_APPEND; 604 entry->mask = MAY_APPEND;
536 else 605 else
537 result = -EINVAL; 606 result = -EINVAL;
538 if (!result) 607 if (!result)
539 entry->flags |= IMA_MASK; 608 entry->flags |= (*args[0].from == '^')
609 ? IMA_INMASK : IMA_MASK;
540 break; 610 break;
541 case Opt_fsmagic: 611 case Opt_fsmagic:
542 ima_log_string(ab, "fsmagic", args[0].from); 612 ima_log_string(ab, "fsmagic", args[0].from);
@@ -566,6 +636,9 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
566 break; 636 break;
567 case Opt_uid: 637 case Opt_uid:
568 ima_log_string(ab, "uid", args[0].from); 638 ima_log_string(ab, "uid", args[0].from);
639 case Opt_euid:
640 if (token == Opt_euid)
641 ima_log_string(ab, "euid", args[0].from);
569 642
570 if (uid_valid(entry->uid)) { 643 if (uid_valid(entry->uid)) {
571 result = -EINVAL; 644 result = -EINVAL;
@@ -574,11 +647,14 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
574 647
575 result = kstrtoul(args[0].from, 10, &lnum); 648 result = kstrtoul(args[0].from, 10, &lnum);
576 if (!result) { 649 if (!result) {
577 entry->uid = make_kuid(current_user_ns(), (uid_t)lnum); 650 entry->uid = make_kuid(current_user_ns(),
578 if (!uid_valid(entry->uid) || (((uid_t)lnum) != lnum)) 651 (uid_t) lnum);
652 if (!uid_valid(entry->uid) ||
653 (uid_t)lnum != lnum)
579 result = -EINVAL; 654 result = -EINVAL;
580 else 655 else
581 entry->flags |= IMA_UID; 656 entry->flags |= (token == Opt_uid)
657 ? IMA_UID : IMA_EUID;
582 } 658 }
583 break; 659 break;
584 case Opt_fowner: 660 case Opt_fowner:
diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c
index de0ce4fbdf69..2934e3d377f1 100644
--- a/security/integrity/ima/ima_template_lib.c
+++ b/security/integrity/ima/ima_template_lib.c
@@ -70,7 +70,8 @@ static void ima_show_template_data_ascii(struct seq_file *m,
70 enum data_formats datafmt, 70 enum data_formats datafmt,
71 struct ima_field_data *field_data) 71 struct ima_field_data *field_data)
72{ 72{
73 u8 *buf_ptr = field_data->data, buflen = field_data->len; 73 u8 *buf_ptr = field_data->data;
74 u32 buflen = field_data->len;
74 75
75 switch (datafmt) { 76 switch (datafmt) {
76 case DATA_FMT_DIGEST_WITH_ALGO: 77 case DATA_FMT_DIGEST_WITH_ALGO: