summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHoucheng Lin <houcheng@gmail.com>2014-10-23 10:36:08 +0200
committerJiri Slaby <jslaby@suse.cz>2014-11-19 18:38:25 +0100
commit37bdac282ed1d1f2641ba9063f50cf42bcb94dc4 (patch)
tree5e9370f29d91b8dce1dded31c968d84864c7be15
parent45ebf3641319166e3a6c468eeeac48aa4d6d567d (diff)
downloadlwn-37bdac282ed1d1f2641ba9063f50cf42bcb94dc4.tar.gz
lwn-37bdac282ed1d1f2641ba9063f50cf42bcb94dc4.zip
netfilter: nf_log: release skbuff on nlmsg put failure
commit b51d3fa364885a2c1e1668f88776c67c95291820 upstream. 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> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
-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 39010fc1e9c0..09172d7abee2 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -348,26 +348,25 @@ nfulnl_alloc_skb(u32 peer_portid, unsigned int inst_size, unsigned int pkt_size)
return skb;
}
-static int
+static void
__nfulnl_send(struct nfulnl_instance *inst)
{
- int status = -1;
-
if (inst->qlen > 1) {
struct nlmsghdr *nlh = nlmsg_put(inst->skb, 0, 0,
NLMSG_DONE,
sizeof(struct nfgenmsg),
0);
- if (!nlh)
+ if (WARN_ONCE(!nlh, "bad nlskb size: %u, tailroom %d\n",
+ inst->skb->len, skb_tailroom(inst->skb))) {
+ kfree_skb(inst->skb);
goto out;
+ }
}
- status = nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid,
- MSG_DONTWAIT);
-
+ nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid,
+ MSG_DONTWAIT);
+out:
inst->qlen = 0;
inst->skb = NULL;
-out:
- return status;
}
static void