ima: audit log hashes
authorPeter Moody <pmoody@google.com>
Thu, 14 Jun 2012 17:04:36 +0000 (10:04 -0700)
committerMimi Zohar <zohar@linux.vnet.ibm.com>
Thu, 13 Sep 2012 18:48:44 +0000 (14:48 -0400)
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>
Documentation/ABI/testing/ima_policy
security/integrity/ima/ima.h
security/integrity/ima/ima_api.c
security/integrity/ima/ima_main.c
security/integrity/ima/ima_policy.c
security/integrity/integrity.h

index dcff822..9869466 100644 (file)
@@ -17,7 +17,7 @@ Description:
 
                rule format: action [condition ...]
 
-               action: measure | dont_measure | appraise | dont_appraise
+               action: measure | dont_measure | appraise | dont_appraise | audit
                condition:= base | lsm
                        base:   [[func=] [mask=] [fsmagic=] [uid=] [fowner]]
                        lsm:    [[subj_user=] [subj_role=] [subj_type=]
index 48aa0d4..8180add 100644 (file)
@@ -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);
index f0d60e7..b356884 100644 (file)
@@ -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;
+}
index 5da08b7..73c9a26 100644 (file)
@@ -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);
index f46f685..cda9031 100644 (file)
@@ -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);
 
index 564ba7d..403ba31 100644 (file)
 #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,