aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorHoucheng Lin <houcheng@gmail.com>2014-10-23 04:36:08 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2014-10-24 08:34:11 -0400
commitb51d3fa364885a2c1e1668f88776c67c95291820 (patch)
treeefd04d22d960f11ee69c9d57807850e48c4515af /net
parentc1e7dc91eed0ed1a51c9b814d648db18bf8fc6e9 (diff)
netfilter: nf_log: release skbuff on nlmsg put failure
The kernel should reserve enough room in the skb so that the DONE message can always be appended. However, in case of e.g. new attribute erronously not being size-accounted for, __nfulnl_send() will still try to put next nlmsg into this full skbuf, causing the skb to be stuck forever and blocking delivery of further messages. Fix issue by releasing skb immediately after nlmsg_put error and WARN() so we can track down the cause of such size mismatch. [ fw@strlen.de: add tailroom/len info to WARN ] Signed-off-by: Houcheng Lin <houcheng@gmail.com> Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/nfnetlink_log.c17
1 files changed, 8 insertions, 9 deletions
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 2d02eac35415..5f1be5ba3559 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -346,26 +346,25 @@ nfulnl_alloc_skb(struct net *net, u32 peer_portid, unsigned int inst_size,
346 return skb; 346 return skb;
347} 347}
348 348
349static int 349static void
350__nfulnl_send(struct nfulnl_instance *inst) 350__nfulnl_send(struct nfulnl_instance *inst)
351{ 351{
352 int status = -1;
353
354 if (inst->qlen > 1) { 352 if (inst->qlen > 1) {
355 struct nlmsghdr *nlh = nlmsg_put(inst->skb, 0, 0, 353 struct nlmsghdr *nlh = nlmsg_put(inst->skb, 0, 0,
356 NLMSG_DONE, 354 NLMSG_DONE,
357 sizeof(struct nfgenmsg), 355 sizeof(struct nfgenmsg),
358 0); 356 0);
359 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);
360 goto out; 360 goto out;
361 }
361 } 362 }
362 status = nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid, 363 nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid,
363 MSG_DONTWAIT); 364 MSG_DONTWAIT);
364 365out:
365 inst->qlen = 0; 366 inst->qlen = 0;
366 inst->skb = NULL; 367 inst->skb = NULL;
367out:
368 return status;
369} 368}
370 369
371static void 370static void