From 13f42a71e49164769a98fc51033c65a211861404 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Thu, 20 Jan 2011 17:54:26 +0100 Subject: Enforce network-order data in the netlink protocol Allow only network-order data, with NLA_F_NET_BYTEORDER flag. Sanity checks also added to prevent processing broken messages where mandatory attributes are missing. (Patrick McHardy's review) --- kernel/include/linux/netfilter/ipset/ip_set.h | 22 ++++++++++---- kernel/ip_set_bitmap_ip.c | 23 ++++++++++---- kernel/ip_set_bitmap_ipmac.c | 15 ++++++++-- kernel/ip_set_bitmap_port.c | 43 +++++++++++++-------------- kernel/ip_set_core.c | 35 ++++++++++------------ kernel/ip_set_hash_ip.c | 19 ++++++++++-- kernel/ip_set_hash_ipport.c | 23 ++++++++++++-- kernel/ip_set_hash_ipportip.c | 27 +++++++++++++---- kernel/ip_set_hash_ipportnet.c | 27 +++++++++++++---- kernel/ip_set_hash_net.c | 17 +++++++++-- kernel/ip_set_hash_netport.c | 21 +++++++++++-- kernel/ip_set_list_set.c | 28 ++++++++++------- 12 files changed, 214 insertions(+), 86 deletions(-) diff --git a/kernel/include/linux/netfilter/ipset/ip_set.h b/kernel/include/linux/netfilter/ipset/ip_set.h index 7679b33..61b08f1 100644 --- a/kernel/include/linux/netfilter/ipset/ip_set.h +++ b/kernel/include/linux/netfilter/ipset/ip_set.h @@ -320,15 +320,14 @@ extern int ip_set_test(ip_set_id_t id, const struct sk_buff *skb, /* Utility functions */ extern void * ip_set_alloc(size_t size, gfp_t gfp_mask); extern void ip_set_free(void *members); -extern int ip_set_get_ipaddr4(struct nlattr *attr[], int type, __be32 *ipaddr); -extern int ip_set_get_ipaddr6(struct nlattr *attr[], int type, - union nf_inet_addr *ipaddr); +extern int ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr); +extern int ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr); static inline int -ip_set_get_hostipaddr4(struct nlattr *attr[], int type, u32 *ipaddr) +ip_set_get_hostipaddr4(struct nlattr *nla, u32 *ipaddr) { __be32 ip; - int ret = ip_set_get_ipaddr4(attr, type, &ip); + int ret = ip_set_get_ipaddr4(nla, &ip); if (ret) return ret; @@ -343,6 +342,19 @@ ip_set_eexist(int ret, u32 flags) return ret == -IPSET_ERR_EXIST && (flags & IPSET_FLAG_EXIST); } +/* Check the NLA_F_NET_BYTEORDER flag */ +static inline bool +ip_set_attr_netorder(struct nlattr *tb[], int type) +{ + return tb[type] && (tb[type]->nla_type & NLA_F_NET_BYTEORDER); +} + +static inline bool +ip_set_optattr_netorder(struct nlattr *tb[], int type) +{ + return !tb[type] || (tb[type]->nla_type & NLA_F_NET_BYTEORDER); +} + /* Useful converters */ static inline u32 ip_set_get_h32(const struct nlattr *attr) diff --git a/kernel/ip_set_bitmap_ip.c b/kernel/ip_set_bitmap_ip.c index 7806ecc..30db991 100644 --- a/kernel/ip_set_bitmap_ip.c +++ b/kernel/ip_set_bitmap_ip.c @@ -121,10 +121,13 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *head, int len, bitmap_ip_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP])) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_hostipaddr4(tb, IPSET_ATTR_IP, &ip); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip); if (ret) return ret; @@ -140,7 +143,7 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *head, int len, return bitmap_ip_test(map, ip_to_id(map, ip)); if (tb[IPSET_ATTR_IP_TO]) { - ret = ip_set_get_hostipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); if (ret) return ret; if (ip > ip_to) { @@ -359,10 +362,14 @@ bitmap_ip_timeout_uadt(struct ip_set *set, struct nlattr *head, int len, bitmap_ip_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_hostipaddr4(tb, IPSET_ATTR_IP, &ip); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip); if (ret) return ret; @@ -374,7 +381,7 @@ bitmap_ip_timeout_uadt(struct ip_set *set, struct nlattr *head, int len, ip_to_id((const struct bitmap_ip *)map, ip)); if (tb[IPSET_ATTR_IP_TO]) { - ret = ip_set_get_hostipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); if (ret) return ret; if (ip > ip_to) { @@ -598,12 +605,16 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *head, int len, bitmap_ip_create_policy)) return -IPSET_ERR_PROTOCOL; - ret = ip_set_get_hostipaddr4(tb, IPSET_ATTR_IP, &first_ip); + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip); if (ret) return ret; if (tb[IPSET_ATTR_IP_TO]) { - ret = ip_set_get_hostipaddr4(tb, IPSET_ATTR_IP_TO, &last_ip); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip); if (ret) return ret; if (first_ip > last_ip) { diff --git a/kernel/ip_set_bitmap_ipmac.c b/kernel/ip_set_bitmap_ipmac.c index 49e7ed1..87870a3 100644 --- a/kernel/ip_set_bitmap_ipmac.c +++ b/kernel/ip_set_bitmap_ipmac.c @@ -380,10 +380,14 @@ bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *head, int len, bitmap_ipmac_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_hostipaddr4(tb, IPSET_ATTR_IP, &data.id); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &data.id); if (ret) return ret; @@ -538,6 +542,7 @@ static const struct nla_policy bitmap_ipmac_create_policy[IPSET_ATTR_CREATE_MAX+1] = { [IPSET_ATTR_IP] = { .type = NLA_NESTED }, [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, + [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, }; @@ -572,12 +577,16 @@ bitmap_ipmac_create(struct ip_set *set, struct nlattr *head, int len, bitmap_ipmac_create_policy)) return -IPSET_ERR_PROTOCOL; - ret = ip_set_get_hostipaddr4(tb, IPSET_ATTR_IP, &first_ip); + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip); if (ret) return ret; if (tb[IPSET_ATTR_IP_TO]) { - ret = ip_set_get_hostipaddr4(tb, IPSET_ATTR_IP_TO, &last_ip); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip); if (ret) return ret; if (first_ip > last_ip) { diff --git a/kernel/ip_set_bitmap_port.c b/kernel/ip_set_bitmap_port.c index dfece55..17303c6 100644 --- a/kernel/ip_set_bitmap_port.c +++ b/kernel/ip_set_bitmap_port.c @@ -116,14 +116,14 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *head, int len, bitmap_port_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - if (tb[IPSET_ATTR_PORT]) - port = ip_set_get_h16(tb[IPSET_ATTR_PORT]); - else - return -IPSET_ERR_PROTOCOL; - + port = ip_set_get_h16(tb[IPSET_ATTR_PORT]); if (port < map->first_port || port > map->last_port) return -IPSET_ERR_BITMAP_RANGE; @@ -347,14 +347,15 @@ bitmap_port_timeout_uadt(struct ip_set *set, struct nlattr *head, int len, bitmap_port_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - if (tb[IPSET_ATTR_PORT]) - port = ip_set_get_h16(tb[IPSET_ATTR_PORT]); - else - return -IPSET_ERR_PROTOCOL; - + port = ip_set_get_h16(tb[IPSET_ATTR_PORT]); if (port < map->first_port || port > map->last_port) return -IPSET_ERR_BITMAP_RANGE; @@ -568,21 +569,19 @@ bitmap_port_create(struct ip_set *set, struct nlattr *head, int len, bitmap_port_create_policy)) return -IPSET_ERR_PROTOCOL; - if (tb[IPSET_ATTR_PORT]) - first_port = ip_set_get_h16(tb[IPSET_ATTR_PORT]); - else + if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT_TO) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) return -IPSET_ERR_PROTOCOL; - if (tb[IPSET_ATTR_PORT_TO]) { - last_port = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); - if (first_port > last_port) { - u16 tmp = first_port; + first_port = ip_set_get_h16(tb[IPSET_ATTR_PORT]); + last_port = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); + if (first_port > last_port) { + u16 tmp = first_port; - first_port = last_port; - last_port = tmp; - } - } else - return -IPSET_ERR_PROTOCOL; + first_port = last_port; + last_port = tmp; + } if (tb[IPSET_ATTR_TIMEOUT]) { struct bitmap_port_timeout *map; diff --git a/kernel/ip_set_core.c b/kernel/ip_set_core.c index e449740..ba2f890 100644 --- a/kernel/ip_set_core.c +++ b/kernel/ip_set_core.c @@ -209,6 +209,12 @@ ip_set_free(void *members) } EXPORT_SYMBOL_GPL(ip_set_free); +static inline bool +flag_nested(const struct nlattr *nla) +{ + return nla->nla_type & NLA_F_NESTED; +} + static const struct nla_policy ipaddr_policy[IPSET_ATTR_IPADDR_MAX + 1] = { [IPSET_ATTR_IPADDR_IPV4] = { .type = NLA_U32 }, [IPSET_ATTR_IPADDR_IPV6] = { .type = NLA_BINARY, @@ -216,19 +222,17 @@ static const struct nla_policy ipaddr_policy[IPSET_ATTR_IPADDR_MAX + 1] = { }; int -ip_set_get_ipaddr4(struct nlattr *attr[], int type, __be32 *ipaddr) +ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr) { struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1]; - if (!attr[type]) + if (unlikely(!flag_nested(nla))) return -IPSET_ERR_PROTOCOL; - - if (nla_parse(tb, IPSET_ATTR_IPADDR_MAX, - nla_data(attr[type]), nla_len(attr[type]), + if (nla_parse(tb, IPSET_ATTR_IPADDR_MAX, nla_data(nla), nla_len(nla), ipaddr_policy)) return -IPSET_ERR_PROTOCOL; - if (!tb[IPSET_ATTR_IPADDR_IPV4]) - return -IPSET_ERR_IPADDR_IPV4; + if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV4))) + return -IPSET_ERR_PROTOCOL; *ipaddr = nla_get_be32(tb[IPSET_ATTR_IPADDR_IPV4]); return 0; @@ -236,19 +240,18 @@ ip_set_get_ipaddr4(struct nlattr *attr[], int type, __be32 *ipaddr) EXPORT_SYMBOL_GPL(ip_set_get_ipaddr4); int -ip_set_get_ipaddr6(struct nlattr *attr[], int type, union nf_inet_addr *ipaddr) +ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr) { struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1]; - if (!attr[type]) + if (unlikely(!flag_nested(nla))) return -IPSET_ERR_PROTOCOL; - if (nla_parse(tb, IPSET_ATTR_IPADDR_MAX, - nla_data(attr[type]), nla_len(attr[type]), + if (nla_parse(tb, IPSET_ATTR_IPADDR_MAX, nla_data(nla), nla_len(nla), ipaddr_policy)) return -IPSET_ERR_PROTOCOL; - if (!tb[IPSET_ATTR_IPADDR_IPV6]) - return -IPSET_ERR_IPADDR_IPV6; + if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV6))) + return -IPSET_ERR_PROTOCOL; memcpy(ipaddr, nla_data(tb[IPSET_ATTR_IPADDR_IPV6]), sizeof(struct in6_addr)); @@ -511,12 +514,6 @@ flag_exist(const struct nlmsghdr *nlh) return nlh->nlmsg_flags & NLM_F_EXCL ? 0 : IPSET_FLAG_EXIST; } -static inline bool -flag_nested(const struct nlattr *nla) -{ - return nla->nla_type & NLA_F_NESTED; -} - static struct nlmsghdr * start_msg(struct sk_buff *skb, u32 pid, u32 seq, unsigned int flags, enum ipset_cmd cmd) diff --git a/kernel/ip_set_hash_ip.c b/kernel/ip_set_hash_ip.c index e8ae8a5..21ace91 100644 --- a/kernel/ip_set_hash_ip.c +++ b/kernel/ip_set_hash_ip.c @@ -156,10 +156,14 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *head, int len, hash_ip4_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_hostipaddr4(tb, IPSET_ATTR_IP, &ip); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip); if (ret) return ret; @@ -179,7 +183,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *head, int len, } if (tb[IPSET_ATTR_IP_TO]) { - ret = ip_set_get_hostipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); if (ret) return ret; if (ip > ip_to) @@ -346,10 +350,14 @@ hash_ip6_uadt(struct ip_set *set, struct nlattr *head, int len, hash_ip6_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &ip); + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &ip); if (ret) return ret; @@ -398,6 +406,11 @@ hash_ip_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) hash_ip_create_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_HASHSIZE]) { hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]); if (hashsize < IPSET_MIMINAL_HASHSIZE) diff --git a/kernel/ip_set_hash_ipport.c b/kernel/ip_set_hash_ipport.c index 4bc1f42..dd92563 100644 --- a/kernel/ip_set_hash_ipport.c +++ b/kernel/ip_set_hash_ipport.c @@ -181,10 +181,16 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *head, int len, hash_ipport_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip); + ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip); if (ret) return ret; @@ -227,7 +233,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *head, int len, ip = ntohl(data.ip); if (tb[IPSET_ATTR_IP_TO]) { - ret = ip_set_get_hostipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); if (ret) return ret; if (ip > ip_to) @@ -402,10 +408,16 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *head, int len, hash_ipport_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip); + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip); if (ret) return ret; @@ -489,6 +501,11 @@ hash_ipport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) hash_ipport_create_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_HASHSIZE]) { hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]); if (hashsize < IPSET_MIMINAL_HASHSIZE) diff --git a/kernel/ip_set_hash_ipportip.c b/kernel/ip_set_hash_ipportip.c index 734529c..04cd079 100644 --- a/kernel/ip_set_hash_ipportip.c +++ b/kernel/ip_set_hash_ipportip.c @@ -188,14 +188,20 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *head, int len, hash_ipportip_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip); + ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip); if (ret) return ret; - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP2, &data.ip2); + ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &data.ip2); if (ret) return ret; @@ -238,7 +244,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *head, int len, ip = ntohl(data.ip); if (tb[IPSET_ATTR_IP_TO]) { - ret = ip_set_get_hostipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); if (ret) return ret; if (ip > ip_to) @@ -419,14 +425,20 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *head, int len, hash_ipportip_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip); + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip); if (ret) return ret; - ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP2, &data.ip2); + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2); if (ret) return ret; @@ -510,6 +522,11 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *head, hash_ipportip_create_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_HASHSIZE]) { hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]); if (hashsize < IPSET_MIMINAL_HASHSIZE) diff --git a/kernel/ip_set_hash_ipportnet.c b/kernel/ip_set_hash_ipportnet.c index b6bc5c9..2b06d51 100644 --- a/kernel/ip_set_hash_ipportnet.c +++ b/kernel/ip_set_hash_ipportnet.c @@ -209,14 +209,20 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *head, int len, hash_ipportnet_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip); + ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip); if (ret) return ret; - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP2, &data.ip2); + ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &data.ip2); if (ret) return ret; @@ -267,7 +273,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *head, int len, ip = ntohl(data.ip); if (tb[IPSET_ATTR_IP_TO]) { - ret = ip_set_get_hostipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to); + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); if (ret) return ret; if (ip > ip_to) @@ -474,14 +480,20 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *head, int len, hash_ipportnet_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip); + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip); if (ret) return ret; - ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP2, &data.ip2); + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2); if (ret) return ret; @@ -573,6 +585,11 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *head, hash_ipportnet_create_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_HASHSIZE]) { hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]); if (hashsize < IPSET_MIMINAL_HASHSIZE) diff --git a/kernel/ip_set_hash_net.c b/kernel/ip_set_hash_net.c index 61c4b4f..175c621 100644 --- a/kernel/ip_set_hash_net.c +++ b/kernel/ip_set_hash_net.c @@ -176,10 +176,14 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *head, int len, hash_net_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip); + ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip); if (ret) return ret; @@ -352,10 +356,14 @@ hash_net6_uadt(struct ip_set *set, struct nlattr *head, int len, hash_net_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip); + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip); if (ret) return ret; @@ -404,6 +412,11 @@ hash_net_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) hash_net_create_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_HASHSIZE]) { hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]); if (hashsize < IPSET_MIMINAL_HASHSIZE) diff --git a/kernel/ip_set_hash_netport.c b/kernel/ip_set_hash_netport.c index ca17f1c..72ca57e 100644 --- a/kernel/ip_set_hash_netport.c +++ b/kernel/ip_set_hash_netport.c @@ -201,10 +201,16 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *head, int len, hash_netport_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip); + ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip); if (ret) return ret; @@ -431,10 +437,16 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *head, int len, hash_netport_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip); + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip); if (ret) return ret; @@ -524,6 +536,11 @@ hash_netport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) hash_netport_create_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_HASHSIZE]) { hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]); if (hashsize < IPSET_MIMINAL_HASHSIZE) diff --git a/kernel/ip_set_list_set.c b/kernel/ip_set_list_set.c index 3525e3b..9cae5d7 100644 --- a/kernel/ip_set_list_set.c +++ b/kernel/ip_set_list_set.c @@ -222,20 +222,22 @@ list_set_uadt(struct ip_set *set, struct nlattr *head, int len, list_set_adt_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!tb[IPSET_ATTR_NAME] || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_LINENO]) *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - if (tb[IPSET_ATTR_NAME]) { - id = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAME]), &s); - if (id == IPSET_INVALID_ID) - return -IPSET_ERR_NAME; - /* "Loop detection" */ - if (s->type->features & IPSET_TYPE_NAME) { - ret = -IPSET_ERR_LOOP; - goto finish; - } - } else - return -IPSET_ERR_PROTOCOL; + id = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAME]), &s); + if (id == IPSET_INVALID_ID) + return -IPSET_ERR_NAME; + /* "Loop detection" */ + if (s->type->features & IPSET_TYPE_NAME) { + ret = -IPSET_ERR_LOOP; + goto finish; + } if (tb[IPSET_ATTR_CADT_FLAGS]) { u32 f = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); @@ -541,6 +543,10 @@ list_set_create(struct ip_set *set, struct nlattr *head, int len, list_set_create_policy)) return -IPSET_ERR_PROTOCOL; + if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_SIZE) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + return -IPSET_ERR_PROTOCOL; + if (tb[IPSET_ATTR_SIZE]) size = ip_set_get_h32(tb[IPSET_ATTR_SIZE]); if (size < IP_SET_LIST_MIN_SIZE) -- cgit v1.2.3