aboutsummaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/integrity/ima/ima.h2
-rw-r--r--security/integrity/ima/ima_api.c32
-rw-r--r--security/integrity/ima/ima_main.c9
-rw-r--r--security/integrity/ima/ima_policy.c11
-rw-r--r--security/integrity/integrity.h7
5 files changed, 55 insertions, 6 deletions
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 48aa0d46d3e..8180adde10b 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -114,6 +114,8 @@ int ima_collect_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);
+void ima_audit_measurement(struct integrity_iint_cache *iint,
+ const unsigned char *filename);
int ima_store_template(struct ima_template_entry *entry, int violation,
struct inode *inode);
void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show);
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index f0d60e754b3..b356884fb3e 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -114,7 +114,7 @@ err_out:
*/
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)
flags &= ~IMA_APPRAISE;
@@ -207,3 +207,33 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
if (result < 0)
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;
+}
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 5da08b75d36..73c9a268253 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -156,8 +156,8 @@ static int process_measurement(struct file *file, const unsigned char *filename,
if (!ima_initialized || !S_ISREG(inode->i_mode))
return 0;
- /* Determine if in appraise/measurement policy,
- * returns IMA_MEASURE, IMA_APPRAISE bitmask. */
+ /* Determine if in appraise/audit/measurement policy,
+ * returns IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT bitmask. */
action = ima_get_action(inode, mask, function);
if (!action)
return 0;
@@ -171,7 +171,8 @@ static int process_measurement(struct file *file, const unsigned char *filename,
goto out;
/* 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;
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)
rc = ima_appraise_measurement(iint, file,
!pathname ? filename : pathname);
+ if (action & IMA_AUDIT)
+ ima_audit_measurement(iint, !pathname ? filename : pathname);
kfree(pathbuf);
out:
mutex_unlock(&inode->i_mutex);
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index f46f685a171..cda903131db 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -31,6 +31,7 @@
#define DONT_MEASURE 0x0002
#define APPRAISE 0x0004 /* same as IMA_APPRAISE */
#define DONT_APPRAISE 0x0008
+#define AUDIT 0x0040
#define MAX_LSM_RULES 6
enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
@@ -277,6 +278,7 @@ enum {
Opt_err = -1,
Opt_measure = 1, Opt_dont_measure,
Opt_appraise, Opt_dont_appraise,
+ Opt_audit,
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_uid, Opt_fowner
@@ -287,6 +289,7 @@ static match_table_t policy_tokens = {
{Opt_dont_measure, "dont_measure"},
{Opt_appraise, "appraise"},
{Opt_dont_appraise, "dont_appraise"},
+ {Opt_audit, "audit"},
{Opt_obj_user, "obj_user=%s"},
{Opt_obj_role, "obj_role=%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;
break;
+ case Opt_audit:
+ ima_log_string(ab, "action", "audit");
+
+ if (entry->action != UNKNOWN)
+ result = -EINVAL;
+
+ entry->action = AUDIT;
+ break;
case Opt_func:
ima_log_string(ab, "func", args[0].from);
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 564ba7db5f6..403ba319a06 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -22,12 +22,15 @@
#define IMA_APPRAISED 0x0008
/*#define IMA_COLLECT 0x0010 do not use this flag */
#define IMA_COLLECTED 0x0020
+#define IMA_AUDIT 0x0040
+#define IMA_AUDITED 0x0080
/* iint cache flags */
#define IMA_DIGSIG 0x0100
-#define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE)
-#define IMA_DONE_MASK (IMA_MEASURED | IMA_APPRAISED | IMA_COLLECTED)
+#define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT)
+#define IMA_DONE_MASK (IMA_MEASURED | IMA_APPRAISED | IMA_AUDITED \
+ | IMA_COLLECTED)
enum evm_ima_xattr_type {
IMA_XATTR_DIGEST = 0x01,