From patchwork Mon May 20 13:00:42 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pablo Neira Ayuso X-Patchwork-Id: 245033 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 887ED2C007E for ; Mon, 20 May 2013 23:00:57 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756145Ab3ETNA4 (ORCPT ); Mon, 20 May 2013 09:00:56 -0400 Received: from mail.us.es ([193.147.175.20]:47772 "EHLO mail.us.es" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755920Ab3ETNAz (ORCPT ); Mon, 20 May 2013 09:00:55 -0400 Received: (qmail 28096 invoked from network); 20 May 2013 15:00:53 +0200 Received: from unknown (HELO us.es) (192.168.2.13) by us.es with SMTP; 20 May 2013 15:00:53 +0200 Received: (qmail 14789 invoked by uid 507); 20 May 2013 13:00:53 -0000 X-Qmail-Scanner-Diagnostics: from 127.0.0.1 by antivirus3 (envelope-from , uid 501) with qmail-scanner-2.10 (clamdscan: 0.97.8/17243. spamassassin: 3.3.2. Clear:RC:1(127.0.0.1):SA:0(-96.4/7.5):. Processed in 1.957244 secs); 20 May 2013 13:00:53 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on antivirus3 X-Spam-Level: X-Spam-Status: No, score=-96.4 required=7.5 tests=BAYES_50, RCVD_IN_BRBL_LASTEXT,RCVD_IN_PBL,RCVD_IN_RP_RNBL,RCVD_IN_SORBS_DUL, RDNS_DYNAMIC,USER_IN_WHITELIST autolearn=disabled version=3.3.2 X-Envelope-From: pablo@netfilter.org Received: from unknown (HELO antivirus3) (127.0.0.1) by us.es with SMTP; 20 May 2013 13:00:51 -0000 Received: from 192.168.1.13 (192.168.1.13) by antivirus3 (F-Secure/fsigk_smtp/410/antivirus3); Mon, 20 May 2013 15:00:51 +0200 (CEST) X-Virus-Status: clean(F-Secure/fsigk_smtp/410/antivirus3) Received: (qmail 5248 invoked from network); 20 May 2013 15:00:51 +0200 Received: from 185.157.76.188.dynamic.jazztel.es (HELO localhost.localdomain) (pneira@us.es@188.76.157.185) by us.es with SMTP; 20 May 2013 15:00:51 +0200 From: Pablo Neira Ayuso To: netfilter-devel@vger.kernel.org Cc: tomasz.bursztyka@linux.intel.com, kaber@trash.net Subject: [RFC 1/2] netfilter: nfnetlink: add commit operation to nfnl_subsystems Date: Mon, 20 May 2013 15:00:42 +0200 Message-Id: <1369054843-14591-1-git-send-email-pablo@netfilter.org> X-Mailer: git-send-email 1.7.10.4 Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org This patch adds the commit operations, that is called after processing a batch composed of several netlink messages. This only allows batches composed of netlink messages going to the same subsystem. Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nfnetlink.c | 73 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 55 insertions(+), 18 deletions(-) diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index ffb92c0..c470123 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -87,11 +87,21 @@ EXPORT_SYMBOL_GPL(nfnetlink_subsys_unregister); static inline const struct nfnetlink_subsystem *nfnetlink_get_subsys(u_int16_t type) { u_int8_t subsys_id = NFNL_SUBSYS_ID(type); + const struct nfnetlink_subsystem *ss; if (subsys_id >= NFNL_SUBSYS_COUNT) return NULL; - return rcu_dereference(subsys_table[subsys_id]); + ss = rcu_dereference(subsys_table[subsys_id]); + if (!ss) { +#ifdef CONFIG_MODULES + rcu_read_unlock(); + request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type)); + rcu_read_lock(); + ss = nfnetlink_get_subsys(type); +#endif + } + return ss; } static inline const struct nfnl_callback * @@ -150,17 +160,8 @@ replay: rcu_read_lock(); ss = nfnetlink_get_subsys(type); if (!ss) { -#ifdef CONFIG_MODULES rcu_read_unlock(); - request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type)); - rcu_read_lock(); - ss = nfnetlink_get_subsys(type); - if (!ss) -#endif - { - rcu_read_unlock(); - return -EINVAL; - } + return -EINVAL; } nc = nfnetlink_find_client(type, ss); @@ -210,22 +211,58 @@ replay: static void nfnetlink_rcv(struct sk_buff *skb) { + unsigned int last_type = 0; + + if (skb->len < nlmsg_total_size(0)) + return; + + /* This is a batch composed of multiple messages */ + if (skb->len != nlmsg_hdr(skb)->nlmsg_len) { + struct nlmsghdr *nlh = nlmsg_hdr(skb); + unsigned int len = 0; + + while (len < skb->len) { + /* We don't allow multiple messages in a batch + * going to different subsystems. + */ + if (last_type && + last_type != NFNL_SUBSYS_ID(nlh->nlmsg_type)) + return netlink_ack(skb, nlh, -EINVAL); + + len += nlh->nlmsg_len; + last_type = NFNL_SUBSYS_ID(nlh->nlmsg_type); + nlh = (struct nlmsghdr *)(skb->data + len); + } + } + netlink_rcv_skb(skb, &nfnetlink_rcv_msg); + + /* Post-processing of this batch, if any. */ + if (last_type) { + struct net *net = sock_net(skb->sk); + const struct nfnetlink_subsystem *ss; + + rcu_read_lock(); + ss = nfnetlink_get_subsys(last_type); + if (!ss) { + rcu_read_unlock(); + return netlink_ack(skb, nlmsg_hdr(skb), -EINVAL); + } + + if (ss->commit) + ss->commit(skb, net); + + rcu_read_unlock(); + } } #ifdef CONFIG_MODULES static void nfnetlink_bind(int group) { - const struct nfnetlink_subsystem *ss; int type = nfnl_group2type[group]; rcu_read_lock(); - ss = nfnetlink_get_subsys(type); - if (!ss) { - rcu_read_unlock(); - request_module("nfnetlink-subsys-%d", type); - return; - } + nfnetlink_get_subsys(type); rcu_read_unlock(); } #endif