From 9dcceb1378b6d66633f613805b2d5a22af4d5383 Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Tue, 5 Jun 2018 11:46:13 +0200 Subject: [PATCH 1/4] netfilter: xt_set: Check hook mask correctly Inserting rule before one with SET target we get error with warning in dmesg(1) output: # iptables -A FORWARD -t mangle -j SET --map-set test src --map-prio # iptables -I FORWARD 1 -t mangle -j ACCEPT iptables: Invalid argument. Run `dmesg' for more information. # dmesg |tail -n1 [268578.026643] mapping of prio or/and queue is allowed only from \ OUTPUT/FORWARD/POSTROUTING chains Rather than checking for supported hook bits for SET target check for unsupported one as done in all rest of matches and targets. Signed-off-by: Serhey Popovych Signed-off-by: Jozsef Kadlecsik --- net/netfilter/xt_set.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c index 6f4c5217d8358..07af7dbf7a303 100644 --- a/net/netfilter/xt_set.c +++ b/net/netfilter/xt_set.c @@ -470,7 +470,7 @@ set_target_v3_checkentry(const struct xt_tgchk_param *par) } if (((info->flags & IPSET_FLAG_MAP_SKBPRIO) | (info->flags & IPSET_FLAG_MAP_SKBQUEUE)) && - !(par->hook_mask & (1 << NF_INET_FORWARD | + (par->hook_mask & ~(1 << NF_INET_FORWARD | 1 << NF_INET_LOCAL_OUT | 1 << NF_INET_POST_ROUTING))) { pr_info_ratelimited("mapping of prio or/and queue is allowed only from OUTPUT/FORWARD/POSTROUTING chains\n"); From bd975e691486ba52790ba23cc9b4fecab7bc0d31 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Thu, 31 May 2018 18:45:21 +0200 Subject: [PATCH 2/4] netfilter: ipset: List timing out entries with "timeout 1" instead of zero When listing sets with timeout support, there's a probability that just timing out entries with "0" timeout value is listed/saved. However when restoring the saved list, the zero timeout value means permanent elelements. The new behaviour is that timing out entries are listed with "timeout 1" instead of zero. Fixes netfilter bugzilla #1258. Signed-off-by: Jozsef Kadlecsik --- include/linux/netfilter/ipset/ip_set_timeout.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/include/linux/netfilter/ipset/ip_set_timeout.h b/include/linux/netfilter/ipset/ip_set_timeout.h index bfb3531fd88a4..7ad8ddf9ca8a4 100644 --- a/include/linux/netfilter/ipset/ip_set_timeout.h +++ b/include/linux/netfilter/ipset/ip_set_timeout.h @@ -65,8 +65,14 @@ ip_set_timeout_set(unsigned long *timeout, u32 value) static inline u32 ip_set_timeout_get(const unsigned long *timeout) { - return *timeout == IPSET_ELEM_PERMANENT ? 0 : - jiffies_to_msecs(*timeout - jiffies)/MSEC_PER_SEC; + u32 t; + + if (*timeout == IPSET_ELEM_PERMANENT) + return 0; + + t = jiffies_to_msecs(*timeout - jiffies)/MSEC_PER_SEC; + /* Zero value in userspace means no timeout */ + return t == 0 ? 1 : t; } #endif /* __KERNEL__ */ From 30a2e107108c66cbcb7776b58cbcd7db223a1cc9 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Tue, 5 Jun 2018 11:53:35 +0200 Subject: [PATCH 3/4] netfilter: ipset: Limit max timeout value Due to the negative value condition in msecs_to_jiffies(), the real max possible timeout value must be set to (UINT_MAX >> 1)/MSEC_PER_SEC. Neutron Soutmun proposed the proper fix, but an insufficient one was applied, see https://patchwork.ozlabs.org/patch/400405/. Signed-off-by: Jozsef Kadlecsik --- include/linux/netfilter/ipset/ip_set_timeout.h | 10 ++++++---- net/netfilter/xt_set.c | 8 ++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/include/linux/netfilter/ipset/ip_set_timeout.h b/include/linux/netfilter/ipset/ip_set_timeout.h index 7ad8ddf9ca8a4..8ce271e187b62 100644 --- a/include/linux/netfilter/ipset/ip_set_timeout.h +++ b/include/linux/netfilter/ipset/ip_set_timeout.h @@ -23,6 +23,9 @@ /* Set is defined with timeout support: timeout value may be 0 */ #define IPSET_NO_TIMEOUT UINT_MAX +/* Max timeout value, see msecs_to_jiffies() in jiffies.h */ +#define IPSET_MAX_TIMEOUT (UINT_MAX >> 1)/MSEC_PER_SEC + #define ip_set_adt_opt_timeout(opt, set) \ ((opt)->ext.timeout != IPSET_NO_TIMEOUT ? (opt)->ext.timeout : (set)->timeout) @@ -32,11 +35,10 @@ ip_set_timeout_uget(struct nlattr *tb) unsigned int timeout = ip_set_get_h32(tb); /* Normalize to fit into jiffies */ - if (timeout > UINT_MAX/MSEC_PER_SEC) - timeout = UINT_MAX/MSEC_PER_SEC; + if (timeout > IPSET_MAX_TIMEOUT) + timeout = IPSET_MAX_TIMEOUT; - /* Userspace supplied TIMEOUT parameter: adjust crazy size */ - return timeout == IPSET_NO_TIMEOUT ? IPSET_NO_TIMEOUT - 1 : timeout; + return timeout; } static inline bool diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c index 07af7dbf7a303..bf2890b132128 100644 --- a/net/netfilter/xt_set.c +++ b/net/netfilter/xt_set.c @@ -372,8 +372,8 @@ set_target_v2(struct sk_buff *skb, const struct xt_action_param *par) /* Normalize to fit into jiffies */ if (add_opt.ext.timeout != IPSET_NO_TIMEOUT && - add_opt.ext.timeout > UINT_MAX / MSEC_PER_SEC) - add_opt.ext.timeout = UINT_MAX / MSEC_PER_SEC; + add_opt.ext.timeout > IPSET_MAX_TIMEOUT) + add_opt.ext.timeout = IPSET_MAX_TIMEOUT; if (info->add_set.index != IPSET_INVALID_ID) ip_set_add(info->add_set.index, skb, par, &add_opt); if (info->del_set.index != IPSET_INVALID_ID) @@ -407,8 +407,8 @@ set_target_v3(struct sk_buff *skb, const struct xt_action_param *par) /* Normalize to fit into jiffies */ if (add_opt.ext.timeout != IPSET_NO_TIMEOUT && - add_opt.ext.timeout > UINT_MAX / MSEC_PER_SEC) - add_opt.ext.timeout = UINT_MAX / MSEC_PER_SEC; + add_opt.ext.timeout > IPSET_MAX_TIMEOUT) + add_opt.ext.timeout = IPSET_MAX_TIMEOUT; if (info->add_set.index != IPSET_INVALID_ID) ip_set_add(info->add_set.index, skb, par, &add_opt); if (info->del_set.index != IPSET_INVALID_ID) From cbdebe481a14b42c45aa9f4ceb5ff19b55de2c57 Mon Sep 17 00:00:00 2001 From: Florent Fourcot Date: Mon, 4 Jun 2018 16:51:19 +0200 Subject: [PATCH 4/4] netfilter: ipset: forbid family for hash:mac sets Userspace `ipset` command forbids family option for hash:mac type: ipset create test hash:mac family inet4 ipset v6.30: Unknown argument: `family' However, this check is not done in kernel itself. When someone use external netlink applications (pyroute2 python library for example), one can create hash:mac with invalid family and inconsistant results from userspace (`ipset` command cannot read set content anymore). This patch enforce the logic in kernel, and forbids insertion of hash:mac with a family set. Since IP_SET_PROTO_UNDEF is defined only for hash:mac, this patch has no impact on other hash:* sets Signed-off-by: Florent Fourcot Signed-off-by: Victorien Molle Signed-off-by: Jozsef Kadlecsik --- net/netfilter/ipset/ip_set_hash_gen.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h index bbad940c01373..8a33dac4e8058 100644 --- a/net/netfilter/ipset/ip_set_hash_gen.h +++ b/net/netfilter/ipset/ip_set_hash_gen.h @@ -1234,7 +1234,10 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, pr_debug("Create set %s with family %s\n", set->name, set->family == NFPROTO_IPV4 ? "inet" : "inet6"); -#ifndef IP_SET_PROTO_UNDEF +#ifdef IP_SET_PROTO_UNDEF + if (set->family != NFPROTO_UNSPEC) + return -IPSET_ERR_INVALID_FAMILY; +#else if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) return -IPSET_ERR_INVALID_FAMILY; #endif