Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf

Pablo Neira Ayuso says:

====================
Netfilter fixes for net

The following patchset contains Netfilter fixes for net:

1) Postpone chain policy update to drop after transaction is complete,
from Florian Westphal.

2) Add entry to flowtable after confirmation to fix UDP flows with
packets going in one single direction.

3) Reference count leak in dst object, from Taehee Yoo.

4) Check for TTL field in flowtable datapath, from Taehee Yoo.

5) Fix h323 conntrack helper due to incorrect boundary check,
from Jakub Jankowski.

6) Fix incorrect rcu dereference when fetching basechain stats,
from Florian Westphal.

7) Missing error check when adding new entries to flowtable,
from Taehee Yoo.

8) Use version field in nfnetlink message to honor the nfgen_family
field, from Kristian Evensen.

9) Remove incorrect configuration check for CONFIG_NF_CONNTRACK_IPV6,
from Subash Abhinov Kasiviswanathan.

10) Prevent dying entries from being added to the flowtable,
from Taehee Yoo.

11) Don't hit WARN_ON() with malformed blob in ebtables with
trailing data after last rule, reported by syzbot, patch
from Florian Westphal.

12) Remove NFT_CT_TIMEOUT enumeration, never used in the kernel
code.

13) Fix incorrect definition for NFT_LOGLEVEL_MAX, from Florian
Westphal.

This batch comes with a conflict that can be fixed with this patch:

diff --cc include/uapi/linux/netfilter/nf_tables.h
index 7bdb234f3d8c,f0cf7b0f4f35..505393c6e959
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@@ -966,6 -966,8 +966,7 @@@ enum nft_socket_keys
* @NFT_CT_DST_IP: conntrack layer 3 protocol destination (IPv4 address)
* @NFT_CT_SRC_IP6: conntrack layer 3 protocol source (IPv6 address)
* @NFT_CT_DST_IP6: conntrack layer 3 protocol destination (IPv6 address)
- * @NFT_CT_TIMEOUT: connection tracking timeout policy assigned to conntrack
+ * @NFT_CT_ID: conntrack id
*/
enum nft_ct_keys {
NFT_CT_STATE,
@@@ -991,6 -993,8 +992,7 @@@
NFT_CT_DST_IP,
NFT_CT_SRC_IP6,
NFT_CT_DST_IP6,
- NFT_CT_TIMEOUT,
+ NFT_CT_ID,
__NFT_CT_MAX
};
#define NFT_CT_MAX (__NFT_CT_MAX - 1)

