IMA: add support to restrict the hash algorithms used for file appraisal
[linux-2.6-microblaze.git] / security / integrity / ima / ima_policy.c
index fd5d46e..1536e6f 100644 (file)
@@ -35,6 +35,7 @@
 #define IMA_FSNAME     0x0200
 #define IMA_KEYRINGS   0x0400
 #define IMA_LABEL      0x0800
+#define IMA_VALIDATE_ALGOS     0x1000
 
 #define UNKNOWN                0
 #define MEASURE                0x0001  /* same as IMA_MEASURE */
@@ -79,6 +80,7 @@ struct ima_rule_entry {
        bool (*uid_op)(kuid_t, kuid_t);    /* Handlers for operators       */
        bool (*fowner_op)(kuid_t, kuid_t); /* uid_eq(), uid_gt(), uid_lt() */
        int pcr;
+       unsigned int allowed_algos; /* bitfield of allowed hash algorithms */
        struct {
                void *rule;     /* LSM file metadata specific */
                char *args_p;   /* audit value */
@@ -90,6 +92,14 @@ struct ima_rule_entry {
        struct ima_template_desc *template;
 };
 
+/*
+ * sanity check in case the kernels gains more hash algorithms that can
+ * fit in an unsigned int
+ */
+static_assert(
+       8 * sizeof(unsigned int) >= HASH_ALGO__LAST,
+       "The bitfield allowed_algos in ima_rule_entry is too small to contain all the supported hash algorithms, consider using a bigger type");
+
 /*
  * Without LSM specific knowledge, the default policy can only be
  * written in terms of .action, .func, .mask, .fsmagic, .uid, and .fowner
@@ -646,6 +656,7 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
  * @pcr: set the pcr to extend
  * @template_desc: the template that should be used for this rule
  * @func_data: func specific data, may be NULL
+ * @allowed_algos: allowlist of hash algorithms for the IMA xattr
  *
  * Measure decision based on func/mask/fsmagic and LSM(subj/obj/type)
  * conditions.
@@ -658,7 +669,7 @@ int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
                     const struct cred *cred, u32 secid, enum ima_hooks func,
                     int mask, int flags, int *pcr,
                     struct ima_template_desc **template_desc,
-                    const char *func_data)
+                    const char *func_data, unsigned int *allowed_algos)
 {
        struct ima_rule_entry *entry;
        int action = 0, actmask = flags | (flags << 1);
@@ -684,8 +695,11 @@ int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
                        action &= ~IMA_HASH;
                        if (ima_fail_unverifiable_sigs)
                                action |= IMA_FAIL_UNVERIFIABLE_SIGS;
-               }
 
+                       if (allowed_algos &&
+                           entry->flags & IMA_VALIDATE_ALGOS)
+                               *allowed_algos = entry->allowed_algos;
+               }
 
                if (entry->action & IMA_DO_MASK)
                        actmask &= ~(entry->action | entry->action << 1);