浏览代码

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>
Houcheng Lin 10 年之前
父节点
当前提交
b51d3fa364
共有 1 个文件被更改,包括 8 次插入9 次删除
  1. 8 9
      net/netfilter/nfnetlink_log.c

+ 8 - 9
net/netfilter/nfnetlink_log.c

@@ -346,26 +346,25 @@ nfulnl_alloc_skb(struct net *net, u32 peer_portid, unsigned int inst_size,
 	return skb;
 	return skb;
 }
 }
 
 
-static int
+static void
 __nfulnl_send(struct nfulnl_instance *inst)
 __nfulnl_send(struct nfulnl_instance *inst)
 {
 {
-	int status = -1;
-
 	if (inst->qlen > 1) {
 	if (inst->qlen > 1) {
 		struct nlmsghdr *nlh = nlmsg_put(inst->skb, 0, 0,
 		struct nlmsghdr *nlh = nlmsg_put(inst->skb, 0, 0,
 						 NLMSG_DONE,
 						 NLMSG_DONE,
 						 sizeof(struct nfgenmsg),
 						 sizeof(struct nfgenmsg),
 						 0);
 						 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;
 			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->qlen = 0;
 	inst->skb = NULL;
 	inst->skb = NULL;
-out:
-	return status;
 }
 }
 
 
 static void
 static void