Commit e7c568e0 authored by Peter Moody's avatar Peter Moody Committed by Mimi Zohar

ima: audit log hashes

This adds an 'audit' policy action which audit logs file measurements.

Changelog v6:
 - use new action flag handling (Dmitry Kasatkin).
 - removed whitespace (Mimi)

Changelog v5:
 - use audit_log_untrustedstring.

Changelog v4:
 - cleanup digest -> hash conversion.
 - use filename rather than d_path in ima_audit_measurement.

Changelog v3:
 - Use newly exported audit_log_task_info for logging pid/ppid/uid/etc.
 - Update the ima_policy ABI documentation.

Changelog v2:
 - Use 'audit' action rather than 'measure_and_audit' to permit
 auditing in the absence of measuring..

Changelog v1:
 - Initial posting.
Signed-off-by: default avatarPeter Moody <pmoody@google.com>
Signed-off-by: default avatarMimi Zohar <zohar@linux.vnet.ibm.com>
parent 45e2472e
...@@ -17,7 +17,7 @@ Description: ...@@ -17,7 +17,7 @@ Description:
rule format: action [condition ...] rule format: action [condition ...]
action: measure | dont_measure | appraise | dont_appraise action: measure | dont_measure | appraise | dont_appraise | audit
condition:= base | lsm condition:= base | lsm
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=]
......
...@@ -114,6 +114,8 @@ int ima_collect_measurement(struct integrity_iint_cache *iint, ...@@ -114,6 +114,8 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
struct file *file); struct file *file);
void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
const unsigned char *filename); const unsigned char *filename);
void ima_audit_measurement(struct integrity_iint_cache *iint,
const unsigned char *filename);
int ima_store_template(struct ima_template_entry *entry, int violation, int ima_store_template(struct ima_template_entry *entry, int violation,
struct inode *inode); struct inode *inode);
void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show); void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show);
......
...@@ -114,7 +114,7 @@ void ima_add_violation(struct inode *inode, const unsigned char *filename, ...@@ -114,7 +114,7 @@ void ima_add_violation(struct inode *inode, const unsigned char *filename,
*/ */
int ima_get_action(struct inode *inode, int mask, int function) int ima_get_action(struct inode *inode, int mask, int function)
{ {
int flags = IMA_MEASURE | IMA_APPRAISE; int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE;
if (!ima_appraise) if (!ima_appraise)
flags &= ~IMA_APPRAISE; flags &= ~IMA_APPRAISE;
...@@ -207,3 +207,33 @@ void ima_store_measurement(struct integrity_iint_cache *iint, ...@@ -207,3 +207,33 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
if (result < 0) if (result < 0)
kfree(entry); kfree(entry);
} }
void ima_audit_measurement(struct integrity_iint_cache *iint,
const unsigned char *filename)
{
struct audit_buffer *ab;
char hash[(IMA_DIGEST_SIZE * 2) + 1];
int i;
if (iint->flags & IMA_AUDITED)
return;
for (i = 0; i < IMA_DIGEST_SIZE; i++)
hex_byte_pack(hash + (i * 2), iint->ima_xattr.digest[i]);
hash[i * 2] = '\0';
ab = audit_log_start(current->audit_context, GFP_KERNEL,
AUDIT_INTEGRITY_RULE);
if (!ab)
return;
audit_log_format(ab, "file=");
audit_log_untrustedstring(ab, filename);
audit_log_format(ab, " hash=");
audit_log_untrustedstring(ab, hash);
audit_log_task_info(ab, current);
audit_log_end(ab);
iint->flags |= IMA_AUDITED;
}
...@@ -156,8 +156,8 @@ static int process_measurement(struct file *file, const unsigned char *filename, ...@@ -156,8 +156,8 @@ static int process_measurement(struct file *file, const unsigned char *filename,
if (!ima_initialized || !S_ISREG(inode->i_mode)) if (!ima_initialized || !S_ISREG(inode->i_mode))
return 0; return 0;
/* Determine if in appraise/measurement policy, /* Determine if in appraise/audit/measurement policy,
* returns IMA_MEASURE, IMA_APPRAISE bitmask. */ * returns IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT bitmask. */
action = ima_get_action(inode, mask, function); action = ima_get_action(inode, mask, function);
if (!action) if (!action)
return 0; return 0;
...@@ -171,7 +171,8 @@ static int process_measurement(struct file *file, const unsigned char *filename, ...@@ -171,7 +171,8 @@ static int process_measurement(struct file *file, const unsigned char *filename,
goto out; goto out;
/* Determine if already appraised/measured based on bitmask /* Determine if already appraised/measured based on bitmask
* (IMA_MEASURE, IMA_MEASURED, IMA_APPRAISE, IMA_APPRAISED) */ * (IMA_MEASURE, IMA_MEASURED, IMA_APPRAISE, IMA_APPRAISED,
* IMA_AUDIT, IMA_AUDITED) */
iint->flags |= action; iint->flags |= action;
action &= ~((iint->flags & IMA_DONE_MASK) >> 1); action &= ~((iint->flags & IMA_DONE_MASK) >> 1);
...@@ -202,6 +203,8 @@ static int process_measurement(struct file *file, const unsigned char *filename, ...@@ -202,6 +203,8 @@ static int process_measurement(struct file *file, const unsigned char *filename,
if (action & IMA_APPRAISE) if (action & IMA_APPRAISE)
rc = ima_appraise_measurement(iint, file, rc = ima_appraise_measurement(iint, file,
!pathname ? filename : pathname); !pathname ? filename : pathname);
if (action & IMA_AUDIT)
ima_audit_measurement(iint, !pathname ? filename : pathname);
kfree(pathbuf); kfree(pathbuf);
out: out:
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#define DONT_MEASURE 0x0002 #define DONT_MEASURE 0x0002
#define APPRAISE 0x0004 /* same as IMA_APPRAISE */ #define APPRAISE 0x0004 /* same as IMA_APPRAISE */
#define DONT_APPRAISE 0x0008 #define DONT_APPRAISE 0x0008
#define AUDIT 0x0040
#define MAX_LSM_RULES 6 #define MAX_LSM_RULES 6
enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE, enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
...@@ -277,6 +278,7 @@ enum { ...@@ -277,6 +278,7 @@ enum {
Opt_err = -1, Opt_err = -1,
Opt_measure = 1, Opt_dont_measure, Opt_measure = 1, Opt_dont_measure,
Opt_appraise, Opt_dont_appraise, Opt_appraise, Opt_dont_appraise,
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
...@@ -287,6 +289,7 @@ static match_table_t policy_tokens = { ...@@ -287,6 +289,7 @@ static match_table_t policy_tokens = {
{Opt_dont_measure, "dont_measure"}, {Opt_dont_measure, "dont_measure"},
{Opt_appraise, "appraise"}, {Opt_appraise, "appraise"},
{Opt_dont_appraise, "dont_appraise"}, {Opt_dont_appraise, "dont_appraise"},
{Opt_audit, "audit"},
{Opt_obj_user, "obj_user=%s"}, {Opt_obj_user, "obj_user=%s"},
{Opt_obj_role, "obj_role=%s"}, {Opt_obj_role, "obj_role=%s"},
{Opt_obj_type, "obj_type=%s"}, {Opt_obj_type, "obj_type=%s"},
...@@ -379,6 +382,14 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) ...@@ -379,6 +382,14 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
entry->action = DONT_APPRAISE; entry->action = DONT_APPRAISE;
break; break;
case Opt_audit:
ima_log_string(ab, "action", "audit");
if (entry->action != UNKNOWN)
result = -EINVAL;
entry->action = AUDIT;
break;
case Opt_func: case Opt_func:
ima_log_string(ab, "func", args[0].from); ima_log_string(ab, "func", args[0].from);
......
...@@ -22,12 +22,15 @@ ...@@ -22,12 +22,15 @@
#define IMA_APPRAISED 0x0008 #define IMA_APPRAISED 0x0008
/*#define IMA_COLLECT 0x0010 do not use this flag */ /*#define IMA_COLLECT 0x0010 do not use this flag */
#define IMA_COLLECTED 0x0020 #define IMA_COLLECTED 0x0020
#define IMA_AUDIT 0x0040
#define IMA_AUDITED 0x0080
/* iint cache flags */ /* iint cache flags */
#define IMA_DIGSIG 0x0100 #define IMA_DIGSIG 0x0100
#define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE) #define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT)
#define IMA_DONE_MASK (IMA_MEASURED | IMA_APPRAISED | IMA_COLLECTED) #define IMA_DONE_MASK (IMA_MEASURED | IMA_APPRAISED | IMA_AUDITED \
| IMA_COLLECTED)
enum evm_ima_xattr_type { enum evm_ima_xattr_type {
IMA_XATTR_DIGEST = 0x01, IMA_XATTR_DIGEST = 0x01,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment