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: Peter Moody <pmoody@google.com> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
This commit is contained in:
parent
45e2472e67
commit
e7c568e0fd
|
@ -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,
|
||||||
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 @@ err_out:
|
||||||
*/
|
*/
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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 @@
|
||||||
#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 {
|
||||||
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 = {
|
||||||
{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)
|
||||||
|
|
||||||
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 @@
|
||||||
#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,
|
||||||
|
|
Reference in New Issue