ipv6: xfrm: Handle errors reported by xfrm6_find_1stfragopt()
[pandora-kernel.git] / net / netlabel / netlabel_domainhash.c
index 7d8083c..bf99567 100644 (file)
@@ -245,6 +245,71 @@ static void netlbl_domhsh_audit_add(struct netlbl_dom_map *entry,
        }
 }
 
+/**
+ * netlbl_domhsh_validate - Validate a new domain mapping entry
+ * @entry: the entry to validate
+ *
+ * This function validates the new domain mapping entry to ensure that it is
+ * a valid entry.  Returns zero on success, negative values on failure.
+ *
+ */
+static int netlbl_domhsh_validate(const struct netlbl_dom_map *entry)
+{
+       struct netlbl_af4list *iter4;
+       struct netlbl_domaddr4_map *map4;
+#if IS_ENABLED(CONFIG_IPV6)
+       struct netlbl_af6list *iter6;
+       struct netlbl_domaddr6_map *map6;
+#endif /* IPv6 */
+
+       if (entry == NULL)
+               return -EINVAL;
+
+       switch (entry->type) {
+       case NETLBL_NLTYPE_UNLABELED:
+               if (entry->type_def.cipsov4 != NULL ||
+                   entry->type_def.addrsel != NULL)
+                       return -EINVAL;
+               break;
+       case NETLBL_NLTYPE_CIPSOV4:
+               if (entry->type_def.cipsov4 == NULL)
+                       return -EINVAL;
+               break;
+       case NETLBL_NLTYPE_ADDRSELECT:
+               netlbl_af4list_foreach(iter4, &entry->type_def.addrsel->list4) {
+                       map4 = netlbl_domhsh_addr4_entry(iter4);
+                       switch (map4->type) {
+                       case NETLBL_NLTYPE_UNLABELED:
+                               if (map4->type_def.cipsov4 != NULL)
+                                       return -EINVAL;
+                               break;
+                       case NETLBL_NLTYPE_CIPSOV4:
+                               if (map4->type_def.cipsov4 == NULL)
+                                       return -EINVAL;
+                               break;
+                       default:
+                               return -EINVAL;
+                       }
+               }
+#if IS_ENABLED(CONFIG_IPV6)
+               netlbl_af6list_foreach(iter6, &entry->type_def.addrsel->list6) {
+                       map6 = netlbl_domhsh_addr6_entry(iter6);
+                       switch (map6->type) {
+                       case NETLBL_NLTYPE_UNLABELED:
+                               break;
+                       default:
+                               return -EINVAL;
+                       }
+               }
+#endif /* IPv6 */
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 /*
  * Domain Hash Table Functions
  */
@@ -311,6 +376,10 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry,
        struct netlbl_af6list *tmp6;
 #endif /* IPv6 */
 
+       ret_val = netlbl_domhsh_validate(entry);
+       if (ret_val != 0)
+               return ret_val;
+
        /* XXX - we can remove this RCU read lock as the spinlock protects the
         *       entire function, but before we do we need to fixup the
         *       netlbl_af[4,6]list RCU functions to do "the right thing" with
@@ -451,7 +520,7 @@ int netlbl_domhsh_remove_entry(struct netlbl_dom_map *entry,
                if (entry != rcu_dereference(netlbl_domhsh_def))
                        list_del_rcu(&entry->list);
                else
-                       rcu_assign_pointer(netlbl_domhsh_def, NULL);
+                       RCU_INIT_POINTER(netlbl_domhsh_def, NULL);
        } else
                ret_val = -ENOENT;
        spin_unlock(&netlbl_domhsh_lock);