rule format: action [condition ...]
- action: measure | dont_measure | appraise | dont_appraise | audit
+ action: measure | dont_measure | appraise | dont_appraise |
+ audit | hash | dont_hash
condition:= base | lsm [option]
base: [[func=] [mask=] [fsmagic=] [fsuuid=] [uid=]
[euid=] [fowner=]]
*/
int ima_get_action(struct inode *inode, int mask, enum ima_hooks func, int *pcr)
{
- int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE;
+ int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH;
flags &= ima_policy_flag;
/*
* ima_must_appraise - set appraise flag
*
- * Return 1 to appraise
+ * Return 1 to appraise or hash
*/
int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func)
{
if (!ima_appraise)
return 0;
- return ima_match_policy(inode, func, mask, IMA_APPRAISE, NULL);
+ return ima_match_policy(inode, func, mask, IMA_APPRAISE | IMA_HASH,
+ NULL);
}
static int ima_fix_xattr(struct dentry *dentry,
if (test_bit(IMA_DIGSIG, &iint->atomic_flags))
return;
- if (iint->ima_file_status != INTEGRITY_PASS)
+ if ((iint->ima_file_status != INTEGRITY_PASS) &&
+ !(iint->flags & IMA_HASH))
return;
rc = ima_collect_measurement(iint, file, NULL, 0, ima_hash_algo);
{
struct inode *inode = d_backing_inode(dentry);
struct integrity_iint_cache *iint;
- int must_appraise;
+ int action;
if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)
|| !(inode->i_opflags & IOP_XATTR))
return;
- must_appraise = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR);
- if (!must_appraise)
+ action = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR);
+ if (!action)
__vfs_removexattr(dentry, XATTR_NAME_IMA);
iint = integrity_iint_find(inode);
if (iint) {
set_bit(IMA_CHANGE_ATTR, &iint->atomic_flags);
- if (!must_appraise)
+ if (!action)
clear_bit(IMA_UPDATE_XATTR, &iint->atomic_flags);
}
}
if ((action & IMA_MEASURE) && (iint->measured_pcrs & (0x1 << pcr)))
action ^= IMA_MEASURE;
+ /* HASH sets the digital signature and update flags, nothing else */
+ if ((action & IMA_HASH) &&
+ !(test_bit(IMA_DIGSIG, &iint->atomic_flags))) {
+ xattr_len = ima_read_xattr(file_dentry(file), &xattr_value);
+ if ((xattr_value && xattr_len > 2) &&
+ (xattr_value->type == EVM_IMA_XATTR_DIGSIG))
+ set_bit(IMA_DIGSIG, &iint->atomic_flags);
+ iint->flags |= IMA_HASHED;
+ action ^= IMA_HASH;
+ set_bit(IMA_UPDATE_XATTR, &iint->atomic_flags);
+ }
+
/* Nothing to do, just return existing appraised status */
if (!action) {
if (must_appraise)
#define APPRAISE 0x0004 /* same as IMA_APPRAISE */
#define DONT_APPRAISE 0x0008
#define AUDIT 0x0040
+#define HASH 0x0100
+#define DONT_HASH 0x0200
#define INVALID_PCR(a) (((a) < 0) || \
(a) >= (FIELD_SIZEOF(struct integrity_iint_cache, measured_pcrs) * 8))
action |= entry->flags & IMA_ACTION_FLAGS;
action |= entry->action & IMA_DO_MASK;
- if (entry->action & IMA_APPRAISE)
+ if (entry->action & IMA_APPRAISE) {
action |= get_subaction(entry, func);
+ action ^= IMA_HASH;
+ }
if (entry->action & IMA_DO_MASK)
actmask &= ~(entry->action | entry->action << 1);
Opt_err = -1,
Opt_measure = 1, Opt_dont_measure,
Opt_appraise, Opt_dont_appraise,
- Opt_audit,
+ Opt_audit, Opt_hash, Opt_dont_hash,
Opt_obj_user, Opt_obj_role, Opt_obj_type,
Opt_subj_user, Opt_subj_role, Opt_subj_type,
Opt_func, Opt_mask, Opt_fsmagic,
{Opt_appraise, "appraise"},
{Opt_dont_appraise, "dont_appraise"},
{Opt_audit, "audit"},
+ {Opt_hash, "hash"},
+ {Opt_dont_hash, "dont_hash"},
{Opt_obj_user, "obj_user=%s"},
{Opt_obj_role, "obj_role=%s"},
{Opt_obj_type, "obj_type=%s"},
entry->action = AUDIT;
break;
+ case Opt_hash:
+ ima_log_string(ab, "action", "hash");
+
+ if (entry->action != UNKNOWN)
+ result = -EINVAL;
+
+ entry->action = HASH;
+ break;
+ case Opt_dont_hash:
+ ima_log_string(ab, "action", "dont_hash");
+
+ if (entry->action != UNKNOWN)
+ result = -EINVAL;
+
+ entry->action = DONT_HASH;
+ break;
case Opt_func:
ima_log_string(ab, "func", args[0].from);
seq_puts(m, pt(Opt_dont_appraise));
if (entry->action & AUDIT)
seq_puts(m, pt(Opt_audit));
+ if (entry->action & HASH)
+ seq_puts(m, pt(Opt_hash));
+ if (entry->action & DONT_HASH)
+ seq_puts(m, pt(Opt_dont_hash));
seq_puts(m, " ");
#define IMA_COLLECTED 0x00000020
#define IMA_AUDIT 0x00000040
#define IMA_AUDITED 0x00000080
+#define IMA_HASH 0x00000100
+#define IMA_HASHED 0x00000200
/* iint cache flags */
#define IMA_ACTION_FLAGS 0xff000000
#define EVM_IMMUTABLE_DIGSIG 0x08000000
#define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \
- IMA_APPRAISE_SUBMASK)
+ IMA_HASH | IMA_APPRAISE_SUBMASK)
#define IMA_DONE_MASK (IMA_MEASURED | IMA_APPRAISED | IMA_AUDITED | \
- IMA_COLLECTED | IMA_APPRAISED_SUBMASK)
+ IMA_HASHED | IMA_COLLECTED | \
+ IMA_APPRAISED_SUBMASK)
/* iint subaction appraise cache flags */
-#define IMA_FILE_APPRAISE 0x00000100
-#define IMA_FILE_APPRAISED 0x00000200
-#define IMA_MMAP_APPRAISE 0x00000400
-#define IMA_MMAP_APPRAISED 0x00000800
-#define IMA_BPRM_APPRAISE 0x00001000
-#define IMA_BPRM_APPRAISED 0x00002000
-#define IMA_READ_APPRAISE 0x00004000
-#define IMA_READ_APPRAISED 0x00008000
+#define IMA_FILE_APPRAISE 0x00001000
+#define IMA_FILE_APPRAISED 0x00002000
+#define IMA_MMAP_APPRAISE 0x00004000
+#define IMA_MMAP_APPRAISED 0x00008000
+#define IMA_BPRM_APPRAISE 0x00010000
+#define IMA_BPRM_APPRAISED 0x00020000
+#define IMA_READ_APPRAISE 0x00040000
+#define IMA_READ_APPRAISED 0x00080000
#define IMA_APPRAISE_SUBMASK (IMA_FILE_APPRAISE | IMA_MMAP_APPRAISE | \
IMA_BPRM_APPRAISE | IMA_READ_APPRAISE)
#define IMA_APPRAISED_SUBMASK (IMA_FILE_APPRAISED | IMA_MMAP_APPRAISED | \