| From 1e738cfa84db031ca55ea8c779110fb469d785be Mon Sep 17 00:00:00 2001 |
| From: Paul Moore <pmoore@redhat.com> |
| Date: Fri, 17 May 2013 09:08:50 +0000 |
| Subject: netlabel: improve domain mapping validation |
| |
| From: Paul Moore <pmoore@redhat.com> |
| |
| [ Upstream commit 6b21e1b77d1a3d58ebfd513264c885695e8a0ba5 ] |
| |
| The net/netlabel/netlabel_domainhash.c:netlbl_domhsh_add() function |
| does not properly validate new domain hash entries resulting in |
| potential problems when an administrator attempts to add an invalid |
| entry. One such problem, as reported by Vlad Halilov, is a kernel |
| BUG (found in netlabel_domainhash.c:netlbl_domhsh_audit_add()) when |
| adding an IPv6 outbound mapping with a CIPSO configuration. |
| |
| This patch corrects this problem by adding the necessary validation |
| code to netlbl_domhsh_add() via the newly created |
| netlbl_domhsh_validate() function. |
| |
| Ideally this patch should also be pushed to the currently active |
| -stable trees. |
| |
| Reported-by: Vlad Halilov <vlad.halilov@gmail.com> |
| Signed-off-by: Paul Moore <pmoore@redhat.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/netlabel/netlabel_domainhash.c | 69 +++++++++++++++++++++++++++++++++++++ |
| 1 file changed, 69 insertions(+) |
| |
| --- a/net/netlabel/netlabel_domainhash.c |
| +++ b/net/netlabel/netlabel_domainhash.c |
| @@ -245,6 +245,71 @@ static void netlbl_domhsh_audit_add(stru |
| } |
| } |
| |
| +/** |
| + * 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_ |
| 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 |