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 your net tree,
they are:

1) Don't pick fixed hash implementation for NFT_SET_EVAL sets, otherwise
userspace hits EOPNOTSUPP with valid rules using the meter statement,
from Florian Westphal.

2) If you send a batch that flushes the existing ruleset (that contains
a NAT chain) and the new ruleset definition comes with a new NAT
chain, don't bogusly hit EBUSY. Also from Florian.

3) Missing netlink policy attribute validation, from Florian.

4) Detach conntrack template from skbuff if IP_NODEFRAG is set on,
from Paolo Abeni.

5) Cache device names in flowtable object, otherwise we may end up
walking over devices going aways given no rtnl_lock is held.

6) Fix incorrect net_device ingress with ingress hooks.

7) Fix crash when trying to read more data than available in UDP
packets from the nf_socket infrastructure, from Subash.
====================

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

+109 -29
+4
include/net/netfilter/nf_tables.h
··· 1068 1068 int nft_register_obj(struct nft_object_type *obj_type); 1069 1069 void nft_unregister_obj(struct nft_object_type *obj_type); 1070 1070 1071 + #define NFT_FLOWTABLE_DEVICE_MAX 8 1072 + 1071 1073 /** 1072 1074 * struct nft_flowtable - nf_tables flow table 1073 1075 * ··· 1082 1080 * @genmask: generation mask 1083 1081 * @use: number of references to this flow table 1084 1082 * @handle: unique object handle 1083 + * @dev_name: array of device names 1085 1084 * @data: rhashtable and garbage collector 1086 1085 * @ops: array of hooks 1087 1086 */ ··· 1096 1093 u32 genmask:2, 1097 1094 use:30; 1098 1095 u64 handle; 1096 + char *dev_name[NFT_FLOWTABLE_DEVICE_MAX]; 1099 1097 /* runtime data below here */ 1100 1098 struct nf_hook_ops *ops ____cacheline_aligned; 1101 1099 struct nf_flowtable data;
+13 -1
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
··· 154 154 struct sk_buff *skb, 155 155 const struct nf_hook_state *state) 156 156 { 157 - if (ip_is_fragment(ip_hdr(skb))) /* IP_NODEFRAG setsockopt set */ 157 + if (ip_is_fragment(ip_hdr(skb))) { /* IP_NODEFRAG setsockopt set */ 158 + enum ip_conntrack_info ctinfo; 159 + struct nf_conn *tmpl; 160 + 161 + tmpl = nf_ct_get(skb, &ctinfo); 162 + if (tmpl && nf_ct_is_template(tmpl)) { 163 + /* when skipping ct, clear templates to avoid fooling 164 + * later targets/matches 165 + */ 166 + skb->_nfct = 0; 167 + nf_ct_put(tmpl); 168 + } 158 169 return NF_ACCEPT; 170 + } 159 171 160 172 return nf_conntrack_in(state->net, PF_INET, state->hook, skb); 161 173 }
+4 -2
net/ipv4/netfilter/nf_socket_ipv4.c
··· 108 108 int doff = 0; 109 109 110 110 if (iph->protocol == IPPROTO_UDP || iph->protocol == IPPROTO_TCP) { 111 - struct udphdr _hdr, *hp; 111 + struct tcphdr _hdr; 112 + struct udphdr *hp; 112 113 113 114 hp = skb_header_pointer(skb, ip_hdrlen(skb), 114 - sizeof(_hdr), &_hdr); 115 + iph->protocol == IPPROTO_UDP ? 116 + sizeof(*hp) : sizeof(_hdr), &_hdr); 115 117 if (hp == NULL) 116 118 return NULL; 117 119
+4 -2
net/ipv6/netfilter/nf_socket_ipv6.c
··· 116 116 } 117 117 118 118 if (tproto == IPPROTO_UDP || tproto == IPPROTO_TCP) { 119 - struct udphdr _hdr, *hp; 119 + struct tcphdr _hdr; 120 + struct udphdr *hp; 120 121 121 - hp = skb_header_pointer(skb, thoff, sizeof(_hdr), &_hdr); 122 + hp = skb_header_pointer(skb, thoff, tproto == IPPROTO_UDP ? 123 + sizeof(*hp) : sizeof(_hdr), &_hdr); 122 124 if (hp == NULL) 123 125 return NULL; 124 126
+83 -23
net/netfilter/nf_tables_api.c
··· 74 74 kfree(trans); 75 75 } 76 76 77 + /* removal requests are queued in the commit_list, but not acted upon 78 + * until after all new rules are in place. 79 + * 80 + * Therefore, nf_register_net_hook(net, &nat_hook) runs before pending 81 + * nf_unregister_net_hook(). 82 + * 83 + * nf_register_net_hook thus fails if a nat hook is already in place 84 + * even if the conflicting hook is about to be removed. 85 + * 86 + * If collision is detected, search commit_log for DELCHAIN matching 87 + * the new nat hooknum; if we find one collision is temporary: 88 + * 89 + * Either transaction is aborted (new/colliding hook is removed), or 90 + * transaction is committed (old hook is removed). 91 + */ 92 + static bool nf_tables_allow_nat_conflict(const struct net *net, 93 + const struct nf_hook_ops *ops) 94 + { 95 + const struct nft_trans *trans; 96 + bool ret = false; 97 + 98 + if (!ops->nat_hook) 99 + return false; 100 + 101 + list_for_each_entry(trans, &net->nft.commit_list, list) { 102 + const struct nf_hook_ops *pending_ops; 103 + const struct nft_chain *pending; 104 + 105 + if (trans->msg_type != NFT_MSG_NEWCHAIN && 106 + trans->msg_type != NFT_MSG_DELCHAIN) 107 + continue; 108 + 109 + pending = trans->ctx.chain; 110 + if (!nft_is_base_chain(pending)) 111 + continue; 112 + 113 + pending_ops = &nft_base_chain(pending)->ops; 114 + if (pending_ops->nat_hook && 115 + pending_ops->pf == ops->pf && 116 + pending_ops->hooknum == ops->hooknum) { 117 + /* other hook registration already pending? */ 118 + if (trans->msg_type == NFT_MSG_NEWCHAIN) 119 + return false; 120 + 121 + ret = true; 122 + } 123 + } 124 + 125 + return ret; 126 + } 127 + 77 128 static int nf_tables_register_hook(struct net *net, 78 129 const struct nft_table *table, 79 130 struct nft_chain *chain) 80 131 { 132 + struct nf_hook_ops *ops; 133 + int ret; 134 + 81 135 if (table->flags & NFT_TABLE_F_DORMANT || 82 136 !nft_is_base_chain(chain)) 83 137 return 0; 84 138 85 - return nf_register_net_hook(net, &nft_base_chain(chain)->ops); 139 + ops = &nft_base_chain(chain)->ops; 140 + ret = nf_register_net_hook(net, ops); 141 + if (ret == -EBUSY && nf_tables_allow_nat_conflict(net, ops)) { 142 + ops->nat_hook = false; 143 + ret = nf_register_net_hook(net, ops); 144 + ops->nat_hook = true; 145 + } 146 + 147 + return ret; 86 148 } 87 149 88 150 static void nf_tables_unregister_hook(struct net *net, ··· 1288 1226 free_percpu(basechain->stats); 1289 1227 if (basechain->stats) 1290 1228 static_branch_dec(&nft_counters_enabled); 1291 - if (basechain->ops.dev != NULL) 1292 - dev_put(basechain->ops.dev); 1293 1229 kfree(chain->name); 1294 1230 kfree(basechain); 1295 1231 } else { ··· 1354 1294 } 1355 1295 1356 1296 nla_strlcpy(ifname, ha[NFTA_HOOK_DEV], IFNAMSIZ); 1357 - dev = dev_get_by_name(net, ifname); 1297 + dev = __dev_get_by_name(net, ifname); 1358 1298 if (!dev) { 1359 1299 module_put(type->owner); 1360 1300 return -ENOENT; ··· 1371 1311 static void nft_chain_release_hook(struct nft_chain_hook *hook) 1372 1312 { 1373 1313 module_put(hook->type->owner); 1374 - if (hook->dev != NULL) 1375 - dev_put(hook->dev); 1376 1314 } 1377 1315 1378 1316 static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, ··· 1969 1911 [NFTA_RULE_POSITION] = { .type = NLA_U64 }, 1970 1912 [NFTA_RULE_USERDATA] = { .type = NLA_BINARY, 1971 1913 .len = NFT_USERDATA_MAXLEN }, 1914 + [NFTA_RULE_ID] = { .type = NLA_U32 }, 1972 1915 }; 1973 1916 1974 1917 static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net, ··· 2505 2446 2506 2447 static bool nft_set_ops_candidate(const struct nft_set_ops *ops, u32 flags) 2507 2448 { 2449 + if ((flags & NFT_SET_EVAL) && !ops->update) 2450 + return false; 2451 + 2508 2452 return (flags & ops->features) == (flags & NFT_SET_FEATURES); 2509 2453 } 2510 2454 ··· 2572 2510 if (est.space == best.space && 2573 2511 est.lookup < best.lookup) 2574 2512 break; 2575 - } else if (est.size < best.size) { 2513 + } else if (est.size < best.size || !bops) { 2576 2514 break; 2577 2515 } 2578 2516 continue; ··· 3377 3315 [NFTA_SET_ELEM_TIMEOUT] = { .type = NLA_U64 }, 3378 3316 [NFTA_SET_ELEM_USERDATA] = { .type = NLA_BINARY, 3379 3317 .len = NFT_USERDATA_MAXLEN }, 3318 + [NFTA_SET_ELEM_EXPR] = { .type = NLA_NESTED }, 3319 + [NFTA_SET_ELEM_OBJREF] = { .type = NLA_STRING }, 3380 3320 }; 3381 3321 3382 3322 static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX + 1] = { ··· 4928 4864 return ERR_PTR(-ENOENT); 4929 4865 } 4930 4866 4931 - #define NFT_FLOWTABLE_DEVICE_MAX 8 4932 - 4933 4867 static int nf_tables_parse_devices(const struct nft_ctx *ctx, 4934 4868 const struct nlattr *attr, 4935 4869 struct net_device *dev_array[], int *len) ··· 4944 4882 } 4945 4883 4946 4884 nla_strlcpy(ifname, tmp, IFNAMSIZ); 4947 - dev = dev_get_by_name(ctx->net, ifname); 4885 + dev = __dev_get_by_name(ctx->net, ifname); 4948 4886 if (!dev) { 4949 4887 err = -ENOENT; 4950 4888 goto err1; ··· 5000 4938 err = nf_tables_parse_devices(ctx, tb[NFTA_FLOWTABLE_HOOK_DEVS], 5001 4939 dev_array, &n); 5002 4940 if (err < 0) 5003 - goto err1; 4941 + return err; 5004 4942 5005 4943 ops = kzalloc(sizeof(struct nf_hook_ops) * n, GFP_KERNEL); 5006 - if (!ops) { 5007 - err = -ENOMEM; 5008 - goto err1; 5009 - } 4944 + if (!ops) 4945 + return -ENOMEM; 5010 4946 5011 4947 flowtable->hooknum = hooknum; 5012 4948 flowtable->priority = priority; ··· 5018 4958 flowtable->ops[i].priv = &flowtable->data.rhashtable; 5019 4959 flowtable->ops[i].hook = flowtable->data.type->hook; 5020 4960 flowtable->ops[i].dev = dev_array[i]; 4961 + flowtable->dev_name[i] = kstrdup(dev_array[i]->name, 4962 + GFP_KERNEL); 5021 4963 } 5022 - 5023 - err = 0; 5024 - err1: 5025 - for (i = 0; i < n; i++) 5026 - dev_put(dev_array[i]); 5027 4964 5028 4965 return err; 5029 4966 } ··· 5192 5135 err5: 5193 5136 i = flowtable->ops_len; 5194 5137 err4: 5195 - for (k = i - 1; k >= 0; k--) 5138 + for (k = i - 1; k >= 0; k--) { 5139 + kfree(flowtable->dev_name[k]); 5196 5140 nf_unregister_net_hook(net, &flowtable->ops[k]); 5141 + } 5197 5142 5198 5143 kfree(flowtable->ops); 5199 5144 err3: ··· 5285 5226 goto nla_put_failure; 5286 5227 5287 5228 for (i = 0; i < flowtable->ops_len; i++) { 5288 - if (flowtable->ops[i].dev && 5229 + if (flowtable->dev_name[i][0] && 5289 5230 nla_put_string(skb, NFTA_DEVICE_NAME, 5290 - flowtable->ops[i].dev->name)) 5231 + flowtable->dev_name[i])) 5291 5232 goto nla_put_failure; 5292 5233 } 5293 5234 nla_nest_end(skb, nest_devs); ··· 5529 5470 continue; 5530 5471 5531 5472 nf_unregister_net_hook(dev_net(dev), &flowtable->ops[i]); 5473 + flowtable->dev_name[i][0] = '\0'; 5532 5474 flowtable->ops[i].dev = NULL; 5533 5475 break; 5534 5476 }
+1 -1
net/netfilter/nft_set_hash.c
··· 674 674 nft_hash_select_ops(const struct nft_ctx *ctx, const struct nft_set_desc *desc, 675 675 u32 flags) 676 676 { 677 - if (desc->size && !(flags & NFT_SET_TIMEOUT)) { 677 + if (desc->size && !(flags & (NFT_SET_EVAL | NFT_SET_TIMEOUT))) { 678 678 switch (desc->klen) { 679 679 case 4: 680 680 return &nft_hash_fast_ops;