diff options
author | Dmitry Kasatkin <dmitry.kasatkin@intel.com> | 2012-06-08 06:58:49 -0400 |
---|---|---|
committer | Mimi Zohar <zohar@linux.vnet.ibm.com> | 2013-01-22 16:10:31 -0500 |
commit | 0e5a247cb37a97d843ef76d09d5f80deb7893ba3 (patch) | |
tree | 7206abaf6d20e69a89584046ed7dc9970ba2da12 | |
parent | a175b8bb29ebbad380ab4788f307fbfc47997b19 (diff) |
ima: added policy support for 'security.ima' type
The 'security.ima' extended attribute may contain either the file data's
hash or a digital signature. This patch adds support for requiring a
specific extended attribute type. It extends the IMA policy with a new
keyword 'appraise_type=imasig'. (Default is hash.)
Changelog v2:
- Fixed Documentation/ABI/testing/ima_policy option syntax
Changelog v1:
- Differentiate between 'required' vs. 'actual' extended attribute
Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
-rw-r--r-- | Documentation/ABI/testing/ima_policy | 4 | ||||
-rw-r--r-- | security/integrity/ima/ima_appraise.c | 5 | ||||
-rw-r--r-- | security/integrity/ima/ima_main.c | 1 | ||||
-rw-r--r-- | security/integrity/ima/ima_policy.c | 18 | ||||
-rw-r--r-- | security/integrity/integrity.h | 2 |
5 files changed, 28 insertions, 2 deletions
diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy index 6a0fc808fb6d..de16de3f148d 100644 --- a/Documentation/ABI/testing/ima_policy +++ b/Documentation/ABI/testing/ima_policy | |||
@@ -18,10 +18,11 @@ Description: | |||
18 | rule format: action [condition ...] | 18 | rule format: action [condition ...] |
19 | 19 | ||
20 | action: measure | dont_measure | appraise | dont_appraise | audit | 20 | action: measure | dont_measure | appraise | dont_appraise | audit |
21 | condition:= base | lsm | 21 | condition:= base | lsm [option] |
22 | base: [[func=] [mask=] [fsmagic=] [uid=] [fowner]] | 22 | base: [[func=] [mask=] [fsmagic=] [uid=] [fowner]] |
23 | lsm: [[subj_user=] [subj_role=] [subj_type=] | 23 | lsm: [[subj_user=] [subj_role=] [subj_type=] |
24 | [obj_user=] [obj_role=] [obj_type=]] | 24 | [obj_user=] [obj_role=] [obj_type=]] |
25 | option: [[appraise_type=]] | ||
25 | 26 | ||
26 | base: func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK] | 27 | base: func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK] |
27 | mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC] | 28 | mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC] |
@@ -29,6 +30,7 @@ Description: | |||
29 | uid:= decimal value | 30 | uid:= decimal value |
30 | fowner:=decimal value | 31 | fowner:=decimal value |
31 | lsm: are LSM specific | 32 | lsm: are LSM specific |
33 | option: appraise_type:= [imasig] | ||
32 | 34 | ||
33 | default policy: | 35 | default policy: |
34 | # PROC_SUPER_MAGIC | 36 | # PROC_SUPER_MAGIC |
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index fa675c907e0f..8004332ccb8f 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c | |||
@@ -102,6 +102,11 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint, | |||
102 | 102 | ||
103 | switch (xattr_value->type) { | 103 | switch (xattr_value->type) { |
104 | case IMA_XATTR_DIGEST: | 104 | case IMA_XATTR_DIGEST: |
105 | if (iint->flags & IMA_DIGSIG_REQUIRED) { | ||
106 | cause = "IMA signature required"; | ||
107 | status = INTEGRITY_FAIL; | ||
108 | break; | ||
109 | } | ||
105 | rc = memcmp(xattr_value->digest, iint->ima_xattr.digest, | 110 | rc = memcmp(xattr_value->digest, iint->ima_xattr.digest, |
106 | IMA_DIGEST_SIZE); | 111 | IMA_DIGEST_SIZE); |
107 | if (rc) { | 112 | if (rc) { |
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index cd00ba39e8e0..3cdd78768c29 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
@@ -169,6 +169,7 @@ static int process_measurement(struct file *file, const char *filename, | |||
169 | * (IMA_MEASURE, IMA_MEASURED, IMA_APPRAISE, IMA_APPRAISED, | 169 | * (IMA_MEASURE, IMA_MEASURED, IMA_APPRAISE, IMA_APPRAISED, |
170 | * IMA_AUDIT, IMA_AUDITED) */ | 170 | * IMA_AUDIT, IMA_AUDITED) */ |
171 | iint->flags |= action; | 171 | iint->flags |= action; |
172 | action &= IMA_DO_MASK; | ||
172 | action &= ~((iint->flags & IMA_DONE_MASK) >> 1); | 173 | action &= ~((iint->flags & IMA_DONE_MASK) >> 1); |
173 | 174 | ||
174 | /* Nothing to do, just return existing appraised status */ | 175 | /* Nothing to do, just return existing appraised status */ |
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 95194539d75e..1a2543a8ee53 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c | |||
@@ -245,6 +245,8 @@ int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, | |||
245 | if (!ima_match_rules(entry, inode, func, mask)) | 245 | if (!ima_match_rules(entry, inode, func, mask)) |
246 | continue; | 246 | continue; |
247 | 247 | ||
248 | action |= entry->flags & IMA_ACTION_FLAGS; | ||
249 | |||
248 | action |= entry->action & IMA_DO_MASK; | 250 | action |= entry->action & IMA_DO_MASK; |
249 | if (entry->action & IMA_DO_MASK) | 251 | if (entry->action & IMA_DO_MASK) |
250 | actmask &= ~(entry->action | entry->action << 1); | 252 | actmask &= ~(entry->action | entry->action << 1); |
@@ -318,7 +320,8 @@ enum { | |||
318 | Opt_audit, | 320 | Opt_audit, |
319 | Opt_obj_user, Opt_obj_role, Opt_obj_type, | 321 | Opt_obj_user, Opt_obj_role, Opt_obj_type, |
320 | Opt_subj_user, Opt_subj_role, Opt_subj_type, | 322 | Opt_subj_user, Opt_subj_role, Opt_subj_type, |
321 | Opt_func, Opt_mask, Opt_fsmagic, Opt_uid, Opt_fowner | 323 | Opt_func, Opt_mask, Opt_fsmagic, Opt_uid, Opt_fowner, |
324 | Opt_appraise_type | ||
322 | }; | 325 | }; |
323 | 326 | ||
324 | static match_table_t policy_tokens = { | 327 | static match_table_t policy_tokens = { |
@@ -338,6 +341,7 @@ static match_table_t policy_tokens = { | |||
338 | {Opt_fsmagic, "fsmagic=%s"}, | 341 | {Opt_fsmagic, "fsmagic=%s"}, |
339 | {Opt_uid, "uid=%s"}, | 342 | {Opt_uid, "uid=%s"}, |
340 | {Opt_fowner, "fowner=%s"}, | 343 | {Opt_fowner, "fowner=%s"}, |
344 | {Opt_appraise_type, "appraise_type=%s"}, | ||
341 | {Opt_err, NULL} | 345 | {Opt_err, NULL} |
342 | }; | 346 | }; |
343 | 347 | ||
@@ -560,6 +564,18 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) | |||
560 | LSM_SUBJ_TYPE, | 564 | LSM_SUBJ_TYPE, |
561 | AUDIT_SUBJ_TYPE); | 565 | AUDIT_SUBJ_TYPE); |
562 | break; | 566 | break; |
567 | case Opt_appraise_type: | ||
568 | if (entry->action != APPRAISE) { | ||
569 | result = -EINVAL; | ||
570 | break; | ||
571 | } | ||
572 | |||
573 | ima_log_string(ab, "appraise_type", args[0].from); | ||
574 | if ((strcmp(args[0].from, "imasig")) == 0) | ||
575 | entry->flags |= IMA_DIGSIG_REQUIRED; | ||
576 | else | ||
577 | result = -EINVAL; | ||
578 | break; | ||
563 | case Opt_err: | 579 | case Opt_err: |
564 | ima_log_string(ab, "UNKNOWN", p); | 580 | ima_log_string(ab, "UNKNOWN", p); |
565 | result = -EINVAL; | 581 | result = -EINVAL; |
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 0a298def5036..9334691b2b75 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h | |||
@@ -26,7 +26,9 @@ | |||
26 | #define IMA_AUDITED 0x0080 | 26 | #define IMA_AUDITED 0x0080 |
27 | 27 | ||
28 | /* iint cache flags */ | 28 | /* iint cache flags */ |
29 | #define IMA_ACTION_FLAGS 0xff00 | ||
29 | #define IMA_DIGSIG 0x0100 | 30 | #define IMA_DIGSIG 0x0100 |
31 | #define IMA_DIGSIG_REQUIRED 0x0200 | ||
30 | 32 | ||
31 | #define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT) | 33 | #define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT) |
32 | #define IMA_DONE_MASK (IMA_MEASURED | IMA_APPRAISED | IMA_AUDITED \ | 34 | #define IMA_DONE_MASK (IMA_MEASURED | IMA_APPRAISED | IMA_AUDITED \ |