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>
This commit is contained in:
parent
a175b8bb29
commit
0e5a247cb3
|
@ -18,10 +18,11 @@ Description:
|
||||||
rule format: action [condition ...]
|
rule format: action [condition ...]
|
||||||
|
|
||||||
action: measure | dont_measure | appraise | dont_appraise | audit
|
action: measure | dont_measure | appraise | dont_appraise | audit
|
||||||
condition:= base | lsm
|
condition:= base | lsm [option]
|
||||||
base: [[func=] [mask=] [fsmagic=] [uid=] [fowner]]
|
base: [[func=] [mask=] [fsmagic=] [uid=] [fowner]]
|
||||||
lsm: [[subj_user=] [subj_role=] [subj_type=]
|
lsm: [[subj_user=] [subj_role=] [subj_type=]
|
||||||
[obj_user=] [obj_role=] [obj_type=]]
|
[obj_user=] [obj_role=] [obj_type=]]
|
||||||
|
option: [[appraise_type=]]
|
||||||
|
|
||||||
base: func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
|
base: func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
|
||||||
mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC]
|
mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC]
|
||||||
|
@ -29,6 +30,7 @@ Description:
|
||||||
uid:= decimal value
|
uid:= decimal value
|
||||||
fowner:=decimal value
|
fowner:=decimal value
|
||||||
lsm: are LSM specific
|
lsm: are LSM specific
|
||||||
|
option: appraise_type:= [imasig]
|
||||||
|
|
||||||
default policy:
|
default policy:
|
||||||
# PROC_SUPER_MAGIC
|
# PROC_SUPER_MAGIC
|
||||||
|
|
|
@ -102,6 +102,11 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint,
|
||||||
|
|
||||||
switch (xattr_value->type) {
|
switch (xattr_value->type) {
|
||||||
case IMA_XATTR_DIGEST:
|
case IMA_XATTR_DIGEST:
|
||||||
|
if (iint->flags & IMA_DIGSIG_REQUIRED) {
|
||||||
|
cause = "IMA signature required";
|
||||||
|
status = INTEGRITY_FAIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
rc = memcmp(xattr_value->digest, iint->ima_xattr.digest,
|
rc = memcmp(xattr_value->digest, iint->ima_xattr.digest,
|
||||||
IMA_DIGEST_SIZE);
|
IMA_DIGEST_SIZE);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
|
|
@ -169,6 +169,7 @@ static int process_measurement(struct file *file, const char *filename,
|
||||||
* (IMA_MEASURE, IMA_MEASURED, IMA_APPRAISE, IMA_APPRAISED,
|
* (IMA_MEASURE, IMA_MEASURED, IMA_APPRAISE, IMA_APPRAISED,
|
||||||
* IMA_AUDIT, IMA_AUDITED) */
|
* IMA_AUDIT, IMA_AUDITED) */
|
||||||
iint->flags |= action;
|
iint->flags |= action;
|
||||||
|
action &= IMA_DO_MASK;
|
||||||
action &= ~((iint->flags & IMA_DONE_MASK) >> 1);
|
action &= ~((iint->flags & IMA_DONE_MASK) >> 1);
|
||||||
|
|
||||||
/* Nothing to do, just return existing appraised status */
|
/* Nothing to do, just return existing appraised status */
|
||||||
|
|
|
@ -245,6 +245,8 @@ int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
|
||||||
if (!ima_match_rules(entry, inode, func, mask))
|
if (!ima_match_rules(entry, inode, func, mask))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
action |= entry->flags & IMA_ACTION_FLAGS;
|
||||||
|
|
||||||
action |= entry->action & IMA_DO_MASK;
|
action |= entry->action & IMA_DO_MASK;
|
||||||
if (entry->action & IMA_DO_MASK)
|
if (entry->action & IMA_DO_MASK)
|
||||||
actmask &= ~(entry->action | entry->action << 1);
|
actmask &= ~(entry->action | entry->action << 1);
|
||||||
|
@ -318,7 +320,8 @@ enum {
|
||||||
Opt_audit,
|
Opt_audit,
|
||||||
Opt_obj_user, Opt_obj_role, Opt_obj_type,
|
Opt_obj_user, Opt_obj_role, Opt_obj_type,
|
||||||
Opt_subj_user, Opt_subj_role, Opt_subj_type,
|
Opt_subj_user, Opt_subj_role, Opt_subj_type,
|
||||||
Opt_func, Opt_mask, Opt_fsmagic, Opt_uid, Opt_fowner
|
Opt_func, Opt_mask, Opt_fsmagic, Opt_uid, Opt_fowner,
|
||||||
|
Opt_appraise_type
|
||||||
};
|
};
|
||||||
|
|
||||||
static match_table_t policy_tokens = {
|
static match_table_t policy_tokens = {
|
||||||
|
@ -338,6 +341,7 @@ static match_table_t policy_tokens = {
|
||||||
{Opt_fsmagic, "fsmagic=%s"},
|
{Opt_fsmagic, "fsmagic=%s"},
|
||||||
{Opt_uid, "uid=%s"},
|
{Opt_uid, "uid=%s"},
|
||||||
{Opt_fowner, "fowner=%s"},
|
{Opt_fowner, "fowner=%s"},
|
||||||
|
{Opt_appraise_type, "appraise_type=%s"},
|
||||||
{Opt_err, NULL}
|
{Opt_err, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -560,6 +564,18 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
|
||||||
LSM_SUBJ_TYPE,
|
LSM_SUBJ_TYPE,
|
||||||
AUDIT_SUBJ_TYPE);
|
AUDIT_SUBJ_TYPE);
|
||||||
break;
|
break;
|
||||||
|
case Opt_appraise_type:
|
||||||
|
if (entry->action != APPRAISE) {
|
||||||
|
result = -EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ima_log_string(ab, "appraise_type", args[0].from);
|
||||||
|
if ((strcmp(args[0].from, "imasig")) == 0)
|
||||||
|
entry->flags |= IMA_DIGSIG_REQUIRED;
|
||||||
|
else
|
||||||
|
result = -EINVAL;
|
||||||
|
break;
|
||||||
case Opt_err:
|
case Opt_err:
|
||||||
ima_log_string(ab, "UNKNOWN", p);
|
ima_log_string(ab, "UNKNOWN", p);
|
||||||
result = -EINVAL;
|
result = -EINVAL;
|
||||||
|
|
|
@ -26,7 +26,9 @@
|
||||||
#define IMA_AUDITED 0x0080
|
#define IMA_AUDITED 0x0080
|
||||||
|
|
||||||
/* iint cache flags */
|
/* iint cache flags */
|
||||||
|
#define IMA_ACTION_FLAGS 0xff00
|
||||||
#define IMA_DIGSIG 0x0100
|
#define IMA_DIGSIG 0x0100
|
||||||
|
#define IMA_DIGSIG_REQUIRED 0x0200
|
||||||
|
|
||||||
#define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT)
|
#define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT)
|
||||||
#define IMA_DONE_MASK (IMA_MEASURED | IMA_APPRAISED | IMA_AUDITED \
|
#define IMA_DONE_MASK (IMA_MEASURED | IMA_APPRAISED | IMA_AUDITED \
|
||||||
|
|
Loading…
Reference in a new issue