That replaces the unused NFT_CT_TIMEOUT definition by NFT_CT_ID. If you prefer,
I can also solve this conflict here, just let me know.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+89 -37
+1 -3
include/uapi/linux/netfilter/nf_tables.h
··· 966 966 * @NFT_CT_DST_IP: conntrack layer 3 protocol destination (IPv4 address) 967 967 * @NFT_CT_SRC_IP6: conntrack layer 3 protocol source (IPv6 address) 968 968 * @NFT_CT_DST_IP6: conntrack layer 3 protocol destination (IPv6 address) 969 - * @NFT_CT_TIMEOUT: connection tracking timeout policy assigned to conntrack 970 969 * @NFT_CT_ID: conntrack id 971 970 */ 972 971 enum nft_ct_keys { ··· 992 993 NFT_CT_DST_IP, 993 994 NFT_CT_SRC_IP6, 994 995 NFT_CT_DST_IP6, 995 - NFT_CT_TIMEOUT, 996 996 NFT_CT_ID, 997 997 __NFT_CT_MAX 998 998 }; ··· 1136 1138 NFT_LOGLEVEL_AUDIT, 1137 1139 __NFT_LOGLEVEL_MAX 1138 1140 }; 1139 - #define NFT_LOGLEVEL_MAX (__NFT_LOGLEVEL_MAX + 1) 1141 + #define NFT_LOGLEVEL_MAX (__NFT_LOGLEVEL_MAX - 1) 1140 1142 1141 1143 /** 1142 1144 * enum nft_queue_attributes - nf_tables queue expression netlink attributes
+3 -1
net/bridge/netfilter/ebtables.c
··· 2153 2153 if (ret < 0) 2154 2154 return ret; 2155 2155 2156 - WARN_ON(size_remaining); 2156 + if (size_remaining) 2157 + return -EINVAL; 2158 + 2157 2159 return state->buf_kern_offset; 2158 2160 } 2159 2161
+1 -1
net/netfilter/nf_conntrack_h323_asn1.c
··· 172 172 if (bits % BITS_PER_BYTE > 0) 173 173 bytes++; 174 174 175 - if (*bs->cur + bytes > *bs->end) 175 + if (bs->cur + bytes > bs->end) 176 176 return 1; 177 177 178 178 return 0;
+3 -8
net/netfilter/nf_conntrack_h323_main.c
··· 748 748 } 749 749 break; 750 750 } 751 - #if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6) 751 + #if IS_ENABLED(CONFIG_IPV6) 752 752 case AF_INET6: { 753 - const struct nf_ipv6_ops *v6ops; 754 753 struct rt6_info *rt1, *rt2; 755 754 struct flowi6 fl1, fl2; 756 - 757 - v6ops = nf_get_ipv6_ops(); 758 - if (!v6ops) 759 - return 0; 760 755 761 756 memset(&fl1, 0, sizeof(fl1)); 762 757 fl1.daddr = src->in6; 763 758 764 759 memset(&fl2, 0, sizeof(fl2)); 765 760 fl2.daddr = dst->in6; 766 - if (!v6ops->route(net, (struct dst_entry **)&rt1, 761 + if (!nf_ip6_route(net, (struct dst_entry **)&rt1, 767 762 flowi6_to_flowi(&fl1), false)) { 768 - if (!v6ops->route(net, (struct dst_entry **)&rt2, 763 + if (!nf_ip6_route(net, (struct dst_entry **)&rt2, 769 764 flowi6_to_flowi(&fl2), false)) { 770 765 if (ipv6_addr_equal(rt6_nexthop(rt1, &fl1.daddr), 771 766 rt6_nexthop(rt2, &fl2.daddr)) &&
+1 -1
net/netfilter/nf_conntrack_netlink.c
··· 1256 1256 struct nf_conntrack_tuple tuple; 1257 1257 struct nf_conn *ct; 1258 1258 struct nfgenmsg *nfmsg = nlmsg_data(nlh); 1259 - u_int8_t u3 = nfmsg->nfgen_family; 1259 + u_int8_t u3 = nfmsg->version ? nfmsg->nfgen_family : AF_UNSPEC; 1260 1260 struct nf_conntrack_zone zone; 1261 1261 int err; 1262 1262
+26 -8
net/netfilter/nf_flow_table_core.c
··· 185 185 186 186 int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow) 187 187 { 188 - flow->timeout = (u32)jiffies; 188 + int err; 189 189 190 - rhashtable_insert_fast(&flow_table->rhashtable, 191 - &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, 192 - nf_flow_offload_rhash_params); 193 - rhashtable_insert_fast(&flow_table->rhashtable, 194 - &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, 195 - nf_flow_offload_rhash_params); 190 + err = rhashtable_insert_fast(&flow_table->rhashtable, 191 + &flow->tuplehash[0].node, 192 + nf_flow_offload_rhash_params); 193 + if (err < 0) 194 + return err; 195 + 196 + err = rhashtable_insert_fast(&flow_table->rhashtable, 197 + &flow->tuplehash[1].node, 198 + nf_flow_offload_rhash_params); 199 + if (err < 0) { 200 + rhashtable_remove_fast(&flow_table->rhashtable, 201 + &flow->tuplehash[0].node, 202 + nf_flow_offload_rhash_params); 203 + return err; 204 + } 205 + 206 + flow->timeout = (u32)jiffies; 196 207 return 0; 197 208 } 198 209 EXPORT_SYMBOL_GPL(flow_offload_add); ··· 243 232 { 244 233 struct flow_offload_tuple_rhash *tuplehash; 245 234 struct flow_offload *flow; 235 + struct flow_offload_entry *e; 246 236 int dir; 247 237 248 238 tuplehash = rhashtable_lookup(&flow_table->rhashtable, tuple, ··· 254 242 dir = tuplehash->tuple.dir; 255 243 flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); 256 244 if (flow->flags & (FLOW_OFFLOAD_DYING | FLOW_OFFLOAD_TEARDOWN)) 245 + return NULL; 246 + 247 + e = container_of(flow, struct flow_offload_entry, flow); 248 + if (unlikely(nf_ct_is_dying(e->ct))) 257 249 return NULL; 258 250 259 251 return tuplehash; ··· 306 290 static void nf_flow_offload_gc_step(struct flow_offload *flow, void *data) 307 291 { 308 292 struct nf_flowtable *flow_table = data; 293 + struct flow_offload_entry *e; 309 294 310 - if (nf_flow_has_expired(flow) || 295 + e = container_of(flow, struct flow_offload_entry, flow); 296 + if (nf_flow_has_expired(flow) || nf_ct_is_dying(e->ct) || 311 297 (flow->flags & (FLOW_OFFLOAD_DYING | FLOW_OFFLOAD_TEARDOWN))) 312 298 flow_offload_del(flow_table, flow); 313 299 }
+6
net/netfilter/nf_flow_table_ip.c
··· 181 181 iph->protocol != IPPROTO_UDP) 182 182 return -1; 183 183 184 + if (iph->ttl <= 1) 185 + return -1; 186 + 184 187 thoff = iph->ihl * 4; 185 188 if (!pskb_may_pull(skb, thoff + sizeof(*ports))) 186 189 return -1; ··· 409 406 410 407 if (ip6h->nexthdr != IPPROTO_TCP && 411 408 ip6h->nexthdr != IPPROTO_UDP) 409 + return -1; 410 + 411 + if (ip6h->hop_limit <= 1) 412 412 return -1; 413 413 414 414 thoff = sizeof(*ip6h);
+46 -13
net/netfilter/nf_tables_api.c
··· 213 213 return err; 214 214 } 215 215 216 - static int nft_trans_chain_add(struct nft_ctx *ctx, int msg_type) 216 + static struct nft_trans *nft_trans_chain_add(struct nft_ctx *ctx, int msg_type) 217 217 { 218 218 struct nft_trans *trans; 219 219 220 220 trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_chain)); 221 221 if (trans == NULL) 222 - return -ENOMEM; 222 + return ERR_PTR(-ENOMEM); 223 223 224 224 if (msg_type == NFT_MSG_NEWCHAIN) 225 225 nft_activate_next(ctx->net, ctx->chain); 226 226 227 227 list_add_tail(&trans->list, &ctx->net->nft.commit_list); 228 - return 0; 228 + return trans; 229 229 } 230 230 231 231 static int nft_delchain(struct nft_ctx *ctx) 232 232 { 233 - int err; 233 + struct nft_trans *trans; 234 234 235 - err = nft_trans_chain_add(ctx, NFT_MSG_DELCHAIN); 236 - if (err < 0) 237 - return err; 235 + trans = nft_trans_chain_add(ctx, NFT_MSG_DELCHAIN); 236 + if (IS_ERR(trans)) 237 + return PTR_ERR(trans); 238 238 239 239 ctx->table->use--; 240 240 nft_deactivate_next(ctx->net, ctx->chain); 241 241 242 - return err; 242 + return 0; 243 243 } 244 244 245 245 static void nft_rule_expr_activate(const struct nft_ctx *ctx, ··· 1189 1189 u64 pkts, bytes; 1190 1190 int cpu; 1191 1191 1192 + if (!stats) 1193 + return 0; 1194 + 1192 1195 memset(&total, 0, sizeof(total)); 1193 1196 for_each_possible_cpu(cpu) { 1194 1197 cpu_stats = per_cpu_ptr(stats, cpu); ··· 1249 1246 if (nft_is_base_chain(chain)) { 1250 1247 const struct nft_base_chain *basechain = nft_base_chain(chain); 1251 1248 const struct nf_hook_ops *ops = &basechain->ops; 1249 + struct nft_stats __percpu *stats; 1252 1250 struct nlattr *nest; 1253 1251 1254 1252 nest = nla_nest_start_noflag(skb, NFTA_CHAIN_HOOK); ··· 1271 1267 if (nla_put_string(skb, NFTA_CHAIN_TYPE, basechain->type->name)) 1272 1268 goto nla_put_failure; 1273 1269 1274 - if (rcu_access_pointer(basechain->stats) && 1275 - nft_dump_stats(skb, rcu_dereference(basechain->stats))) 1270 + stats = rcu_dereference_check(basechain->stats, 1271 + lockdep_commit_lock_is_held(net)); 1272 + if (nft_dump_stats(skb, stats)) 1276 1273 goto nla_put_failure; 1277 1274 } 1278 1275 ··· 1620 1615 struct nft_base_chain *basechain; 1621 1616 struct nft_stats __percpu *stats; 1622 1617 struct net *net = ctx->net; 1618 + struct nft_trans *trans; 1623 1619 struct nft_chain *chain; 1624 1620 struct nft_rule **rules; 1625 1621 int err; ··· 1668 1662 ops->dev = hook.dev; 1669 1663 1670 1664 chain->flags |= NFT_BASE_CHAIN; 1671 - basechain->policy = policy; 1665 + basechain->policy = NF_ACCEPT; 1672 1666 } else { 1673 1667 chain = kzalloc(sizeof(*chain), GFP_KERNEL); 1674 1668 if (chain == NULL) ··· 1704 1698 if (err) 1705 1699 goto err2; 1706 1700 1707 - err = nft_trans_chain_add(ctx, NFT_MSG_NEWCHAIN); 1708 - if (err < 0) { 1701 + trans = nft_trans_chain_add(ctx, NFT_MSG_NEWCHAIN); 1702 + if (IS_ERR(trans)) { 1703 + err = PTR_ERR(trans); 1709 1704 rhltable_remove(&table->chains_ht, &chain->rhlhead, 1710 1705 nft_chain_ht_params); 1711 1706 goto err2; 1712 1707 } 1708 + 1709 + nft_trans_chain_policy(trans) = -1; 1710 + if (nft_is_base_chain(chain)) 1711 + nft_trans_chain_policy(trans) = policy; 1713 1712 1714 1713 table->use++; 1715 1714 list_add_tail_rcu(&chain->list, &table->chains); ··· 6321 6310 return 0; 6322 6311 } 6323 6312 6313 + /* a drop policy has to be deferred until all rules have been activated, 6314 + * otherwise a large ruleset that contains a drop-policy base chain will 6315 + * cause all packets to get dropped until the full transaction has been 6316 + * processed. 6317 + * 6318 + * We defer the drop policy until the transaction has been finalized. 6319 + */ 6320 + static void nft_chain_commit_drop_policy(struct nft_trans *trans) 6321 + { 6322 + struct nft_base_chain *basechain; 6323 + 6324 + if (nft_trans_chain_policy(trans) != NF_DROP) 6325 + return; 6326 + 6327 + if (!nft_is_base_chain(trans->ctx.chain)) 6328 + return; 6329 + 6330 + basechain = nft_base_chain(trans->ctx.chain); 6331 + basechain->policy = NF_DROP; 6332 + } 6333 + 6324 6334 static void nft_chain_commit_update(struct nft_trans *trans) 6325 6335 { 6326 6336 struct nft_base_chain *basechain; ··· 6663 6631 nf_tables_chain_notify(&trans->ctx, NFT_MSG_NEWCHAIN); 6664 6632 /* trans destroyed after rcu grace period */ 6665 6633 } else { 6634 + nft_chain_commit_drop_policy(trans); 6666 6635 nft_clear(net, trans->ctx.chain); 6667 6636 nf_tables_chain_notify(&trans->ctx, NFT_MSG_NEWCHAIN); 6668 6637 nft_trans_destroy(trans);
+2 -2
net/netfilter/nft_flow_offload.c
··· 94 94 if (help) 95 95 goto out; 96 96 97 - if (ctinfo == IP_CT_NEW || 98 - ctinfo == IP_CT_RELATED) 97 + if (!nf_ct_is_confirmed(ct)) 99 98 goto out; 100 99 101 100 if (test_and_set_bit(IPS_OFFLOAD_BIT, &ct->status)) ··· 112 113 if (ret < 0) 113 114 goto err_flow_add; 114 115 116 + dst_release(route.tuple[!dir].dst); 115 117 return; 116 118 117 119 err_flow_add: