aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-10-27 18:47:40 -0400
committerDavid S. Miller <davem@davemloft.net>2014-10-27 18:47:40 -0400
commit5d26b1f50a610fb28700cdc3446590495a5f607c (patch)
treef937c9e7f4d0eabeed93dce93a21020c1fb164e5 /net
parent93a35f59f1b13a02674877e3efdf07ae47e34052 (diff)
parent7965ee93719921ea5978f331da653dfa2d7b99f5 (diff)
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) Allow to recycle a TCP port in conntrack when the change role from server to client, from Marcelo Leitner. 2) Fix possible off by one access in ip_set_nfnl_get_byindex(), patch from Dan Carpenter. 3) alloc_percpu returns NULL on error, no need for IS_ERR() in nf_tables chain statistic updates. From Sabrina Dubroca. 4) Don't compile ip options in bridge netfilter, this mangles the packet and bridge should not alter layer >= 3 headers when forwarding packets. Patch from Herbert Xu and tested by Florian Westphal. 5) Account the final NLMSG_DONE message when calculating the size of the nflog netlink batches. Patch from Florian Westphal. 6) Fix a possible netlink attribute length overflow with large packets. Again from Florian Westphal. 7) Release the skbuff if nfnetlink_log fails to put the final NLMSG_DONE message. This fixes a leak on error. This shouldn't ever happen though, otherwise this means we miscalculate the netlink batch size, so spot a warning if this ever happens so we can track down the problem. This patch from Houcheng Lin. 8) Look at the right list when recycling targets in the nft_compat, patch from Arturo Borrero. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_netfilter.c24
-rw-r--r--net/netfilter/ipset/ip_set_core.c2
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c4
-rw-r--r--net/netfilter/nf_tables_api.c4
-rw-r--r--net/netfilter/nfnetlink_log.c31
-rw-r--r--net/netfilter/nft_compat.c2
6 files changed, 27 insertions, 40 deletions
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 1bada53bb195..1a4f32c09ad5 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -192,7 +192,6 @@ static inline void nf_bridge_save_header(struct sk_buff *skb)
192 192
193static int br_parse_ip_options(struct sk_buff *skb) 193static int br_parse_ip_options(struct sk_buff *skb)
194{ 194{
195 struct ip_options *opt;
196 const struct iphdr *iph; 195 const struct iphdr *iph;
197 struct net_device *dev = skb->dev; 196 struct net_device *dev = skb->dev;
198 u32 len; 197 u32 len;
@@ -201,7 +200,6 @@ static int br_parse_ip_options(struct sk_buff *skb)
201 goto inhdr_error; 200 goto inhdr_error;
202 201
203 iph = ip_hdr(skb); 202 iph = ip_hdr(skb);
204 opt = &(IPCB(skb)->opt);
205 203
206 /* Basic sanity checks */ 204 /* Basic sanity checks */
207 if (iph->ihl < 5 || iph->version != 4) 205 if (iph->ihl < 5 || iph->version != 4)
@@ -227,23 +225,11 @@ static int br_parse_ip_options(struct sk_buff *skb)
227 } 225 }
228 226
229 memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); 227 memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
230 if (iph->ihl == 5) 228 /* We should really parse IP options here but until
231 return 0; 229 * somebody who actually uses IP options complains to
232 230 * us we'll just silently ignore the options because
233 opt->optlen = iph->ihl*4 - sizeof(struct iphdr); 231 * we're lazy!
234 if (ip_options_compile(dev_net(dev), opt, skb)) 232 */
235 goto inhdr_error;
236
237 /* Check correct handling of SRR option */
238 if (unlikely(opt->srr)) {
239 struct in_device *in_dev = __in_dev_get_rcu(dev);
240 if (in_dev && !IN_DEV_SOURCE_ROUTE(in_dev))
241 goto drop;
242
243 if (ip_options_rcv_srr(skb))
244 goto drop;
245 }
246
247 return 0; 233 return 0;
248 234
249inhdr_error: 235inhdr_error:
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index 912e5a05b79d..86f9d76b1464 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -659,7 +659,7 @@ ip_set_nfnl_get_byindex(struct net *net, ip_set_id_t index)
659 struct ip_set *set; 659 struct ip_set *set;
660 struct ip_set_net *inst = ip_set_pernet(net); 660 struct ip_set_net *inst = ip_set_pernet(net);
661 661
662 if (index > inst->ip_set_max) 662 if (index >= inst->ip_set_max)
663 return IPSET_INVALID_ID; 663 return IPSET_INVALID_ID;
664 664
665 nfnl_lock(NFNL_SUBSYS_IPSET); 665 nfnl_lock(NFNL_SUBSYS_IPSET);
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 44d1ea32570a..d87b6423ffb2 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -213,7 +213,7 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
213 { 213 {
214/* REPLY */ 214/* REPLY */
215/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ 215/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */
216/*syn*/ { sIV, sS2, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sS2 }, 216/*syn*/ { sIV, sS2, sIV, sIV, sIV, sIV, sIV, sSS, sIV, sS2 },
217/* 217/*
218 * sNO -> sIV Never reached. 218 * sNO -> sIV Never reached.
219 * sSS -> sS2 Simultaneous open 219 * sSS -> sS2 Simultaneous open
@@ -223,7 +223,7 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
223 * sFW -> sIV 223 * sFW -> sIV
224 * sCW -> sIV 224 * sCW -> sIV
225 * sLA -> sIV 225 * sLA -> sIV
226 * sTW -> sIV Reopened connection, but server may not do it. 226 * sTW -> sSS Reopened connection, but server may have switched role
227 * sCL -> sIV 227 * sCL -> sIV
228 */ 228 */
229/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ 229/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 65eb2a1160d5..11ab4b078f3b 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -1328,10 +1328,10 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
1328 basechain->stats = stats; 1328 basechain->stats = stats;
1329 } else { 1329 } else {
1330 stats = netdev_alloc_pcpu_stats(struct nft_stats); 1330 stats = netdev_alloc_pcpu_stats(struct nft_stats);
1331 if (IS_ERR(stats)) { 1331 if (stats == NULL) {
1332 module_put(type->owner); 1332 module_put(type->owner);
1333 kfree(basechain); 1333 kfree(basechain);
1334 return PTR_ERR(stats); 1334 return -ENOMEM;
1335 } 1335 }
1336 rcu_assign_pointer(basechain->stats, stats); 1336 rcu_assign_pointer(basechain->stats, stats);
1337 } 1337 }
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index b1e3a0579416..5f1be5ba3559 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -43,7 +43,8 @@
43#define NFULNL_NLBUFSIZ_DEFAULT NLMSG_GOODSIZE 43#define NFULNL_NLBUFSIZ_DEFAULT NLMSG_GOODSIZE
44#define NFULNL_TIMEOUT_DEFAULT 100 /* every second */ 44#define NFULNL_TIMEOUT_DEFAULT 100 /* every second */
45#define NFULNL_QTHRESH_DEFAULT 100 /* 100 packets */ 45#define NFULNL_QTHRESH_DEFAULT 100 /* 100 packets */
46#define NFULNL_COPY_RANGE_MAX 0xFFFF /* max packet size is limited by 16-bit struct nfattr nfa_len field */ 46/* max packet size is limited by 16-bit struct nfattr nfa_len field */
47#define NFULNL_COPY_RANGE_MAX (0xFFFF - NLA_HDRLEN)
47 48
48#define PRINTR(x, args...) do { if (net_ratelimit()) \ 49#define PRINTR(x, args...) do { if (net_ratelimit()) \
49 printk(x, ## args); } while (0); 50 printk(x, ## args); } while (0);
@@ -252,6 +253,8 @@ nfulnl_set_mode(struct nfulnl_instance *inst, u_int8_t mode,
252 253
253 case NFULNL_COPY_PACKET: 254 case NFULNL_COPY_PACKET:
254 inst->copy_mode = mode; 255 inst->copy_mode = mode;
256 if (range == 0)
257 range = NFULNL_COPY_RANGE_MAX;
255 inst->copy_range = min_t(unsigned int, 258 inst->copy_range = min_t(unsigned int,
256 range, NFULNL_COPY_RANGE_MAX); 259 range, NFULNL_COPY_RANGE_MAX);
257 break; 260 break;
@@ -343,26 +346,25 @@ nfulnl_alloc_skb(struct net *net, u32 peer_portid, unsigned int inst_size,
343 return skb; 346 return skb;
344} 347}
345 348
346static int 349static void
347__nfulnl_send(struct nfulnl_instance *inst) 350__nfulnl_send(struct nfulnl_instance *inst)
348{ 351{
349 int status = -1;
350
351 if (inst->qlen > 1) { 352 if (inst->qlen > 1) {
352 struct nlmsghdr *nlh = nlmsg_put(inst->skb, 0, 0, 353 struct nlmsghdr *nlh = nlmsg_put(inst->skb, 0, 0,
353 NLMSG_DONE, 354 NLMSG_DONE,
354 sizeof(struct nfgenmsg), 355 sizeof(struct nfgenmsg),
355 0); 356 0);
356 if (!nlh) 357 if (WARN_ONCE(!nlh, "bad nlskb size: %u, tailroom %d\n",
358 inst->skb->len, skb_tailroom(inst->skb))) {
359 kfree_skb(inst->skb);
357 goto out; 360 goto out;
361 }
358 } 362 }
359 status = nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid, 363 nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid,
360 MSG_DONTWAIT); 364 MSG_DONTWAIT);
361 365out:
362 inst->qlen = 0; 366 inst->qlen = 0;
363 inst->skb = NULL; 367 inst->skb = NULL;
364out:
365 return status;
366} 368}
367 369
368static void 370static void
@@ -649,7 +651,8 @@ nfulnl_log_packet(struct net *net,
649 + nla_total_size(sizeof(u_int32_t)) /* gid */ 651 + nla_total_size(sizeof(u_int32_t)) /* gid */
650 + nla_total_size(plen) /* prefix */ 652 + nla_total_size(plen) /* prefix */
651 + nla_total_size(sizeof(struct nfulnl_msg_packet_hw)) 653 + nla_total_size(sizeof(struct nfulnl_msg_packet_hw))
652 + nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp)); 654 + nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp))
655 + nla_total_size(sizeof(struct nfgenmsg)); /* NLMSG_DONE */
653 656
654 if (in && skb_mac_header_was_set(skb)) { 657 if (in && skb_mac_header_was_set(skb)) {
655 size += nla_total_size(skb->dev->hard_header_len) 658 size += nla_total_size(skb->dev->hard_header_len)
@@ -678,8 +681,7 @@ nfulnl_log_packet(struct net *net,
678 break; 681 break;
679 682
680 case NFULNL_COPY_PACKET: 683 case NFULNL_COPY_PACKET:
681 if (inst->copy_range == 0 684 if (inst->copy_range > skb->len)
682 || inst->copy_range > skb->len)
683 data_len = skb->len; 685 data_len = skb->len;
684 else 686 else
685 data_len = inst->copy_range; 687 data_len = inst->copy_range;
@@ -692,8 +694,7 @@ nfulnl_log_packet(struct net *net,
692 goto unlock_and_release; 694 goto unlock_and_release;
693 } 695 }
694 696
695 if (inst->skb && 697 if (inst->skb && size > skb_tailroom(inst->skb)) {
696 size > skb_tailroom(inst->skb) - sizeof(struct nfgenmsg)) {
697 /* either the queue len is too high or we don't have 698 /* either the queue len is too high or we don't have
698 * enough room in the skb left. flush to userspace. */ 699 * enough room in the skb left. flush to userspace. */
699 __nfulnl_flush(inst); 700 __nfulnl_flush(inst);
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c
index 0480f57a4eb6..9d6d6f60a80f 100644
--- a/net/netfilter/nft_compat.c
+++ b/net/netfilter/nft_compat.c
@@ -672,7 +672,7 @@ nft_target_select_ops(const struct nft_ctx *ctx,
672 family = ctx->afi->family; 672 family = ctx->afi->family;
673 673
674 /* Re-use the existing target if it's already loaded. */ 674 /* Re-use the existing target if it's already loaded. */
675 list_for_each_entry(nft_target, &nft_match_list, head) { 675 list_for_each_entry(nft_target, &nft_target_list, head) {
676 struct xt_target *target = nft_target->ops.data; 676 struct xt_target *target = nft_target->ops.data;
677 677
678 if (strcmp(target->name, tg_name) == 0 && 678 if (strcmp(target->name, tg_name) == 0 &&